Most of these information are accessible via the <span class="italic">property table</span>. The table is on the left side of the model window.
</p>
<p><img src="../etc/tutorial_5_01.png" /></p>
+<p>
+Suppose we want to modify some properties of this molecule. This is ethyl benzoate, which has been built by (1) first creating benzene, and (2) then replacing one of the hydrogen with "COOCH2CH3". Of course there is nothing wrong with this molecule. However, when we look at the property table, we can point out several points that can be improved. First, the names of the atoms are so simple that we cannot guess which atom is what unless we carefully look at the table. Second, some of the atoms have the same name (like "C1" of atoms 0 and 11). Third, the "residue" name is only "RES" that is not informative. Fourth, the residue number (shown in the number after the residue name "RES") changes between the benzene ring and the carbonyl atom, however it should be more logical to assign the "benzoyl" (i.e. "C6H5CO") group as one residue and the ethoxy group as another. We will learn how to edit these points on the property table.
+</p>
+<h2>2. Editing the atom property</h2>
+<p>
+
+</p>
</div>
<div class="contents" lang="ja">
STUB void MainViewCallback_showTable(MainView *mview);
STUB void MainViewCallback_hideTable(MainView *mview);
STUB void MainViewCallback_ensureVisible(MainView *mview, int row);
+STUB void MainViewCallback_startEditText(MainView *mview, int row, int column);
/* Register the type definition */
//extern void MainView_register(PyObject *module);
}
}
+#pragma mark ====== MD support (including modification of Molecule) ======
+
+/* Call md_prepare for the MDArena. If MDArena has not been created, a new arena is created.
+ If something goes wrong, returns 1 (for missing parameters) or -1 (more serious error).
+ If retmsg is not NULL, a message describing the problem is returned there. This message
+ must be free'd by the caller. */
+int
+MoleculePrepareMDArena(Molecule *mol, int check_only, char **retmsg)
+{
+ const char *msg;
+ Int nangles, *angles, ndihedrals, *dihedrals, nimpropers, *impropers;
+ Int missing = 0;
+ IntGroup *ig1, *ig2, *ig3;
+ MDArena *arena = mol->arena;
+
+ if (arena == NULL) {
+ md_arena_new(mol);
+ arena = mol->arena;
+ } else if (arena->xmol != mol)
+ md_arena_set_molecule(arena, mol);
+
+ arena->is_initialized = 0;
+
+ /* Rebuild the tables */
+ ig1 = ig2 = ig3 = NULL;
+ nangles = MoleculeFindMissingAngles(mol, &angles);
+ ndihedrals = MoleculeFindMissingDihedrals(mol, &dihedrals);
+ nimpropers = MoleculeFindMissingImpropers(mol, &impropers);
+ if (nangles > 0) {
+ ig1 = IntGroupNewWithPoints(mol->nangles, nangles, -1);
+ MolActionCreateAndPerform(mol, gMolActionAddAngles, nangles * 3, angles, ig1);
+ free(angles);
+ IntGroupRelease(ig1);
+ }
+ if (ndihedrals > 0) {
+ ig2 = IntGroupNewWithPoints(mol->ndihedrals, ndihedrals, -1);
+ MolActionCreateAndPerform(mol, gMolActionAddDihedrals, ndihedrals * 4, dihedrals, ig2);
+ free(dihedrals);
+ IntGroupRelease(ig2);
+ }
+ if (nimpropers > 0) {
+ ig3 = IntGroupNewWithPoints(mol->nimpropers, nimpropers, -1);
+ MolActionCreateAndPerform(mol, gMolActionAddImpropers, nimpropers * 4, impropers, ig3);
+ free(impropers);
+ IntGroupRelease(ig3);
+ }
+
+ /* Prepare parameters and internal information */
+ msg = md_prepare(arena, check_only);
+
+ /* Some parameters are missing? */
+ if (msg != NULL) {
+ if (strstr(msg, "parameter") != NULL && strstr(msg, "missing") != NULL)
+ missing = 1;
+ else {
+ if (retmsg != NULL)
+ asprintf(retmsg, "cannot initialize for MD: %s", msg);
+ return -1;
+ }
+ }
+
+ /* The local parameter list is updated */
+ {
+ Int parType, idx;
+ if (mol->par == NULL)
+ mol->par = ParameterNew();
+ for (parType = kFirstParType; parType <= kLastParType; parType++) {
+ /* Delete global and undefined parameters */
+ UnionPar *up, *upbuf;
+ Int nparams, count;
+ ig1 = IntGroupNew();
+ for (idx = 0; (up = ParameterGetUnionParFromTypeAndIndex(mol->par, parType, idx)) != NULL; idx++) {
+ if (up->bond.src != 0)
+ IntGroupAdd(ig1, idx, 1);
+ }
+ if (IntGroupGetCount(ig1) > 0)
+ MolActionCreateAndPerform(mol, gMolActionDeleteParameters, parType, ig1);
+ IntGroupRelease(ig1);
+ /* Copy global and undefined parameters from arena and insert to mol->par */
+ nparams = ParameterGetCountForType(arena->par, parType);
+ if (nparams == 0)
+ continue;
+ upbuf = (UnionPar *)calloc(sizeof(UnionPar), nparams);
+ ig1 = IntGroupNew();
+ ig2 = IntGroupNew();
+ for (idx = 0; (up = ParameterGetUnionParFromTypeAndIndex(arena->par, parType, idx)) != NULL; idx++) {
+ if (up->bond.src > 0)
+ IntGroupAdd(ig1, idx, 1); /* Global parameter */
+ else if (up->bond.src < 0)
+ IntGroupAdd(ig2, idx, 1); /* Undefined parameter */
+ }
+ if ((count = IntGroupGetCount(ig1)) > 0) {
+ /* Insert global parameters (at the top) */
+ ParameterCopy(arena->par, parType, upbuf, ig1);
+ ig3 = IntGroupNewWithPoints(0, count, -1);
+ MolActionCreateAndPerform(mol, gMolActionAddParameters, parType, ig3, count, upbuf);
+ IntGroupRelease(ig3);
+ }
+ if ((count = IntGroupGetCount(ig2)) > 0) {
+ /* Insert undefined parameters (at the bottom) */
+ ParameterCopy(arena->par, parType, upbuf, ig2);
+ idx = ParameterGetCountForType(mol->par, parType);
+ ig3 = IntGroupNewWithPoints(idx, count, -1);
+ MolActionCreateAndPerform(mol, gMolActionAddParameters, parType, ig3, count, upbuf);
+ IntGroupRelease(ig3);
+ }
+ IntGroupRelease(ig2);
+ IntGroupRelease(ig1);
+ free(upbuf);
+ }
+ mol->needsMDRebuild = 0; /* We know the "modified" parameters are consistent with the MDArena */
+ }
+
+ if (missing) {
+ if (retmsg != NULL)
+ *retmsg = strdup(msg);
+ return 1;
+ } else return 0;
+}
+
#pragma mark ====== Serialize ======
Molecule *
int MoleculeWriteToTepFile(Molecule *mp, const char *fname, char *errbuf, int errbufsize);
void MoleculeDump(Molecule *mol);
+int MoleculePrepareMDArena(Molecule *mol, int check_only, char **retmsg);
+
char *MoleculeSerialize(Molecule *mp, Int *outLength, Int *timep);
Molecule *MoleculeDeserialize(const char *data, Int length, Int *timep);
s_MDArena_Prepare(int argc, VALUE *argv, VALUE self)
{
MDArena *arena;
+ Int check_only = 0, status;
+ char *msg;
+ VALUE fval;
+ Data_Get_Struct(self, MDArena, arena);
+ rb_scan_args(argc, argv, "01", &fval);
+ if (RTEST(fval))
+ check_only = 1;
+ status = MoleculePrepareMDArena(arena->xmol, check_only, &msg);
+ if (status < 0) {
+ /* Exception object is created first to have a chance to do free(msg) */
+ VALUE exval = rb_exc_new2(rb_eMolbyError, msg);
+ free(msg);
+ rb_exc_raise(exval);
+ } else if (status > 0) {
+ free(msg);
+ return Qnil;
+ } else return self;
+
+#if 0
+ MDArena *arena;
Molecule *mol;
const char *msg;
Int nangles, *angles, ndihedrals, *dihedrals, nimpropers, *impropers;
if (missing)
return Qnil;
else return self;
+#endif
}
/*
if (listctrl != NULL)
listctrl->EnsureVisible(row);
}
+
+void
+MainViewCallback_startEditText(MainView *mview, int row, int column)
+{
+ MyListCtrl *listctrl = s_MyListCtrlFromMainView(mview);
+ if (listctrl != NULL)
+ listctrl->StartEditText(row, column);
+}
+
create_parameter_menu->Append(myMenuID_CreateNewDihedralParameter, _T("Dihedral"));
create_parameter_menu->Append(myMenuID_CreateNewImproperParameter, _T("Improper"));
create_parameter_menu->Append(myMenuID_CreateNewVdwPairParameter, _T("Vdw Pair"));
- create_parameter_menu->Append(myMenuID_CreateNewVdwOffsetParameter, _T("Vdw Offset"));
+ create_parameter_menu->Append(myMenuID_CreateNewVdwCutoffParameter, _T("Vdw Cutoff"));
edit_menu->Append(myMenuID_CreateNewAtom, _T("Create New Atom\tCtrl-I"));
edit_menu->Append(myMenuID_CreateNewParameter, _T("Create New Parameter"), create_parameter_menu);
edit_menu->AppendSeparator();
myMenuID_CreateNewDihedralParameter = 110,
myMenuID_CreateNewImproperParameter = 111,
myMenuID_CreateNewVdwPairParameter = 112,
- myMenuID_CreateNewVdwOffsetParameter = 113,
+ myMenuID_CreateNewVdwCutoffParameter = 113,
myMenuID_AddHydrogen = 114,
myMenuID_AddHydrogenSp3 = 115,
myMenuID_AddHydrogenSp2 = 116,
EVT_MENU(wxID_CUT, MyDocument::OnCut)
EVT_MENU(wxID_DELETE, MyDocument::OnDelete)
EVT_MENU(myMenuID_CreateNewAtom, MyDocument::OnCreateNewAtom)
- EVT_MENU_RANGE(myMenuID_CreateNewVdwParameter, myMenuID_CreateNewVdwOffsetParameter, MyDocument::OnCreateNewParameter)
+ EVT_MENU_RANGE(myMenuID_CreateNewVdwParameter, myMenuID_CreateNewVdwCutoffParameter, MyDocument::OnCreateNewParameter)
EVT_MENU(wxID_SELECTALL, MyDocument::OnSelectAll)
EVT_MENU(myMenuID_SelectFragment, MyDocument::OnSelectFragment)
EVT_MENU(myMenuID_SelectReverse, MyDocument::OnSelectReverse)
void
MyDocument::OnCreateNewAtom(wxCommandEvent &event)
{
- int idx;
+ Int idx, i, j, row;
+ char name[6];
IntGroup *ig = MoleculeGetSelection(mol);
MainView *mview = GetMainView();
+ Atom *ap, arec;
+
if (mview == NULL)
return;
- MainViewCallback_selectTable(mview, kMainViewAtomTableIndex);
+
+ /* Make an atom name "Cxxx" */
+ for (i = 0; i < 1000; i++) {
+ sprintf(name, "C%03d", i);
+ for (j = 0, ap = mol->atoms; j < mol->natoms; j++, ap = ATOM_NEXT(ap)) {
+ if (strncmp(ap->aname, name, 4) == 0)
+ break;
+ }
+ if (j >= mol->natoms)
+ break;
+ }
+ memset(&arec, 0, sizeof(arec));
+ strncpy(arec.aname, name, 4);
+ arec.type = AtomTypeEncodeToUInt("c3");
+ arec.element[0] = 'C';
+ arec.atomicNumber = 6;
+ arec.weight = WeightForAtomicNumber(6);
+ arec.occupancy = 1.0;
+
if (ig != NULL && IntGroupGetCount(ig) > 0) {
idx = IntGroupGetEndPoint(ig, IntGroupGetIntervalCount(ig) - 1);
} else {
idx = mol->natoms;
}
- MolActionCreateAndPerform(mol, SCRIPT_ACTION("si"), "create_atom", "", idx);
+
+ if (MolActionCreateAndPerform(mol, gMolActionAddAnAtom, &arec, idx, &idx) != 0)
+ return;
+
+ /* Show the atom table and select the newly created atom */
+ MainViewCallback_selectTable(mview, kMainViewAtomTableIndex);
ig = IntGroupNewWithPoints(idx, 1, -1);
MoleculeSetSelection(mol, ig);
IntGroupRelease(ig);
- MainViewCallback_setNeedsDisplay(mview, 1);
- MainViewCallback_reloadTableData(mview);
- MainViewCallback_ensureVisible(mview, MainView_indexToTableRow(mview, idx));
+ MainView_refreshTable(mview);
+ row = MainView_indexToTableRow(mview, idx);
+/* MainViewCallback_ensureVisible(mview, row); */ /* Invoked from startEditText */
+ MainViewCallback_startEditText(mview, row, 1);
}
void
MyDocument::OnCreateNewParameter(wxCommandEvent &event)
{
-/* int uid = event.GetId();
- const char *type;
+ int uid = event.GetId();
+ Int parType, n;
+ UnionPar ubuf;
IntGroup *ig;
+ UInt ctype = AtomTypeEncodeToUInt("C");
+ Double cweight = WeightForAtomicNumber(6);
+ memset(&ubuf, 0, sizeof(ubuf));
+ ubuf.bond.src = -1; /* Undefined */
switch (uid) {
- case myMenuID_CreateNewVdwParameter: type = "td"; break;
- case myMenuID_AddHydrogenSp2: type = "tr"; break;
- case myMenuID_AddHydrogenLinear: type = "li"; break;
- case myMenuID_AddHydrogenPyramidal: type = "py"; break;
- case myMenuID_AddHydrogenBent: type = "be"; break;
- default: return;
+ case myMenuID_CreateNewVdwParameter:
+ parType = kVdwParType;
+ ubuf.vdw.type1 = ctype;
+ ubuf.vdw.atomicNumber = 6;
+ ubuf.vdw.weight = cweight;
+ break;
+ case myMenuID_CreateNewBondParameter:
+ parType = kBondParType;
+ ubuf.bond.type1 = ubuf.bond.type2 = ctype;
+ break;
+ case myMenuID_CreateNewAngleParameter:
+ parType = kAngleParType;
+ ubuf.angle.type1 = ubuf.angle.type2 = ubuf.angle.type3 = ctype;
+ break;
+ case myMenuID_CreateNewDihedralParameter:
+ parType = kDihedralParType;
+ ubuf.torsion.type1 = ubuf.torsion.type2 = ubuf.torsion.type3 = ubuf.torsion.type4 = ctype;
+ break;
+ case myMenuID_CreateNewImproperParameter:
+ parType = kImproperParType;
+ ubuf.torsion.type1 = ubuf.torsion.type2 = ubuf.torsion.type3 = ubuf.torsion.type4 = ctype;
+ break;
+ case myMenuID_CreateNewVdwPairParameter:
+ parType = kVdwPairParType;
+ ubuf.vdwp.type1 = ubuf.vdwp.type2 = ctype;
+ break;
+ case myMenuID_CreateNewVdwCutoffParameter:
+ parType = kVdwCutoffParType;
+ ubuf.vdwcutoff.n1 = ubuf.vdwcutoff.n2 = ctype;
+ break;
+ default:
+ return;
+ }
+ if (mol->par == NULL) {
+ char *errmsg;
+ if (MoleculePrepareMDArena(mol, 1, &errmsg) < 0) {
+ MyAppCallback_messageBox(errmsg, "MM/MD Setup Error", 1, 3);
+ free(errmsg);
+ return;
+ }
+ }
+ n = ParameterGetCountForType(mol->par, parType);
+ ig = IntGroupNewWithPoints(n, 1, -1);
+ MolActionCreateAndPerform(mol, gMolActionAddParameters, parType, ig, 1, &ubuf);
+ if (ParameterGetCountForType(mol->par, parType) == n + 1) {
+ /* Successful creation of the parameter */
+ MainView *mview = GetMainView();
+ Int row;
+ MainViewCallback_selectTable(mview, kMainViewParameterTableIndex);
+ MainView_refreshTable(mview);
+ row = ParameterTableGetRowFromTypeAndIndex(mol->par, parType, n);
+ MainViewCallback_startEditText(mview, row, 1);
}
- */
}
void
RDSize size;
wxCoord w, h, descent, leading;
wxPaintDC dc((wxWindow *)item);
- int len = strlen(s);
- const char *s1, *s2;
+ int len;
+ const char *s1, *s2, *sfin;
size.width = size.height = 0;
s1 = (s == NULL || s[0] == 0 ? " " : s);
+ len = strlen(s1);
+ sfin = s1 + len;
while (1) {
s2 = strchr(s1, '\n');
if (s2 == NULL)
- s2 = s + len;
+ s2 = sfin;
wxString str(s1, wxConvUTF8, s2 - s1);
dc.GetTextExtent(str, &w, &h, &descent, &leading);
if (size.width < w)
size.width = w;
size.height += h + descent + leading;
- if (s2 == s + len)
+ if (s2 >= sfin)
break;
s1 = s2 + 1;
}