1 
2 /*
3 A* -------------------------------------------------------------------
4 B* This file contains source code for the PyMOL computer program
5 C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
6 D* -------------------------------------------------------------------
7 E* It is unlawful to modify or remove this copyright notice.
8 F* -------------------------------------------------------------------
9 G* Please see the accompanying LICENSE file for further information.
10 H* -------------------------------------------------------------------
11 I* Additional authors of this source file include:
12 -*
13 -*
14 -*
15 Z* -------------------------------------------------------------------
16 */
17 #include"os_python.h"
18 
19 #include"os_predef.h"
20 #include"os_python.h"
21 #include"os_std.h"
22 
23 #include"MemoryDebug.h"
24 #include"Err.h"
25 #include"Base.h"
26 #include"OOMac.h"
27 #include"Symmetry.h"
28 #include"Setting.h"
29 #include"Ortho.h"
30 #include"Matrix.h"
31 #include"P.h"
32 #include"PConv.h"
33 #include"Util.h"
34 #include"PConv.h"
35 
SymmetryAsPyList(CSymmetry * I)36 PyObject *SymmetryAsPyList(CSymmetry * I)
37 {
38   PyObject *result = NULL;
39 
40   if(I) {
41     result = PyList_New(2);
42     PyList_SetItem(result, 0, CrystalAsPyList(&I->Crystal));
43     PyList_SetItem(result, 1, PyString_FromString(I->SpaceGroup));
44   }
45   return (PConvAutoNone(result));
46 }
47 
SymmetryFromPyList(CSymmetry * I,PyObject * list)48 static int SymmetryFromPyList(CSymmetry * I, PyObject * list)
49 {
50   int ok = true;
51   ov_size ll;
52   PyObject *secondval;
53 
54   if(ok)
55     ok = (I != NULL);
56   if(ok)
57     ok = (list != NULL);
58   if(ok)
59     ok = PyList_Check(list);
60   if(ok)
61     ll = PyList_Size(list);
62   if (ok && ll>=2){
63     secondval = PyList_GetItem(list, 1);
64     if (PyList_Check(secondval)){
65       /* if only the crystal, read it */
66       if(ok)
67 	ok = CrystalFromPyList(&I->Crystal, list);
68     } else {
69       if(ok)
70 	ok = CrystalFromPyList(&I->Crystal, PyList_GetItem(list, 0));
71       if(ok)
72 	PConvPyStrToStr(PyList_GetItem(list, 1), I->SpaceGroup, sizeof(WordType));
73     }
74   }
75   if(ok) {
76       SymmetryUpdate(I);
77   }
78   /* TO SUPPORT BACKWARDS COMPATIBILITY...
79      Always check ll when adding new PyList_GetItem's */
80   return (ok);
81 }
82 
SymmetryNewFromPyList(PyMOLGlobals * G,PyObject * list)83 CSymmetry *SymmetryNewFromPyList(PyMOLGlobals * G, PyObject * list)
84 {
85   CSymmetry *I = NULL;
86   I = new CSymmetry(G);
87   if(I) {
88     if(!SymmetryFromPyList(I, list)) {
89       SymmetryFree(I);
90       I = NULL;
91     }
92   }
93   return (I);
94 }
95 
96 #ifndef _PYMOL_NOPY
97 #ifdef _PYMOL_XRAY
SymmetryDump44f(PyMOLGlobals * G,const float * m,const char * prefix)98 static void SymmetryDump44f(PyMOLGlobals * G, const float *m, const char *prefix)
99 {
100   if(prefix) {
101     PRINTF "%s %12.5f %12.5f %12.5f %12.5f\n", prefix, m[0], m[1], m[2], m[3] ENDF(G);
102     PRINTF "%s %12.5f %12.5f %12.5f %12.5f\n", prefix, m[4], m[5], m[6], m[7] ENDF(G);
103     PRINTF "%s %12.5f %12.5f %12.5f %12.5f\n", prefix, m[8], m[9], m[10], m[11] ENDF(G);
104     PRINTF "%s %12.5f %12.5f %12.5f %12.5f\n", prefix, m[12], m[13], m[14], m[15] ENDF(G);
105   } else {
106     PRINTF "%12.5f %12.5f %12.5f %12.5f\n", m[0], m[1], m[2], m[3] ENDF(G);
107     PRINTF "%12.5f %12.5f %12.5f %12.5f\n", m[4], m[5], m[6], m[7] ENDF(G);
108     PRINTF "%12.5f %12.5f %12.5f %12.5f\n", m[8], m[9], m[10], m[11] ENDF(G);
109     PRINTF "%12.5f %12.5f %12.5f %12.5f\n", m[12], m[13], m[14], m[15] ENDF(G);
110   }
111 }
112 #endif
113 #endif
114 
115 /*
116  * Lookup the symmetry operations by space group symbol (from Python with
117  * pymol.xray) and populate SymMatVLA.
118  *
119  * Return false if space group unknown.
120  */
SymmetryAttemptGeneration(CSymmetry * I,int quiet)121 int SymmetryAttemptGeneration(CSymmetry * I, int quiet)
122 {
123   if (I->SymMatVLA) {
124     // don't re-run unless SymmetryUpdate() was called
125     return true;
126   }
127 
128   int ok = false;
129 #ifndef _PYMOL_NOPY
130 #ifdef _PYMOL_XRAY
131   PyMOLGlobals *G = I->G;
132   CrystalUpdate(&I->Crystal);
133   if(!quiet) {
134     if(Feedback(G, FB_Symmetry, FB_Blather)) {
135       CrystalDump(&I->Crystal);
136     }
137   }
138   /* TAKEN OUT BB 2/2012  SpaceGroup can be blank,
139      sg_sym_to_mat_list has a blank entry with no operations
140   if(!I->SpaceGroup[0]) {
141     ErrMessage(G, "Symmetry", "Missing space group symbol");
142     } else */
143   if(P_xray) {
144     int blocked = PAutoBlock(G);
145     ov_size a, l;
146     PyObject *mats;
147     mats = PYOBJECT_CALLMETHOD(P_xray, "sg_sym_to_mat_list", "s", I->SpaceGroup);
148     if(mats && (mats != Py_None)) {
149       l = PyList_Size(mats);
150       I->SymMatVLA = pymol::vla<float>(16*l);
151       if(!quiet) {
152         PRINTFB(G, FB_Symmetry, FB_Details)
153         " Symmetry: Found %d symmetry operators.\n", (int) l ENDFB(G);
154       }
155       for(a = 0; a < l; a++) {
156         PConv44PyListTo44f(PyList_GetItem(mats, a), I->SymMatVLA + (a * 16));
157         if(!quiet) {
158           if(Feedback(G, FB_Symmetry, FB_Blather)) {
159             SymmetryDump44f(G, I->SymMatVLA + (a * 16), " Symmetry:");
160           }
161         }
162       }
163       ok = true;
164       Py_DECREF(mats);
165     } else {
166       ErrMessage(G, "Symmetry", "Unable to get matrices.");
167     }
168     PAutoUnblock(G, blocked);
169   }
170 #endif
171 #endif
172   return (ok);
173 }
174 
SymmetryFree(CSymmetry * I)175 void SymmetryFree(CSymmetry * I)
176 {
177   if (!I)
178     return;
179 
180   delete I;
181 }
182 
SymmetryUpdate(CSymmetry * I)183 void SymmetryUpdate(CSymmetry * I)
184 {
185   CrystalUpdate(&I->Crystal);
186   I->SymMatVLA.freeP();
187 }
188 
SymmetryDump(CSymmetry * I)189 void SymmetryDump(CSymmetry * I)
190 {
191 }
192 
193 /*
194  * Get the number of symmetry matrices
195  */
getNSymMat() const196 int CSymmetry::getNSymMat() const {
197   if (!SymMatVLA)
198     return 0;
199   return VLAGetSize(SymMatVLA) / 16;
200 }
201 
202 /*
203  * Register a a space group with symmetry operations (if not already registered)
204  *
205  * sg: space group symbol, e.g. "P 1"
206  * sym_op: list of symmetry operations, e.g. ["x,y,z", "-x,-y,z"]
207  */
SymmetrySpaceGroupRegister(PyMOLGlobals * G,const char * sg,const std::vector<std::string> & sym_op)208 void SymmetrySpaceGroupRegister(PyMOLGlobals * G, const char* sg, const std::vector<std::string>& sym_op) {
209 #if !defined(_PYMOL_NOPY) && defined(_PYMOL_XRAY)
210   if (!P_xray)
211     return;
212 
213   int blocked = PAutoBlock(G);
214   PYOBJECT_CALLMETHOD(P_xray,
215       "sg_register_if_unknown", "sN", sg, PConvToPyObject(sym_op));
216   PAutoUnblock(G, blocked);
217 #endif
218 }
219