Skip to content
Open
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
9 changes: 9 additions & 0 deletions source/src/apps/public/restype_converter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <core/chemical/sdf/MolFileIOReader.hh>
#include <core/chemical/sdf/mol_writer.hh>
#include <core/chemical/mmCIF/mmCIFParser.hh>
#include <core/chemical/mmCIF/mmCIFWriter.hh>

#include <core/conformation/Residue.fwd.hh>
#include <core/conformation/ResidueFactory.hh>
Expand Down Expand Up @@ -69,6 +70,8 @@ void register_options() {
option.add_relevant( out::pdb );
option.add_relevant( restype_convert::params_out );
option.add_relevant( restype_convert::sdf_out );
option.add_relevant( out::mmCIF );


}

Expand Down Expand Up @@ -254,6 +257,12 @@ output_residue_types( utility::vector1< core::chemical::ResidueTypeCOP > const &
files_outputted = true;
}

if ( option[ out::mmCIF ]() ) {
mmCIF::mmCIFWriter writer;
writer.write_file( determine_output_name( name, "cif" ), *restype );
files_outputted = true;
}

}

if ( ! files_outputted ) {
Expand Down
1 change: 1 addition & 0 deletions source/src/core.2.src.settings
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ sources = {
],
"core/chemical/mmCIF": [
"mmCIFParser",
"mmCIFWriter",
],
"core/conformation": [
"AbstractRotamerTrie",
Expand Down
28 changes: 24 additions & 4 deletions source/src/core/chemical/mmCIF/mmCIFParser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,26 @@ mmCIFParser::get_molfile_molecule( gemmi::cif::Block & block ) {

sdf::MolFileIOMoleculeOP molecule( new sdf::MolFileIOMolecule() );

molecule->name( block.name );
//only proceed if the tables for bonds and atoms are present
if ( !block.has_mmcif_category("_chem_comp_atom") ) {
TR.Error << "Cannot parse CIF file. No atom block (chem_comp_atom) found for " << block.name << std::endl;
return molecule;
}

/////////////////// Standard Residue-level data
molecule->name( block.name );

std::string const * name3 = block.find_value("_chem_comp.three_letter_code"); // Non-owning raw pointer, null if not found.
if ( name3 && !name3->empty() ) {
molecule->name3( as_string(name3) );
}
std::string const * name1 = block.find_value("_chem_comp.one_letter_code"); // Non-owning raw pointer, null if not found.
if ( name1 && !name1->empty() ) {
molecule->name1( as_string(name1) );
}

//////////////////// Standard Atom-level data

// There's another possible issue. to pre-pick about. We absolutely NEED N,
// because we need to be very specific about adding and deleting atoms.
// also... residue types without N are very likely to be a poor representative
Expand All @@ -126,6 +139,8 @@ mmCIFParser::get_molfile_molecule( gemmi::cif::Block & block ) {
int model_Cartn_y = find_gemmi_column(atom_comp,"model_Cartn_y");
int model_Cartn_z = find_gemmi_column(atom_comp,"model_Cartn_z");
int charge = find_gemmi_column(atom_comp,"charge");
int partial_charge = find_gemmi_column(atom_comp,"partial_charge");


int atom_name_id = find_gemmi_column(atom_comp,"atom_id");
if ( atom_name_id < 0 ) {
Expand Down Expand Up @@ -207,9 +222,9 @@ mmCIFParser::get_molfile_molecule( gemmi::cif::Block & block ) {
// Get the chem_comp table first, because this will help us
// look out for extraneous atoms common in CIF entries -- extra nitrogen H
// and OH terminus on C
gemmi::cif::Table chem_comp = block.find( "_chem_comp.", {"type"} );
if ( chem_comp.size() > 0 ) {
std::string type = as_string(chem_comp[0][0]);
gemmi::cif::Table chem_comp_type = block.find( "_chem_comp.", {"type"} );
if ( chem_comp_type.size() > 0 ) {
std::string type = as_string(chem_comp_type[0][0]);
if ( type == "L-PEPTIDE LINKING" && is_peptide_linking ) {
TR.Debug << "Found L-peptide RT" << std::endl;// named " << molecule->name() << std::endl;
molecule->add_str_str_data( "Rosetta Properties", "PROTEIN POLYMER L_AA" );
Expand Down Expand Up @@ -246,6 +261,8 @@ mmCIFParser::get_molfile_molecule( gemmi::cif::Block & block ) {
}
}



// Sometimes OP3/O3P is used for non-term-deletable phosphate oxygens. (THX)
//bool interesting_upper_behavior = false;

Expand Down Expand Up @@ -470,6 +487,9 @@ mmCIFParser::get_molfile_molecule( gemmi::cif::Block & block ) {
} else {
atom->formal_charge( 0 );
}
if ( partial_charge >= 0 ) {
atom->partial_charge( as_number( atom_comp[ii][partial_charge], 0 ) ); // Default zero if present and null
}

molecule->add_atom( atom );
// only increment if we actually get here.
Expand Down
191 changes: 191 additions & 0 deletions source/src/core/chemical/mmCIF/mmCIFWriter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
// -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
// vi: set ts=2 noet:
//
// (c) Copyright Rosetta Commons Member Institutions.
// (c) This file is part of the Rosetta software suite and is made available under license.
// (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
// (c) For more information, see http://www.rosettacommons.org. Questions about this can be
// (c) addressed to University of Washington CoMotion, email: [email protected].

/// @file src/core/chemical/sdf/mmCIFWriter.cc
/// @author Rocco Moretti ([email protected])

#include <core/chemical/mmCIF/mmCIFWriter.hh>

#include <core/chemical/ResidueType.hh>
#include <core/chemical/Element.hh>

#include <core/types.hh>

//Utility functions
#include <basic/Tracer.hh>
#include <utility/io/ozstream.hh>
#include <utility/string_util.hh>
#include <utility/stream_util.hh>
#include <utility/gemmi_util.hh>

//external CIF includes
#include <gemmi/cif.hpp>
#include <gemmi/to_cif.hpp>
#include <gemmi/numb.hpp> // for as_number


namespace core {
namespace chemical {
namespace mmCIF {


//Load up the tracer for this class
static basic::Tracer TR( "core.io.mmCIF.mmCIFWriter" );

void
mmCIFWriter::write_file(std::string const & file_name, core::chemical::ResidueType const & restype) {
utility::io::ozstream outfile;
outfile.open(file_name.c_str(), std::ios::out);
if ( !outfile ) {
throw CREATE_EXCEPTION(utility::excn::FileNotFound, "Cannot open file"+file_name);
}
write_stream(outfile,restype);
outfile.close();
}

void
mmCIFWriter::write_stream(std::ostream & output_stream, core::chemical::ResidueType const & restype) {
gemmi::cif::WriteOptions options;
options.prefer_pairs = true;
options.misuse_hash = true;
options.align_pairs = 48; // Matches from-RCSB alignment
options.align_loops = 10;

gemmi::cif::Block block;
block.name = restype.name();
add_data_to_block( block, restype );

gemmi::cif::write_cif_block_to_stream( output_stream, block, options );
}

void
mmCIFWriter::add_data_to_block( gemmi::cif::Block &block, core::chemical::ResidueType const & restype ) {
using utility::gemmi_get_table;
using utility::gemmi_append_row;

////////////// Standard Residue-level data
//
std::string type;
if ( restype.is_polymer() ) {
if ( restype.is_l_aa() ) {
type = "L-PEPTIDE LINKING";
} else if ( restype.is_d_aa() ) {
type = "D-PEPTIDE LINKING";
} else if ( restype.is_RNA() ) {
type = "RNA LINKING";
} else if ( restype.is_DNA() ) {
type = "DNA LINKING";
}
} else {
type = "NON-POLYMER";
}

gemmi::cif::Table chem_comp = gemmi_get_table(block, "_chem_comp", {
"id",
"name",
"one_letter_code",
"three_letter_code",
"type"
});

gemmi_append_row( chem_comp, {
restype.name(),
restype.name(),
std::string(1, restype.name1() ),
restype.name3(),
type
});

////////////// Standard Atom-level Data

gemmi::cif::Table atom_comp = gemmi_get_table(block, "_chem_comp_atom", {
"comp_id",
"atom_id",
"type_symbol",
"charge",
"model_Cartn_x",
"model_Cartn_y",
"model_Cartn_z",
"partial_charge"
} );

for ( core::Size ii(1); ii <= restype.natoms(); ++ii ) {
std::vector< std::string > vec;
vec.push_back( restype.name() );
vec.push_back( restype.atom_name(ii) );
vec.push_back( restype.element_type(ii)->get_chemical_symbol() );
vec.push_back( std::to_string( restype.formal_charge(ii) ) );
core::Vector pos = restype.ideal_xyz(ii);
vec.push_back( std::to_string(pos.x()) );
vec.push_back( std::to_string(pos.y()) );
vec.push_back( std::to_string(pos.z()) );
vec.push_back( std::to_string(restype.atom_charge(ii)) );

gemmi_append_row( atom_comp, vec );
}

//////////////// Rosetta-specific Atom-level Data
//
//// Note, if there's a standard place to put this data, prefer that
//gemmi::cif::Table rosetta_atom_comp = gemmi_get_table(block, "_rosetta_chem_comp_atom", {
// "comp_id",
// "atom_id",
// } );
//
//for ( core::Size ii(1); ii <= restype.natoms(); ++ii ) {
// std::vector< std::string > vec;
// vec.push_back( restype.name() );
// vec.push_back( restype.atom_name(ii) );
//
// gemmi_append_row( rosetta_atom_comp, vec );
//}
//
//////////////// Standard Bond-level Data

gemmi::cif::Table bond_comp = gemmi_get_table(block, "_chem_comp_bond", {
"comp_id",
"atom_id_1",
"atom_id_2",
"value_order",
"pdbx_aromatic_flag",
} );

utility::vector1< std::pair< core::Size, core::Size > > const & all_bonds = restype.bonds();

for ( core::Size ii(1); ii <= restype.nbonds(); ++ii ) {
std::vector< std::string > vec;
vec.push_back( restype.name() );
core::Size atm1 = all_bonds[ii].first;
core::Size atm2 = all_bonds[ii].second;
vec.push_back( restype.atom_name( atm1 ) );
vec.push_back( restype.atom_name( atm2 ) );
std::string bond_type = "UNK";
switch ( restype.bond_type( atm1, atm2 ) ) {
case SingleBond :
bond_type = "SING"; break;
case DoubleBond :
bond_type = "DOUB"; break;
case TripleBond :
bond_type = "TRIP"; break;
case AromaticBond :
bond_type = "AROM"; break;
default :
bond_type = "UNK"; break;
}
vec.push_back( bond_type );
vec.push_back( (restype.bond_type( atm1, atm2 ) == AromaticBond) ? "Y" : "N" );

gemmi_append_row( bond_comp, vec );
}
}


}
}
}
28 changes: 28 additions & 0 deletions source/src/core/chemical/mmCIF/mmCIFWriter.fwd.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
// vi: set ts=2 noet:
//
// (c) Copyright Rosetta Commons Member Institutions.
// (c) This file is part of the Rosetta software suite and is made available under license.
// (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
// (c) For more information, see http://www.rosettacommons.org. Questions about this can be
// (c) addressed to University of Washington CoMotion, email: [email protected].

/// @file src/core/chemical/mmCIF/mmCIFWriter.fwd.hh
/// @author Rocco Moretti ([email protected])

#ifndef INCLUDED_core_chemical_mmCIF_mmCIFWriter_fwd_hh
#define INCLUDED_core_chemical_mmCIF_mmCIFWriter_fwd_hh

#include <utility/pointer/owning_ptr.hh>


namespace core {
namespace chemical {
namespace mmCIF {

}
}
}

#endif

66 changes: 66 additions & 0 deletions source/src/core/chemical/mmCIF/mmCIFWriter.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
// vi: set ts=2 noet:
//
// (c) Copyright Rosetta Commons Member Institutions.
// (c) This file is part of the Rosetta software suite and is made available under license.
// (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
// (c) For more information, see http://www.rosettacommons.org. Questions about this can be
// (c) addressed to University of Washington CoMotion, email: [email protected].
//////////////////////////////////////////////////////////////////////
///
/// @brief
/// Class to convert a ResidueType to mmCIF.
///
/// @file src/core/chemical/sdf/mmCIFWriter.hh
///
/// @details
///
/// @author Rocco Moretti ([email protected])
///
///
/////////////////////////////////////////////////////////////////////////

#ifndef INCLUDED_core_chemical_mmCIF_mmCIFWriter_hh
#define INCLUDED_core_chemical_mmCIF_mmCIFWriter_hh

#include <core/chemical/mmCIF/mmCIFWriter.fwd.hh>
#include <core/chemical/ResidueType.fwd.hh>

#include <utility/vector1.hh>
#include <utility/VirtualBase.hh>
#include <map>
#include <core/types.hh>

#include <utility/gemmi_util.fwd.hh>

namespace core {
namespace chemical {
namespace mmCIF {

class mmCIFWriter : public utility::VirtualBase
{

public:

mmCIFWriter() = default;
~mmCIFWriter() override = default;

void
write_file( std::string const & filename, core::chemical::ResidueType const & restype );

void
write_stream( std::ostream & output_stream, core::chemical::ResidueType const & restype );

void
add_data_to_block( gemmi::cif::Block & block, core::chemical::ResidueType const & restype );

private:

};



}
}
}
#endif
Loading