making custom molecules at runtime?

Provide C++ API for creating molecular models whose dynamics can be simulated using the SimTK Simbody library. A link to the online API reference documentation for Molmodel can be found on the Documents page.
POST REPLY
User avatar
Samuel Flores
Posts: 189
Joined: Mon Apr 30, 2007 1:06 pm

making custom molecules at runtime?

Post by Samuel Flores » Mon Apr 21, 2014 11:16 am

Guys,

I'd like my code (MMB) to create arbitrary molecules at runtime from a user-provided set of commands. I didn't get far before I realized I don't know how to do this, and whether it's even feasible. I started by hacking the "Methane" class in Compound.h:


class Methane : public Molecule {
public:
Methane()
{
setBaseCompound("methyl", MethylGroup());
inheritAtomNames("methyl");
convertInboardBondCenterToOutboard();
bondAtom(AliphaticHydrogen("H4"), "methyl/bond", 0.1112);
setBiotypeIndex( "C", Biotype::MethaneC().getIndex() );
setBiotypeIndex( "H1", Biotype::MethaneH().getIndex() );
setBiotypeIndex( "H2", Biotype::MethaneH().getIndex() );
setBiotypeIndex( "H3", Biotype::MethaneH().getIndex() );
setBiotypeIndex( "H4", Biotype::MethaneH().getIndex() );
setCompoundName("Methane");
}
};


I figured the user could issue commands like "setBaseCompound methyl MethylGroup()" and I would somehow parse this. The problem, of course, is that I can't turn the literal "MethylGroup()" into an object. I thought about listing all available descendants of Compound in a vector and looping through it, but that seems clumsy. A ridiculously simple-minded way to go about this would be :

class CustomMolecule : public Molecule {
public:
CustomMolecule(vector <MoleculeBuildCommand> moleculeBuildCommandVector)
{
for ( int i = 0; i < moleculeBuildCommandVector.size(); i++) {
if (moleculeBuildCommandVector.Command.compare("setBaseCompound") == 0) {
if (moleculeBuildCommandVector.BaseCompoundName.compare("methyl") == 0) {setBaseCompound(moleculeBuildCommandVector.BaseCompoundName , MethylGroup()); }
if (moleculeBuildCommandVector.BaseCompoundName.compare("MethyleneGroup") == 0) {setBaseCompound(moleculeBuildCommandVector.BaseCompoundName , MethyleneGroup()); }
}
}
}}

.. and so on for all available compounds. Plus I would have to add parsing of the other commands ("bondAtom", etc).

In any event, is there any way to do this in a way that's not downright dumb?

Sam

User avatar
Michael Sherman
Posts: 807
Joined: Fri Apr 01, 2005 6:05 pm

Re: making custom molecules at runtime?

Post by Michael Sherman » Mon Apr 21, 2014 12:54 pm

I think you could do what you want by using std::map or std::unordered_map (hash table) in C++ to map strings to particular objects or to functions. You would look up the string "methyl" in the map, which would return the object MethylGroup() which you would then feed to setBaseCompound(). That would be very fast and clean.

Regards,
Sherm

User avatar
Samuel Flores
Posts: 189
Joined: Mon Apr 30, 2007 1:06 pm

Re: making custom molecules at runtime?

Post by Samuel Flores » Tue Apr 22, 2014 8:42 am

Hi Sherm,

I followed your advice and created a map :

map <const String , Compound> compoundObjectMap;

I initialized it with commands such as:

compoundObjectMap.insert (std::pair <const String , Compound> ("AliphaticHydrogen",AliphaticHydrogen() ))

This actually worked for the setBaseCompound command.

Note that AliphaticHydrogen() is a Compound::SingleAtom. Now I want to actually use this in the bondAtom command. But it is expecting a Compound::SingleAtom, whereas the object I retrieve from compoundObjectMap has been upcast and now thinks it's just a Compound:

41 Compound::SingleAtom myCompound = compoundObjectMapContainer.fetch(moleculeBuildCommandVector[1]);
42 myCompound.setCompoundName(moleculeBuildCommandVector[2]);
44 bondAtom(Compound::SingleAtom(myCompound) ,
45 moleculeBuildCommandVector[3], // name of bond at which to attach the atom
46 atof(moleculeBuildCommandVector[4].c_str()) ); // Default bond length

I can't seem to downcast myCompound back into a Compound::SingleAtom. Is there some way to use compoundObjectMap that doesn't require upcasting? Any ideas on how to get around this?

Sam


Sam

User avatar
Samuel Flores
Posts: 189
Joined: Mon Apr 30, 2007 1:06 pm

Re: making custom molecules at runtime?

Post by Samuel Flores » Tue Apr 22, 2014 10:47 am

I decided to maintain separate maps for Compound's and Compound::SingleAtom's:

35 map <const String , Compound::SingleAtom> singleAtomMap;

Then I had trouble fetching a SingleAtom:


33 Compound::SingleAtom CompoundObjectMapContainer::fetchSingleAtom(const String compoundName) {
34 if (singleAtomMap.find(compoundName) == singleAtomMap.end()) {
35 ErrorManager::instance <<__FILE__<<":"<<__LINE__<<" No Compound object found with name "<<compoundName <<endl; ErrorManager::instance.treatError() ;
36 }
37 else return singleAtomMap[compoundName];
38 }

I got this error:


In file included from /Users/Sam/svn/RNAToolbox/trunk/src/MoleculeContainer.cpp:3:
In file included from /Users/Sam/svn/RNAToolbox/trunk/include/MoleculeContainer.h:6:
In file included from /usr/local/SimTK/include/SimTKmolmodel.h:47:
In file included from /usr/local/SimTK/include/Simbody.h:38:
In file included from /usr/local/SimTK/include/SimTKcommon.h:64:
In file included from /usr/local/SimTK/include/SimTKcommon/internal/ThreadLocal.h:28:
In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/c++/4.2.1/map:66:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/c++/4.2.1/bits/stl_map.h:350:45: error: no
matching constructor for initialization of 'mapped_type' (aka 'SimTK::Compound::SingleAtom')
__i = insert(__i, value_type(__k, mapped_type()));
^
/Users/Sam/svn/RNAToolbox/trunk/src/MoleculeContainer.cpp:37:30: note: in instantiation of member function 'std::map<const SimTK::String,
SimTK::Compound::SingleAtom, std::less<const SimTK::String>, std::allocator<std::pair<const SimTK::String, SimTK::Compound::SingleAtom> > >::operator[]'
requested here
else return singleAtomMap[compoundName];
^
/usr/local/SimTK/include/molmodel/internal/Compound.h:1205:5: note: candidate constructor not viable: requires 2 arguments, but 0 were provided
SingleAtom(
^
/usr/local/SimTK/include/molmodel/internal/Compound.h:1203:18: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument,
but 0 were provided
class Compound::SingleAtom : public Compound {


I think it's saying that there is no default constructor for SingleAtom, only constructors that require 1 or 2 arguments. Can you tell me how to fetch this object? I had no trouble fetching a Compound from a similar map.

User avatar
Michael Sherman
Posts: 807
Joined: Fri Apr 01, 2005 6:05 pm

Re: making custom molecules at runtime?

Post by Michael Sherman » Tue Apr 22, 2014 11:11 am

Hi, Sam.

I think your original approach would work -- you just have to downcast the Compound to the appropriate type (e.g. Compound::SingleAtom) once you know what you have. In C++ you should be able to do static_cast<Compound::SingleAtom>(someCompound).

Since SingleAtom doesn't have a default constructor, it can't be put in an std::map which apparently depends on that. You could fix that by adding a defalut constructor to SingleAtom, or go back to using the Compound base type (which apparently has the needed constructors), and then figure out how to downcast it.

Regards,
Sherm

POST REPLY