OSDN Git Service

Create New Parameter menu command is implemented. MoleculePrepareMDArena() is implmen...
authortoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Tue, 26 Jul 2011 15:54:43 +0000 (15:54 +0000)
committertoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Tue, 26 Jul 2011 15:54:43 +0000 (15:54 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@79 a2be9bc6-48de-4e38-9406-05402d4bc13c

Documents/etc/tutorial_5_01.png
Documents/src/doc_source.html
MolLib/MainView.h
MolLib/Molecule.c
MolLib/Molecule.h
MolLib/Ruby_bind/ruby_md.c
wxSources/MoleculeView.cpp
wxSources/MyApp.cpp
wxSources/MyApp.h
wxSources/MyDocument.cpp
wxSources/RubyDialogFrame.cpp

index 955ea3d..1d937cf 100644 (file)
Binary files a/Documents/etc/tutorial_5_01.png and b/Documents/etc/tutorial_5_01.png differ
index 25302b0..86991e4 100644 (file)
@@ -919,6 +919,13 @@ A molecule has many properties. It has a set of atoms and bonds. An atom has a n
 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">
index 3bdf663..e6b5861 100755 (executable)
@@ -241,6 +241,7 @@ STUB IntGroup *MainViewCallback_getTableSelection(MainView *mview);
 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);
index 49d354e..3681bc3 100755 (executable)
@@ -3932,6 +3932,126 @@ MoleculeDump(Molecule *mol)
        }
 }
 
+#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 *
index 76b24ef..febe533 100755 (executable)
@@ -350,6 +350,8 @@ int MoleculeWriteToDcdFile(Molecule *mp, const char *fname, char *errbuf, int er
 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);
 
index 099706f..6eb55c4 100644 (file)
@@ -161,6 +161,26 @@ static VALUE
 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;
@@ -267,6 +287,7 @@ s_MDArena_Prepare(int argc, VALUE *argv, VALUE self)
        if (missing)
                return Qnil;
        else return self;
+#endif
 }
 
 /*
index 6cf0201..cfee3e4 100755 (executable)
@@ -1232,3 +1232,12 @@ MainViewCallback_ensureVisible(MainView *mview, int row)
        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);
+}
+
index f4ef1f4..77b854c 100755 (executable)
@@ -353,7 +353,7 @@ MyApp::CreateMenuBar(int kind, wxMenu **out_file_history_menu, wxMenu **out_edit
        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();
index 32cdb02..e2630fd 100755 (executable)
@@ -56,7 +56,7 @@ enum {
        myMenuID_CreateNewDihedralParameter = 110,
        myMenuID_CreateNewImproperParameter = 111,
        myMenuID_CreateNewVdwPairParameter = 112,
-       myMenuID_CreateNewVdwOffsetParameter = 113,
+       myMenuID_CreateNewVdwCutoffParameter = 113,
        myMenuID_AddHydrogen = 114,
        myMenuID_AddHydrogenSp3 = 115,
        myMenuID_AddHydrogenSp2 = 116,
index da11306..896b0d1 100755 (executable)
@@ -74,7 +74,7 @@ BEGIN_EVENT_TABLE(MyDocument, wxDocument)
        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)
@@ -503,41 +503,118 @@ MyDocument::OnDelete(wxCommandEvent& event)
 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
index 11385bd..b41cfcf 100644 (file)
@@ -610,20 +610,22 @@ RubyDialogCallback_sizeOfString(RDItem *item, const char *s)
        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;
        }