Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for bond label in base classes and CJSON #1495

Merged
merged 3 commits into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions avogadro/core/atom.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,13 +380,13 @@ Vector3 AtomTemplate<Molecule_T>::forceVector() const
template <class Molecule_T>
void AtomTemplate<Molecule_T>::setLabel(const std::string& label)
{
m_molecule->setLabel(m_index, label);
m_molecule->setAtomLabel(m_index, label);
}

template <class Molecule_T>
std::string AtomTemplate<Molecule_T>::label() const
{
return m_molecule->label(m_index);
return m_molecule->atomLabel(m_index);
}

} // namespace Core
Expand Down
24 changes: 14 additions & 10 deletions avogadro/core/molecule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ Molecule::Molecule(const Molecule& other)
: m_data(other.m_data), m_partialCharges(other.m_partialCharges),
m_spectra(other.m_spectra), m_customElementMap(other.m_customElementMap),
m_elements(other.m_elements), m_positions2d(other.m_positions2d),
m_positions3d(other.m_positions3d), m_label(other.m_label),
m_coordinates3d(other.m_coordinates3d), m_timesteps(other.m_timesteps),
m_hybridizations(other.m_hybridizations),
m_positions3d(other.m_positions3d), m_atomLabels(other.m_atomLabels),
m_bondLabels(other.m_bondLabels), m_coordinates3d(other.m_coordinates3d),
m_timesteps(other.m_timesteps), m_hybridizations(other.m_hybridizations),
m_formalCharges(other.m_formalCharges), m_colors(other.m_colors),
m_vibrationFrequencies(other.m_vibrationFrequencies),
m_vibrationIRIntensities(other.m_vibrationIRIntensities),
Expand Down Expand Up @@ -79,7 +79,8 @@ Molecule::Molecule(const Molecule& other)

void Molecule::readProperties(const Molecule& other)
{
m_label = other.m_label;
m_atomLabels = other.m_atomLabels;
m_bondLabels = other.m_bondLabels;
m_colors = other.m_colors;
// merge data maps by iterating through other's map
for (auto it = other.m_data.constBegin(); it != other.m_data.constEnd();
Expand Down Expand Up @@ -134,9 +135,9 @@ Molecule::Molecule(Molecule&& other) noexcept
m_spectra(other.m_spectra),
m_customElementMap(std::move(other.m_customElementMap)),
m_elements(other.m_elements), m_positions2d(other.m_positions2d),
m_positions3d(other.m_positions3d), m_label(other.m_label),
m_coordinates3d(other.m_coordinates3d), m_timesteps(other.m_timesteps),
m_hybridizations(other.m_hybridizations),
m_positions3d(other.m_positions3d), m_atomLabels(other.m_atomLabels),
m_bondLabels(other.m_bondLabels), m_coordinates3d(other.m_coordinates3d),
m_timesteps(other.m_timesteps), m_hybridizations(other.m_hybridizations),
m_formalCharges(other.m_formalCharges), m_colors(other.m_colors),
m_vibrationFrequencies(other.m_vibrationFrequencies),
m_vibrationIRIntensities(other.m_vibrationIRIntensities),
Expand Down Expand Up @@ -176,7 +177,8 @@ Molecule& Molecule::operator=(const Molecule& other)
m_elements = other.m_elements;
m_positions2d = other.m_positions2d;
m_positions3d = other.m_positions3d;
m_label = other.m_label;
m_atomLabels = other.m_atomLabels;
m_bondLabels = other.m_bondLabels;
m_coordinates3d = other.m_coordinates3d;
m_timesteps = other.m_timesteps;
m_hybridizations = other.m_hybridizations;
Expand Down Expand Up @@ -238,7 +240,8 @@ Molecule& Molecule::operator=(Molecule&& other) noexcept
m_elements = other.m_elements;
m_positions2d = other.m_positions2d;
m_positions3d = other.m_positions3d;
m_label = other.m_label;
m_atomLabels = other.m_atomLabels;
m_bondLabels = other.m_bondLabels;
m_coordinates3d = other.m_coordinates3d;
m_timesteps = other.m_timesteps;
m_hybridizations = other.m_hybridizations;
Expand Down Expand Up @@ -646,12 +649,13 @@ void Molecule::clearAtoms()
{
m_positions2d.clear();
m_positions3d.clear();
m_label.clear();
m_atomLabels.clear();
m_hybridizations.clear();
m_formalCharges.clear();
m_colors.clear();
m_atomicNumbers.clear();
m_bondOrders.clear();
m_bondLabels.clear();
m_graph.clear();
m_partialCharges.clear();
m_elements.reset();
Expand Down
91 changes: 78 additions & 13 deletions avogadro/core/molecule.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,27 @@ class AVOGADROCORE_EXPORT Molecule
*/
bool setAtomPosition3d(Index atomId, const Vector3& pos);

std::string label(Index atomId) const;
bool setLabel(const Core::Array<std::string>& label);
bool setLabel(Index atomId, const std::string& label);
/**
* @return Any custom label for the requested atom.
* @param atomId The index of the atom.
*/
std::string atomLabel(Index atomId) const;
/**
* Set the custom label of a single atom.
* @param atomId The index of the atom to modify.
* @param label The new label of the atom.
* @return True on success, false otherwise.
*/
bool setAtomLabel(Index atomId, const std::string& label);

const Core::Array<std::string> atomLabels() const { return m_atomLabels; }

/**
* Set all the atom labels in the molecule.
* @param label The new label array. Must be of length atomCount().
* @return True on success, false otherwise.
*/
bool setAtomLabels(const Core::Array<std::string>& label);

/**
* Set whether the specified atom is selected or not.
Expand Down Expand Up @@ -404,6 +422,28 @@ class AVOGADROCORE_EXPORT Molecule
/** @return the bond between atomId1 and atomId2. */
BondType bond(Index atomId1, Index atomId2) const;

/**
* @return Any custom label for the requested bond.
* @param bondIndex The index of the bond.
*/
std::string bondLabel(Index bondIndex) const;
/**
* Set the custom label of a single bond.
* @param bondIndex The index of the bond to modify.
* @param label The new label of the bond.
* @return True on success, false otherwise.
*/
bool setBondLabel(Index bondIndex, const std::string& label);

const Core::Array<std::string> bondLabels() const { return m_bondLabels; }

/**
* Set all the atom labels in the molecule.
* @param label The new label array. Must be of length atomCount().
* @return True on success, false otherwise.
*/
bool setBondLabels(const Core::Array<std::string>& label);

/**
* @brief Get all bonds to @p a.
* @return A vector of bonds to the supplied atom @p a.
Expand Down Expand Up @@ -780,7 +820,8 @@ class AVOGADROCORE_EXPORT Molecule
//!< force fields)
Array<Vector2> m_positions2d;
Array<Vector3> m_positions3d;
Array<std::string> m_label;
Array<std::string> m_atomLabels;
Array<std::string> m_bondLabels;
Array<Array<Vector3>> m_coordinates3d; //!< Store conformers/trajectories.
Array<double> m_timesteps;
Array<AtomHybridization> m_hybridizations;
Expand Down Expand Up @@ -989,26 +1030,26 @@ inline bool Molecule::setAtomPosition3d(Index atomId, const Vector3& pos)
return false;
}

inline std::string Molecule::label(Index atomId) const
inline std::string Molecule::atomLabel(Index atomId) const
{
return atomId < m_label.size() ? m_label[atomId] : "";
return atomId < m_atomLabels.size() ? m_atomLabels[atomId] : "";
}

inline bool Molecule::setLabel(const Core::Array<std::string>& label)
inline bool Molecule::setAtomLabels(const Core::Array<std::string>& labels)
{
if (label.size() == atomCount() || label.size() == 0) {
m_label = label;
if (labels.size() == atomCount() || labels.size() == 0) {
m_atomLabels = labels;
return true;
}
return false;
}

inline bool Molecule::setLabel(Index atomId, const std::string& label)
inline bool Molecule::setAtomLabel(Index atomId, const std::string& label)
{
if (atomId < atomCount()) {
if (atomId >= m_label.size())
m_label.resize(atomCount(), "");
m_label[atomId] = label;
if (atomId >= m_atomLabels.size())
m_atomLabels.resize(atomCount(), "");
m_atomLabels[atomId] = label;
return true;
}
return false;
Expand Down Expand Up @@ -1086,6 +1127,30 @@ inline const Array<unsigned char>& Molecule::bondOrders() const
return m_bondOrders;
}

inline std::string Molecule::bondLabel(Index bondId) const
{
return bondId < m_bondLabels.size() ? m_bondLabels[bondId] : "";
}

inline bool Molecule::setBondLabels(const Core::Array<std::string>& labels)
{
if (labels.size() == atomCount() || labels.size() == 0) {
m_bondLabels = labels;
return true;
}
return false;
}

inline bool Molecule::setBondLabel(Index bondId, const std::string& label)
{
if (bondId < bondCount()) {
if (bondId >= m_bondLabels.size())
m_bondLabels.resize(bondCount(), "");
m_bondLabels[bondId] = label;
return true;
}
return false;
}
inline const Graph& Molecule::graph() const
{
return m_graph;
Expand Down
33 changes: 27 additions & 6 deletions avogadro/io/cjsonformat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ bool CjsonFormat::deserialize(std::istream& file, Molecule& molecule,
json labels = atoms["labels"];
if (labels.is_array() && labels.size() == atomCount) {
for (size_t i = 0; i < atomCount; ++i) {
molecule.atom(i).setLabel(labels[i]);
molecule.setAtomLabel(i, labels[i]);
}
}

Expand Down Expand Up @@ -239,6 +239,14 @@ bool CjsonFormat::deserialize(std::istream& file, Molecule& molecule,
molecule.bond(i).setOrder(static_cast<int>(order[i]));
}
}

// are there bond labels?
json bondLabels = bonds["labels"];
if (bondLabels.is_array() && bondLabels.size() == molecule.bondCount()) {
for (unsigned int i = 0; i < molecule.bondCount(); ++i) {
molecule.setBondLabel(i, bondLabels[i]);
}
}
}

// residues are optional, but should be loaded
Expand Down Expand Up @@ -1051,12 +1059,15 @@ bool CjsonFormat::serialize(std::ostream& file, const Molecule& molecule,
}
}

// labels
json labels;
for (size_t i = 0; i < molecule.atomCount(); ++i) {
labels.push_back(molecule.label(i));
// check for atom labels
Array atomLabels = molecule.atomLabels();
if (atomLabels.size() == molecule.atomCount()) {
json labels;
for (Index i = 0; i < molecule.atomCount(); ++i) {
labels.push_back(atomLabels[i]);
}
root["atoms"]["labels"] = labels;
}
root["atoms"]["labels"] = labels;

// formal charges
json formalCharges;
Expand Down Expand Up @@ -1086,6 +1097,16 @@ bool CjsonFormat::serialize(std::ostream& file, const Molecule& molecule,
}
root["bonds"]["connections"]["index"] = connections;
root["bonds"]["order"] = order;

// check if there are bond labels
Array bondLabels = molecule.bondLabels();
if (bondLabels.size() == molecule.bondCount()) {
json labels;
for (Index i = 0; i < molecule.bondCount(); ++i) {
labels.push_back(bondLabels[i]);
}
root["bonds"]["labels"] = labels;
}
}

// Create and populate any residue arrays
Expand Down
Loading
Loading