layer2/ObjectMap.cpp (4,875 lines of code) (raw):

/* A* ------------------------------------------------------------------- B* This file contains source code for the PyMOL computer program C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific. D* ------------------------------------------------------------------- E* It is unlawful to modify or remove this copyright notice. F* ------------------------------------------------------------------- G* Please see the accompanying LICENSE file for further information. H* ------------------------------------------------------------------- I* Additional authors of this source file include: -* -* -* Z* ------------------------------------------------------------------- */ #include <stdint.h> #include <algorithm> #include"os_python.h" #include"os_numpy.h" #include"os_std.h" #include"os_gl.h" #include"OOMac.h" #include"ObjectMap.h" #include"Base.h" #include"MemoryDebug.h" #include"Map.h" #include"Parse.h" #include"Isosurf.h" #include"Vector.h" #include"Color.h" #include"main.h" #include"Scene.h" #include"PConv.h" #include"Word.h" #include"Vector.h" #include"PyMOLGlobals.h" #include"Matrix.h" #include"Util.h" #include"ShaderMgr.h" #include"CGO.h" #include"File.h" #include"Executive.h" #define n_space_group_numbers 231 static const char * space_group_numbers[] = { "", "P 1", "P -1", "P 2", "P 21", "C 2", "P M", "P C", "C M", "C C", "P 2/M", "P 21/M", "C 2/M", "P 2/C", "P 21/C", "C 2/C", "P 2 2 2", "P 2 2 21", "P 21 21 2", "P 21 21 21", "C 2 2 21", "C 2 2 2", "F 2 2 2", "I 2 2 2", "I 21 21 21", "P M M 2", "P M C 21", "P C C 2", "P M A 2", "P C A 21", "P N C 2", "P M N 21", "P B A 2", "P N A 21", "P N N 2", "C M M 2", "C M C 21", "C C C 2", "A M M 2", "A B M 2", "A M A 2", "A B A 2", "F M M 2", "F D D 2", "I M M 2", "I B A 2", "I M A 2", "P M M M", "P N N N", "P C C M", "P B A N", "P M M A", "P N N A", "P M N A", "P C C A", "P B A M", "P C C N", "P B C M", "P N N M", "P M M N", "P B C N", "P B C A", "P N M A", "C M C M", "C M C A", "C M M M", "C C C M", "C M M A", "C C C A", "F M M M", "F D D D", "I M M M", "I B A M", "I B C A", "I M M A", "P 4", "P 41", "P 42", "P 43", "I 4", "I 41", "P -4", "I -4", "P 4/M", "P 42/M", "P 4/N", "P 42/N", "I 4/M", "I 41/A", "P 4 2 2", "P 4 21 2", "P 41 2 2", "P 41 21 2", "P 42 2 2", "P 42 21 2", "P 43 2 2", "P 43 21 2", "I 4 2 2", "I 41 2 2", "P 4 M M", "P 4 B M", "P 42 C M", "P 42 N M", "P 4 C C", "P 4 N C", "P 42 M C", "P 42 B C", "I 4 M M", "I 4 C M", "I 41 M D", "I 41 C D", "P -4 2 M", "P -4 2 C", "P -4 21 M", "P -4 21 C", "P -4 M 2", "P -4 C 2", "P -4 B 2", "P -4 N 2", "I -4 M 2", "I -4 C 2", "I -4 2 M", "I -4 2 D", "P 4/M M M", "P 4/M C C", "P 4/N B M", "P 4/N N C", "P 4/M B M", "P 4/M N C", "P 4/N M M", "P 4/N C C", "P 42/M M C", "P 42/M C M", "P 42/N B C", "P 42/N N M", "P 42/M B C", "P 42/M N M", "P 42/N M C", "P 42/N C M", "I 4/M M M", "I 4/M C M", "I 41/A M D", "I 41/A C D", "P 3", "P 31", "P 32", "R 3", "P -3", "R -3", "P 3 1 2", "P 3 2 1", "P 31 1 2", "P 31 2 1", "P 32 1 2", "P 32 2 1", "R 3 2", "P 3 M 1", "P 3 1 M", "P 3 C 1", "P 3 1 C", "R 3 M", "R 3 C", "P -3 1 M", "P -3 1 C", "P -3 M 1", "P -3 C 1", "R -3 M", "R -3 C", "P 6", "P 61", "P 65", "P 62", "P 64", "P 63", "P -6", "P 6/M", "P 63/M", "P 6 2 2", "P 61 2 2", "P 65 2 2", "P 62 2 2", "P 64 2 2", "P 63 2 2", "P 6 M M", "P 6 C C", "P 63 C M", "P 63 M C", "P -6 M 2", "P -6 C 2", "P -6 2 M", "P -6 2 C", "P 6/M M M", "P 6/M C C", "P 63/M C M", "P 63/M M C", "P 2 3", "F 2 3", "I 2 3", "P 21 3", "I 21 3", "P M -3", "P N -3", "F M -3", "F D -3", "I M -3", "P A -3", "I A -3", "P 4 3 2", "P 42 3 2", "F 4 3 2", "F 41 3 2", "I 4 3 2", "P 43 3 2", "P 41 3 2", "I 41 3 2", "P -4 3 M", "F -4 3 M", "I -4 3 M", "P -4 3 N", "F -4 3 C", "I -4 3 D", "P M -3 M", "P N -3 N", "P M -3 N", "P N -3 M", "F M -3 M", "F M -3 C", "F D -3 M", "F D -3 C", "I M -3 M", "I A -3 D", }; /* MapState::ValidXtal -- determines whether the MapState's Xtal type passed in is valid * PARAMS * ms, MapState * RETURNS * true/false */ int ObjectMapStateValidXtal(ObjectMapState * ms) { if(ms && ms->Active) { switch (ms->MapSource) { /* these are the only formats which are known to contain xtal information */ case cMapSourceCrystallographic: case cMapSourceCCP4: case cMapSourceBRIX: case cMapSourceGRD: return true; break; } } return false; } /* Map::ValidXtal -- detemines whether the Map is valid * PARAMS * I, Map * state, map's state * RETURNS * true/false */ int ObjectMapValidXtal(ObjectMap * I, int state) { if((state >= 0) && (state < I->NState)) { ObjectMapState *ms = I->State + state; return ObjectMapStateValidXtal(ms); } return false; } /* Map::TransformMatrix -- transform this map's matrix by 'matrix' parameter * PARAMS * I, the map * state, the map's state * matrix, matrix to mult. by * RETURNS * None; updates Map */ void ObjectMapTransformMatrix(ObjectMap * I, int state, double *matrix) { for(StateIterator iter(I->Obj.G, I->Obj.Setting, state, I->NState); iter.next();) { ObjectMapState *ms = I->State + iter.state; if(ms->Active) { ObjectStateTransformMatrix(&ms->State, matrix); } } ObjectMapUpdateExtents(I); } /* Map::ResetMatrix -- reset's the map's matrix for the given state * PARAMS * I, the map * state, the map's state */ void ObjectMapResetMatrix(ObjectMap * I, int state) { for(StateIterator iter(I->Obj.G, I->Obj.Setting, state, I->NState); iter.next();) { ObjectMapState *ms = I->State + iter.state; if(ms->Active) { ObjectStateResetMatrix(&ms->State); } } ObjectMapUpdateExtents(I); } /* Map::GetMatrix * PARAMS * I, the map * state, the map's state * matrix, ptr to the the buffer to copy the data into * RETURNS * true/false; updates matrix parameter */ int ObjectMapGetMatrix(ObjectMap * I, int state, double **matrix) { ObjectMapState *ms = ObjectMapGetState(I, state); if(ms->Active) { *matrix = ObjectStateGetMatrix(&ms->State); return true; } return false; } /* Map::SetMatrix * PARAMS * I, the map * state, the map's state * matrix, the matrix to set to */ int ObjectMapSetMatrix(ObjectMap * I, int state, double *matrix) { bool result = false; for(StateIterator iter(I->Obj.G, I->Obj.Setting, state, I->NState); iter.next();) { ObjectMapState *ms = I->State + iter.state; if(ms->Active) { ObjectStateSetMatrix(&ms->State, matrix); result = true; } } return result; } /* MapState::GetExcludedStats -- * PARARMS * G, usual PyMOL globals * ms, MapState * vert_vla, variable length array of vertices * beyond, radius of exclusion * within, radius of inlcusion * level, map level * * RETURNS * number of exluded pts? */ int ObjectMapStateGetExcludedStats(PyMOLGlobals * G, ObjectMapState * ms, float *vert_vla, float beyond, float within, float *level) { double sum = 0.0, sumsq = 0.0; float mean, stdev; int cnt = 0; int list_size; float cutoff = beyond; MapType *voxelmap = NULL; /* size of the VLA */ if(vert_vla) { list_size = VLAGetSize(vert_vla) / 3; } else { list_size = 0; } if(cutoff < within) cutoff = within; /* make a new map from the VLA .............. */ if(list_size) voxelmap = MapNew(G, -cutoff, vert_vla, list_size, NULL); if(voxelmap || (!list_size)) { int a, b, c; int h, k, l, i, j; int *fdim = ms->FDim; float *v, f_val; int within_flag, within_default = false; int beyond_flag; Isofield *field = ms->Field; if(list_size) MapSetupExpress(voxelmap); within_flag = true; beyond_flag = true; if(within < R_SMALL4) within_default = true; for(c = 0; c < fdim[2]; c++) { for(b = 0; b < fdim[1]; b++) { for(a = 0; a < fdim[0]; a++) { if(list_size) { within_flag = within_default; beyond_flag = true; v = F4Ptr(field->points, a, b, c, 0); MapLocus(voxelmap, v, &h, &k, &l); i = *(MapEStart(voxelmap, h, k, l)); if(i) { j = voxelmap->EList[i++]; while(j >= 0) { if(!within_flag) { if(within3f(vert_vla + 3 * j, v, within)) { within_flag = true; } } if(within3f(vert_vla + 3 * j, v, beyond)) { beyond_flag = false; break; } j = voxelmap->EList[i++]; } } } if(within_flag && beyond_flag) { /* point isn't too close to any vertex */ f_val = F3(field->data, a, b, c); sum += f_val; sumsq += (f_val * f_val); cnt++; } } } } if(voxelmap) MapFree(voxelmap); } if(cnt) { mean = (float) (sum / cnt); stdev = (float) sqrt1d((sumsq - (sum * sum / cnt)) / (cnt)); level[1] = mean; level[0] = mean - stdev; level[2] = mean + stdev; } return cnt; } /* MapState::ObjectMapStateGetDataRange -- get min/max from the scalar field * PARAMS * G * usual PyMOLGlobals * ms * I * RETURNS * npts, but stores range in min/max */ int ObjectMapStateGetDataRange(PyMOLGlobals * G, ObjectMapState * ms, float *min, float *max) { float max_val = 0.0F, min_val = 0.0F; CField *data = ms->Field->data; int cnt = data->dim[0] * data->dim[1] * data->dim[2]; float *raw_data = (float *) data->data; if(cnt) { int a; min_val = (max_val = *(raw_data++)); for(a = 1; a < cnt; a++) { double f_val = *(raw_data++); if(min_val > f_val) min_val = f_val; if(max_val < f_val) max_val = f_val; } } *min = min_val; *max = max_val; return cnt; } /* MapState::ObjectMapStateGetHistogram -- compute a map histogram * * INPUT PARAMS * * h_points - number of histogram points * limit - limit the data to (mean - limit * stdev, mean + limit * stdev) * if limit <= 0, don't trim the histogram * min_arg, max_arg - limit the data, has priority over "limit" param; * Unused if min_arg==max_arg * * OUTPUT PARAMS * * histogram - output histogram buffer. first four values are * minimum, maximum, mean and stdev, followed by n_points * of non-normalized histogram counts. */ int ObjectMapStateGetHistogram(PyMOLGlobals * G, ObjectMapState * ms, int n_points, float limit, float *histogram, float min_arg, float max_arg) { float max_val = 0.0f, min_val = 0.0f; float sum = 0.0f, sumsq = 0.0f; float min_his, max_his, irange, mean, stdev; int pos; CField *data = ms->Field->data; int cnt = data->dim[0] * data->dim[1] * data->dim[2]; float *raw_data = (float *) data->data; if(cnt) { int a; // compute min/max/mean/stdev sum = min_val = (max_val = *(raw_data++)); sumsq = sum*sum; for(a = 1; a < cnt; a++) { double f_val = *(raw_data++); if(min_val > f_val) min_val = f_val; if(max_val < f_val) max_val = f_val; sum += f_val; sumsq += f_val*f_val; } mean = (float) (sum / cnt); stdev = (float) sqrt1d((sumsq - (sum * sum / cnt)) / (cnt)); // adjust min/max to limit if (min_arg != max_arg) { min_his = min_arg; max_his = max_arg; } else if (limit > 0.0F) { min_his = mean - limit*stdev; if (min_his < min_val) min_his = min_val; max_his = mean + limit*stdev; if (max_his > max_val) max_his = max_val; } else { min_his = min_val; max_his = max_val; } // Compute the histogram if(n_points > 0) { irange = (float)(n_points-1) / (max_his - min_his); for (a = 0; a < n_points; a++) histogram[a+4] = 0.0f; raw_data = (float *) data->data; for (a = 0; a < cnt; a++) { double f_val = *(raw_data++); pos = (int)(irange * (f_val-min_his)); if (pos >= 0 && pos < n_points) { histogram[pos+4] += 1.0; } } } histogram[0] = min_his; histogram[1] = max_his; histogram[2] = mean; histogram[3] = stdev; } else { histogram[0] = 0.0; histogram[1] = 1.0; histogram[2] = 1.0; histogram[3] = 1.0; } return cnt; } int ObjectMapInterpolate(ObjectMap * I, int state, const float *array, float *result, int *flag, int n) { int ok = false; float txf_buffer[3]; float *txf = txf_buffer; ObjectMapState *ms = ObjectMapGetState(I, state); if(ms && ms->Active) { double *matrix = ObjectStateGetInvMatrix(&ms->State); if(matrix) { /* we have to back-transform points */ if(n > 1) { txf = Alloc(float, 3 * n); } const float *src = array; float *dst = txf; array = txf; for (int nn = n; nn--; src += 3, dst += 3) { transform44d3f(matrix, src, dst); } } ok = ObjectMapStateInterpolate(ms, array, result, flag, n); } if(txf != txf_buffer) FreeP(txf); return (ok); } static int ObjectMapStateTrim(PyMOLGlobals * G, ObjectMapState * ms, float *mn, float *mx, int quiet) { int div[3]; int min[3]; int fdim[4]; int new_min[3], new_max[3], new_fdim[3]; int a, b, c, d, e, f; float *vt, *vr; float v[3]; float grid[3]; Isofield *field; int result = true; float orig_size = 1.0F; float new_size = 1.0F; if(ObjectMapStateValidXtal(ms)) { float tst[3], frac_tst[3]; float frac_mn[3]; float frac_mx[3]; int hit_flag = false; /* compute the limiting box extents in fractional space */ for(a = 0; a < 8; a++) { tst[0] = (a & 0x1) ? mn[0] : mx[0]; tst[1] = (a & 0x2) ? mn[1] : mx[1]; tst[2] = (a & 0x4) ? mn[2] : mx[2]; transform33f3f(ms->Symmetry->Crystal->RealToFrac, tst, frac_tst); if(!a) { copy3f(frac_tst, frac_mn); copy3f(frac_tst, frac_mx); } else { for(b = 0; b < 3; b++) { frac_mn[b] = (frac_mn[b] > frac_tst[b]) ? frac_tst[b] : frac_mn[b]; frac_mx[b] = (frac_mx[b] < frac_tst[b]) ? frac_tst[b] : frac_mx[b]; } } } for(a = 0; a < 3; a++) { div[a] = ms->Div[a]; min[a] = ms->Min[a]; fdim[a] = ms->FDim[a]; } fdim[3] = 3; { int first_flag[3] = { false, false, false }; for(d = 0; d < 3; d++) { int tst_min, tst_max; float v_min, v_max; for(c = 0; c < (fdim[d] - 1); c++) { tst_min = c + min[d]; tst_max = tst_min + 1; v_min = tst_min / ((float) div[d]); v_max = tst_max / ((float) div[d]); if(((v_min >= frac_mn[d]) && (v_min <= frac_mx[d])) || ((v_max >= frac_mn[d]) && (v_max <= frac_mx[d]))) { if(!first_flag[d]) { first_flag[d] = true; new_min[d] = tst_min; new_max[d] = tst_max; } else { new_min[d] = (new_min[d] > tst_min) ? tst_min : new_min[d]; new_max[d] = (new_max[d] < tst_max) ? tst_max : new_max[d]; } } } new_fdim[d] = (new_max[d] - new_min[d]) + 1; } hit_flag = first_flag[0] && first_flag[1] & first_flag[2]; } if(hit_flag) hit_flag = (new_fdim[0] != fdim[0]) || (new_fdim[1] != fdim[1]) || (new_fdim[2] != fdim[2]); if(hit_flag) { orig_size = fdim[0] * fdim[1] * fdim[2]; new_size = new_fdim[0] * new_fdim[1] * new_fdim[2]; field = IsosurfFieldAlloc(G, new_fdim); field->save_points = ms->Field->save_points; for(c = 0; c < new_fdim[2]; c++) { f = c + (new_min[2] - min[2]); for(b = 0; b < new_fdim[1]; b++) { e = b + (new_min[1] - min[1]); for(a = 0; a < new_fdim[0]; a++) { d = a + (new_min[0] - min[0]); vt = F4Ptr(field->points, a, b, c, 0); vr = F4Ptr(ms->Field->points, d, e, f, 0); copy3f(vr, vt); F3(field->data, a, b, c) = F3(ms->Field->data, d, e, f); } } } IsosurfFieldFree(G, ms->Field); for(a = 0; a < 3; a++) { ms->Min[a] = new_min[a]; ms->Max[a] = new_max[a]; ms->FDim[a] = new_fdim[a]; } ms->Field = field; /* compute new extents */ v[2] = (ms->Min[2]) / ((float) ms->Div[2]); v[1] = (ms->Min[1]) / ((float) ms->Div[1]); v[0] = (ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMin); v[2] = ((ms->FDim[2] - 1) + ms->Min[2]) / ((float) ms->Div[2]); v[1] = ((ms->FDim[1] - 1) + ms->Min[1]) / ((float) ms->Div[1]); v[0] = ((ms->FDim[0] - 1) + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMax); /* new corner */ { float vv[3]; d = 0; for(c = 0; c < ms->FDim[2]; c += (ms->FDim[2] - 1)) { v[2] = (c + ms->Min[2]) / ((float) ms->Div[2]); for(b = 0; b < ms->FDim[1]; b += (ms->FDim[1] - 1)) { v[1] = (b + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < ms->FDim[0]; a += (ms->FDim[0] - 1)) { v[0] = (a + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vv); copy3f(vv, ms->Corner + 3 * d); d++; } } } } result = true; } } else { /* not a crystal map */ int hit_flag = false; float *origin = ms->Origin; for(a = 0; a < 3; a++) { min[a] = ms->Min[a]; grid[a] = ms->Grid[a]; fdim[a] = ms->FDim[a]; } fdim[3] = 3; { int first_flag[3] = { false, false, false }; for(d = 0; d < 3; d++) { int tst_min, tst_max; float v_min, v_max; for(c = 0; c < (fdim[d] - 1); c++) { tst_min = c + min[d]; tst_max = tst_min + 1; v_min = origin[d] + grid[d] * (tst_min); v_max = origin[d] + grid[d] * (tst_max); if(((v_min >= mn[d]) && (v_min <= mx[d])) || ((v_max >= mn[d]) && (v_max <= mx[d]))) { if(!first_flag[d]) { first_flag[d] = true; hit_flag = true; new_min[d] = tst_min; new_max[d] = tst_max; } else { new_min[d] = (new_min[d] > tst_min) ? tst_min : new_min[d]; new_max[d] = (new_max[d] < tst_max) ? tst_max : new_max[d]; } } } new_fdim[d] = (new_max[d] - new_min[d]) + 1; } hit_flag = first_flag[0] && first_flag[1] & first_flag[2]; } if(hit_flag) hit_flag = (new_fdim[0] != fdim[0]) || (new_fdim[1] != fdim[1]) || (new_fdim[2] != fdim[2]); if(hit_flag) { orig_size = fdim[0] * fdim[1] * fdim[2]; new_size = new_fdim[0] * new_fdim[1] * new_fdim[2]; field = IsosurfFieldAlloc(G, new_fdim); field->save_points = ms->Field->save_points; for(c = 0; c < new_fdim[2]; c++) { f = c + (new_min[2] - min[2]); for(b = 0; b < new_fdim[1]; b++) { e = b + (new_min[1] - min[1]); for(a = 0; a < new_fdim[0]; a++) { d = a + (new_min[0] - min[0]); vt = F4Ptr(field->points, a, b, c, 0); vr = F4Ptr(ms->Field->points, d, e, f, 0); copy3f(vr, vt); F3(field->data, a, b, c) = F3(ms->Field->data, d, e, f); } } } IsosurfFieldFree(G, ms->Field); for(a = 0; a < 3; a++) { ms->Min[a] = new_min[a]; ms->Max[a] = new_max[a]; ms->FDim[a] = new_fdim[a]; if(ms->Dim) ms->Dim[a] = new_fdim[a]; } ms->Field = field; for(e = 0; e < 3; e++) { ms->ExtentMin[e] = ms->Origin[e] + ms->Grid[e] * ms->Min[e]; ms->ExtentMax[e] = ms->Origin[e] + ms->Grid[e] * ms->Max[e]; } d = 0; for(c = 0; c < ms->FDim[2]; c += ms->FDim[2] - 1) { v[2] = ms->Origin[2] + ms->Grid[2] * (c + ms->Min[2]); for(b = 0; b < ms->FDim[1]; b += ms->FDim[1] - 1) { v[1] = ms->Origin[1] + ms->Grid[1] * (b + ms->Min[1]); for(a = 0; a < ms->FDim[0]; a += ms->FDim[0] - 1) { v[0] = ms->Origin[0] + ms->Grid[0] * (a + ms->Min[0]); copy3f(v, ms->Corner + 3 * d); d++; } } } result = true; } } if(result && (!quiet)) { PRINTFB(G, FB_ObjectMap, FB_Actions) " ObjectMap: Map volume reduced by %2.0f%%.\n", (100 * (orig_size - new_size)) / orig_size ENDFB(G); } return result; } static int ObjectMapStateDouble(PyMOLGlobals * G, ObjectMapState * ms) { int div[3]; int min[3]; int max[3]; int fdim[4]; int a, b, c; float v[3], vr[3]; float *vt; float x, y, z; float grid[3]; Isofield *field; if(ObjectMapStateValidXtal(ms)) { for(a = 0; a < 3; a++) { div[a] = ms->Div[a] * 2; min[a] = ms->Min[a] * 2; max[a] = ms->Max[a] * 2; fdim[a] = ms->FDim[a] * 2 - 1; } fdim[3] = 3; field = IsosurfFieldAlloc(G, fdim); field->save_points = ms->Field->save_points; for(c = 0; c < fdim[2]; c++) { v[2] = (c + min[2]) / ((float) div[2]); z = (c & 0x1) ? 0.5F : 0.0F; for(b = 0; b < fdim[1]; b++) { v[1] = (b + min[1]) / ((float) div[1]); y = (b & 0x1) ? 0.5F : 0.0F; for(a = 0; a < fdim[0]; a++) { v[0] = (a + min[0]) / ((float) div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); x = (a & 0x1) ? 0.5F : 0.0F; vt = F4Ptr(field->points, a, b, c, 0); copy3f(vr, vt); if((a & 0x1) || (b & 0x1) || (c & 0x1)) { F3(field->data, a, b, c) = FieldInterpolatef(ms->Field->data, a / 2, b / 2, c / 2, x, y, z); } else { F3(field->data, a, b, c) = F3(ms->Field->data, a / 2, b / 2, c / 2); } } } } IsosurfFieldFree(G, ms->Field); for(a = 0; a < 3; a++) { ms->Min[a] = min[a]; ms->Max[a] = max[a]; ms->FDim[a] = fdim[a]; ms->Div[a] = div[a]; } ms->Field = field; } else { for(a = 0; a < 3; a++) { grid[a] = ms->Grid[a] / 2.0F; min[a] = ms->Min[a] * 2; max[a] = ms->Max[a] * 2; fdim[a] = ms->FDim[a] * 2 - 1; } fdim[3] = 3; field = IsosurfFieldAlloc(G, fdim); field->save_points = ms->Field->save_points; for(c = 0; c < fdim[2]; c++) { v[2] = ms->Origin[2] + grid[2] * (c + min[2]); z = (c & 0x1) ? 0.5F : 0.0F; for(b = 0; b < fdim[1]; b++) { v[1] = ms->Origin[1] + grid[1] * (b + min[1]); y = (b & 0x1) ? 0.5F : 0.0F; for(a = 0; a < fdim[0]; a++) { v[0] = ms->Origin[0] + grid[0] * (a + min[0]); x = (a & 0x1) ? 0.5F : 0.0F; vt = F4Ptr(field->points, a, b, c, 0); copy3f(v, vt); if((a & 0x1) || (b & 0x1) || (c & 0x1)) { F3(field->data, a, b, c) = FieldInterpolatef(ms->Field->data, a / 2, b / 2, c / 2, x, y, z); } else { F3(field->data, a, b, c) = F3(ms->Field->data, a / 2, b / 2, c / 2); } } } } IsosurfFieldFree(G, ms->Field); for(a = 0; a < 3; a++) { ms->Min[a] = min[a]; ms->Max[a] = max[a]; ms->FDim[a] = fdim[a]; if(ms->Dim) ms->Dim[a] = fdim[a]; if(ms->Grid) ms->Grid[a] = grid[a]; } ms->Field = field; } return 1; } static int ObjectMapStateHalve(PyMOLGlobals * G, ObjectMapState * ms, int smooth) { int div[3]; int min[3]; int max[3]; int fdim[4]; int a, b, c; float v[3], vr[3]; float *vt; float x, y, z; float grid[3]; Isofield *field; if(ObjectMapStateValidXtal(ms)) { int *old_div, *old_min, *old_max; int a_2, b_2, c_2; for(a = 0; a < 3; a++) { div[a] = ms->Div[a] / 2; /* note that when Div is odd, a one-cell extrapolation will occur in order to preserve map size and get us onto a even number of sampling intervals for the cell */ min[a] = ms->Min[a] / 2; max[a] = ms->Max[a] / 2; while((min[a] * 2) < ms->Min[a]) min[a]++; while((max[a] * 2) > ms->Max[a]) max[a]--; fdim[a] = (max[a] - min[a]) + 1; } fdim[3] = 3; old_div = ms->Div; old_min = ms->Min; old_max = ms->Max; if(smooth) FieldSmooth3f(ms->Field->data); field = IsosurfFieldAlloc(G, fdim); field->save_points = ms->Field->save_points; /* printf("old_div %d %d %d\n",old_div[0],old_div[1],old_div[2]); printf("old_min %d %d %d\n",old_min[0],old_min[1],old_min[2]); printf("min %d %d %d\n",min[0],min[1],min[2]); printf("%d %d %d\n",ms->FDim[0],ms->FDim[1],ms->FDim[2]); */ for(c = 0; c < fdim[2]; c++) { v[2] = (c + min[2]) / ((float) div[2]); c_2 = (c + min[2]) * 2 - old_min[2]; z = (v[2] - ((c_2 + old_min[2]) / (float) old_div[2])) * old_div[2]; if(c_2 >= old_max[2]) { c_2 = old_max[2] - 1; z = (v[2] - ((c_2 + old_min[2]) / (float) old_div[2])) * old_div[2]; } for(b = 0; b < fdim[1]; b++) { v[1] = (b + min[1]) / ((float) div[1]); b_2 = (b + min[1]) * 2 - old_min[1]; y = (v[1] - ((b_2 + old_min[1]) / (float) old_div[1])) * old_div[1]; if(b_2 >= old_max[1]) { b_2 = old_max[1] - 1; y = (v[1] - ((b_2 + old_min[1]) / (float) old_div[1])) * old_div[1]; } for(a = 0; a < fdim[0]; a++) { v[0] = (a + min[0]) / ((float) div[0]); a_2 = (a + min[0]) * 2 - old_min[0]; x = (v[0] - ((a_2 + old_min[0]) / (float) old_div[0])) * old_div[0]; if(a_2 >= old_max[0]) { a_2 = old_max[0] - 1; x = (v[0] - ((a_2 + old_min[0]) / (float) old_div[0])) * old_div[0]; } transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); vt = F4Ptr(field->points, a, b, c, 0); copy3f(vr, vt); F3(field->data, a, b, c) = FieldInterpolatef(ms->Field->data, a_2, b_2, c_2, x, y, z); } } } IsosurfFieldFree(G, ms->Field); for(a = 0; a < 3; a++) { ms->Min[a] = min[a]; ms->Max[a] = max[a]; ms->FDim[a] = fdim[a]; ms->Div[a] = div[a]; } ms->Field = field; /* compute new extents */ v[2] = (ms->Min[2]) / ((float) ms->Div[2]); v[1] = (ms->Min[1]) / ((float) ms->Div[1]); v[0] = (ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMin); v[2] = ((ms->FDim[2] - 1) + ms->Min[2]) / ((float) ms->Div[2]); v[1] = ((ms->FDim[1] - 1) + ms->Min[1]) / ((float) ms->Div[1]); v[0] = ((ms->FDim[0] - 1) + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMax); /* new corner */ { float vv[3]; int d = 0; for(c = 0; c < ms->FDim[2]; c += (ms->FDim[2] - 1)) { v[2] = (c + ms->Min[2]) / ((float) ms->Div[2]); for(b = 0; b < ms->FDim[1]; b += (ms->FDim[1] - 1)) { v[1] = (b + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < ms->FDim[0]; a += (ms->FDim[0] - 1)) { v[0] = (a + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vv); copy3f(vv, ms->Corner + 3 * d); d++; } } } } } else { for(a = 0; a < 3; a++) { grid[a] = ms->Grid[a] * 2.0F; min[a] = ms->Min[a] / 2; max[a] = ms->Max[a] / 2; fdim[a] = (ms->FDim[a] + 1) / 2; } fdim[3] = 3; field = IsosurfFieldAlloc(G, fdim); field->save_points = ms->Field->save_points; for(c = 0; c < fdim[2]; c++) { v[2] = ms->Origin[2] + grid[2] * (c + min[2]); for(b = 0; b < fdim[1]; b++) { v[1] = ms->Origin[1] + grid[1] * (b + min[1]); for(a = 0; a < fdim[0]; a++) { v[0] = ms->Origin[0] + grid[0] * (a + min[0]); vt = F4Ptr(field->points, a, b, c, 0); copy3f(v, vt); F3(field->data, a, b, c) = F3(ms->Field->data, a * 2, b * 2, c * 2); } } } IsosurfFieldFree(G, ms->Field); for(a = 0; a < 3; a++) { ms->Min[a] = min[a]; ms->Max[a] = max[a]; ms->FDim[a] = fdim[a]; if(ms->Dim) ms->Dim[a] = fdim[a]; if(ms->Grid) ms->Grid[a] = grid[a]; } ms->Field = field; } return 1; } int ObjectMapTrim(ObjectMap * I, int state, float *mn, float *mx, int quiet) { int a; int result = true; int update = false; /* TO DO: convert mn and mx into map local coordinates if map itself is transformed... */ if(state < 0) { for(a = 0; a < I->NState; a++) { if(I->State[a].Active) { if(ObjectMapStateTrim(I->Obj.G, &I->State[a], mn, mx, quiet)) update = true; else result = false; } } } else if((state >= 0) && (state < I->NState) && (I->State[state].Active)) { update = result = ObjectMapStateTrim(I->Obj.G, &I->State[state], mn, mx, quiet); } else { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Errors) " ObjectMap-Error: invalidate state.\n" ENDFB(I->Obj.G); result = false; } if(update) ObjectMapUpdateExtents(I); return (result); } int ObjectMapDouble(ObjectMap * I, int state) { int a; int result = true; if(state < 0) { for(a = 0; a < I->NState; a++) { if(I->State[a].Active) result = result && ObjectMapStateDouble(I->Obj.G, &I->State[a]); } } else if((state >= 0) && (state < I->NState) && (I->State[state].Active)) { ObjectMapStateDouble(I->Obj.G, &I->State[state]); } else { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Errors) " ObjectMap-Error: invalidate state.\n" ENDFB(I->Obj.G); result = false; } return (result); } int ObjectMapHalve(ObjectMap * I, int state, int smooth) { int a; int result = true; if(state < 0) { for(a = 0; a < I->NState; a++) { if(I->State[a].Active) result = result && ObjectMapStateHalve(I->Obj.G, &I->State[a], smooth); } } else if((state >= 0) && (state < I->NState) && (I->State[state].Active)) { ObjectMapStateHalve(I->Obj.G, &I->State[state], smooth); } else { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Errors) " ObjectMap-Error: invalidate state.\n" ENDFB(I->Obj.G); result = false; } ObjectMapUpdateExtents(I); return (result); } int ObjectMapStateContainsPoint(ObjectMapState * ms, float *point) { int result = false; float x, y, z; int x_floor, y_floor, z_floor; int x_ceil, y_ceil, z_ceil; if(ObjectMapStateValidXtal(ms)) { float frac[3]; transform33f3f(ms->Symmetry->Crystal->RealToFrac, point, frac); x = (ms->Div[0] * frac[0]); y = (ms->Div[1] * frac[1]); z = (ms->Div[2] * frac[2]); x_floor = floor(x); x_ceil = ceil(x); y_floor = floor(y); y_ceil = ceil(y); z_floor = floor(z); z_ceil = ceil(z); if((x_floor >= ms->Min[0]) && (x_ceil <= ms->Max[0]) && (y_floor >= ms->Min[1]) && (y_ceil <= ms->Max[1]) && (z_floor >= ms->Min[2]) && (z_ceil <= ms->Max[2])) result = true; } else { x = (point[0] - ms->Origin[0]) / ms->Grid[0]; y = (point[1] - ms->Origin[1]) / ms->Grid[1]; z = (point[2] - ms->Origin[2]) / ms->Grid[2]; x_floor = floor(x); x_ceil = ceil(x); y_floor = floor(y); y_ceil = ceil(y); z_floor = floor(z); z_ceil = ceil(z); if((x_floor >= ms->Min[0]) && (x_ceil <= ms->Max[0]) && (y_floor >= ms->Min[1]) && (y_ceil <= ms->Max[1]) && (z_floor >= ms->Min[2]) && (z_ceil <= ms->Max[2])) result = true; if((x >= ms->Min[0]) && (x <= ms->Max[0]) && (y >= ms->Min[1]) && (y <= ms->Max[1]) && (z >= ms->Min[2]) && (z <= ms->Max[2])) result = true; } return (result); } int ObjectMapStateInterpolate(ObjectMapState * ms, const float *array, float *result, int *flag, int n) { int ok = true; const float *inp; int a, b, c; float x, y, z; inp = array; if(ObjectMapStateValidXtal(ms)) { float frac[3]; while(n--) { /* get the fractional coordinate */ transform33f3f(ms->Symmetry->Crystal->RealToFrac, inp, frac); inp += 3; /* compute the effective lattice offset as a function of cell spacing */ x = (ms->Div[0] * frac[0]); y = (ms->Div[1] * frac[1]); z = (ms->Div[2] * frac[2]); /* now separate the integral and fractional parts for interpolation */ a = (int) floor(x + R_SMALL8); b = (int) floor(y + R_SMALL8); c = (int) floor(z + R_SMALL8); x -= a; y -= b; z -= c; if(flag) *flag = 1; /* wrap into the map */ if(a < ms->Min[0]) { if(x < 0.99F) { ok = false; if(flag) *flag = 0; } x = 0.0F; a = ms->Min[0]; } else if(a >= ms->FDim[0] + ms->Min[0] - 1) { if(x > 0.01F) { ok = false; if(flag) *flag = 0; } x = 0.0F; a = ms->FDim[0] + ms->Min[0] - 1; } if(b < ms->Min[1]) { if(y < 0.99F) { ok = false; if(flag) *flag = 0; } y = 0.0F; b = ms->Min[1]; } else if(b >= ms->FDim[1] + ms->Min[1] - 1) { if(y > 0.01F) { ok = false; if(flag) *flag = 0; } y = 0.0F; b = ms->FDim[1] + ms->Min[1] - 1; } if(c < ms->Min[2]) { if(z < 0.99F) { ok = false; if(flag) *flag = 0; } z = 0.0F; c = ms->Min[2]; } else if(c >= ms->FDim[2] + ms->Min[2] - 1) { if(z > 0.01) { ok = false; if(flag) *flag = 0; } z = 0.0F; c = ms->FDim[2] + ms->Min[2] - 1; } /* printf("%d %d %d %8.3f %8.3f %8.3f\n",a,b,c,x,y,z); */ *(result++) = FieldInterpolatef(ms->Field->data, a - ms->Min[0], b - ms->Min[1], c - ms->Min[2], x, y, z); if(flag) flag++; } } else { while(n--) { x = (inp[0] - ms->Origin[0]) / ms->Grid[0]; y = (inp[1] - ms->Origin[1]) / ms->Grid[1]; z = (inp[2] - ms->Origin[2]) / ms->Grid[2]; inp += 3; a = (int) floor(x + R_SMALL8); b = (int) floor(y + R_SMALL8); c = (int) floor(z + R_SMALL8); x -= a; y -= b; z -= c; if(flag) *flag = 1; if(a < ms->Min[0]) { x = 0.0F; a = ms->Min[0]; ok = false; if(flag) *flag = 0; } else if(a >= ms->Max[0]) { x = 1.0F; a = ms->Max[0] - 1; ok = false; if(flag) *flag = 0; } if(b < ms->Min[1]) { y = 0.0F; b = ms->Min[1]; ok = false; if(flag) *flag = 0; } else if(b >= ms->Max[1]) { y = 1.0F; b = ms->Max[1] - 1; ok = false; if(flag) *flag = 0; } if(c < ms->Min[2]) { z = 0.0F; c = ms->Min[2]; ok = false; if(flag) *flag = 0; } else if(c >= ms->Max[2]) { z = 1.0F; c = ms->Max[2] - 1; ok = false; if(flag) *flag = 0; } /* printf("%d %d %d %8.3f %8.3f %8.3f\n",a,b,c,x,y,z); */ *(result++) = FieldInterpolatef(ms->Field->data, a - ms->Min[0], b - ms->Min[1], c - ms->Min[2], x, y, z); if(flag) flag++; } } return (ok); } #ifndef _PYMOL_NOPY static int ObjectMapNumPyArrayToMapState(PyMOLGlobals * G, ObjectMapState * I, PyObject * ary, int quiet); #endif void ObjectMapRegeneratePoints(ObjectMap * om){ int i; for (i=0; i<om->NState;i++){ ObjectMapStateRegeneratePoints(om->State + i); } } void ObjectMapStateRegeneratePoints(ObjectMapState * ms) { int a, b, c, e; float v[3], vr[3]; if(ObjectMapStateValidXtal(ms)) { for(c = 0; c < ms->FDim[2]; c++) { v[2] = (c + ms->Min[2]) / ((float) ms->Div[2]); for(b = 0; b < ms->FDim[1]; b++) { v[1] = (b + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < ms->FDim[0]; a++) { v[0] = (a + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); for(e = 0; e < 3; e++) F4(ms->Field->points, a, b, c, e) = vr[e]; } } } } else { for(c = 0; c < ms->FDim[2]; c++) { v[2] = ms->Origin[2] + ms->Grid[2] * (c + ms->Min[2]); for(b = 0; b < ms->FDim[1]; b++) { v[1] = ms->Origin[1] + ms->Grid[1] * (b + ms->Min[1]); for(a = 0; a < ms->FDim[0]; a++) { v[0] = ms->Origin[0] + ms->Grid[0] * (a + ms->Min[0]); for(e = 0; e < 3; e++) { F4(ms->Field->points, a, b, c, e) = v[e]; } } } } } } static PyObject *ObjectMapStateAsPyList(ObjectMapState * I) { PyObject *result = NULL; result = PyList_New(16); PyList_SetItem(result, 0, PyInt_FromLong(I->Active)); if(I->Symmetry) { PyList_SetItem(result, 1, SymmetryAsPyList(I->Symmetry)); } else { PyList_SetItem(result, 1, PConvAutoNone(Py_None)); } if(I->Origin) { PyList_SetItem(result, 2, PConvFloatArrayToPyList(I->Origin, 3)); } else { PyList_SetItem(result, 2, PConvAutoNone(Py_None)); } if(I->Range) { PyList_SetItem(result, 3, PConvFloatArrayToPyList(I->Range, 3)); } else { PyList_SetItem(result, 3, PConvAutoNone(Py_None)); } if(I->Dim) { PyList_SetItem(result, 4, PConvIntArrayToPyList(I->Dim, 3)); } else { PyList_SetItem(result, 4, PConvAutoNone(Py_None)); } if(I->Grid) { PyList_SetItem(result, 5, PConvFloatArrayToPyList(I->Grid, 3)); } else { PyList_SetItem(result, 5, PConvAutoNone(Py_None)); } PyList_SetItem(result, 6, PConvFloatArrayToPyList(I->Corner, 24)); PyList_SetItem(result, 7, PConvFloatArrayToPyList(I->ExtentMin, 3)); PyList_SetItem(result, 8, PConvFloatArrayToPyList(I->ExtentMax, 3)); PyList_SetItem(result, 9, PyInt_FromLong(I->MapSource)); PyList_SetItem(result, 10, PConvIntArrayToPyList(I->Div, 3)); PyList_SetItem(result, 11, PConvIntArrayToPyList(I->Min, 3)); PyList_SetItem(result, 12, PConvIntArrayToPyList(I->Max, 3)); PyList_SetItem(result, 13, PConvIntArrayToPyList(I->FDim, 4)); PyList_SetItem(result, 14, IsosurfAsPyList(I->State.G, I->Field)); PyList_SetItem(result, 15, ObjectStateAsPyList(&I->State)); return (PConvAutoNone(result)); } static PyObject *ObjectMapAllStatesAsPyList(ObjectMap * I) { PyObject *result = NULL; int a; result = PyList_New(I->NState); for(a = 0; a < I->NState; a++) { if(I->State[a].Active) { PyList_SetItem(result, a, ObjectMapStateAsPyList(I->State + a)); } else { PyList_SetItem(result, a, PConvAutoNone(NULL)); } } return (PConvAutoNone(result)); } static int ObjectMapStateCopy(PyMOLGlobals * G, const ObjectMapState * src, ObjectMapState * I) { int ok = true; if(ok) { I->Active = src->Active; if(I->Active) { /* if(src->Symmetry->Crystal) */ /* I->Symmetry->Crystal = CrystalCopy(src->Symmetry->Crystal); */ /* else */ /* I->Symmetry->Crystal = NULL; */ if(src->Symmetry) I->Symmetry = SymmetryCopy(src->Symmetry); else I->Symmetry = NULL; if(src->Origin) { I->Origin = Alloc(float, 3); if(I->Origin) { copy3f(src->Origin, I->Origin); } } else { I->Origin = NULL; } if(src->Range) { I->Range = Alloc(float, 3); if(I->Range) { copy3f(src->Range, I->Range); } } else { I->Origin = NULL; } if(src->Grid) { I->Grid = Alloc(float, 3); if(I->Grid) { copy3f(src->Grid, I->Grid); } } else { I->Origin = NULL; } if(src->Dim) { I->Dim = Alloc(int, 4); if(I->Dim) { copy3f(src->Dim, I->Dim); } } else { I->Origin = NULL; } { int a; for(a = 0; a < 24; a++) I->Corner[a] = src->Corner[a]; } copy3f(src->ExtentMin, I->ExtentMin); copy3f(src->ExtentMax, I->ExtentMax); I->MapSource = src->MapSource; copy3f(src->Div, I->Div); copy3f(src->Min, I->Min); copy3f(src->Max, I->Max); copy3f(src->FDim, I->FDim); I->Field = IsosurfNewCopy(G, src->Field); ObjectStateCopy(&I->State, &src->State); if(ok) ObjectMapStateRegeneratePoints(I); } } return (ok); } static int ObjectMapStateFromPyList(PyMOLGlobals * G, ObjectMapState * I, PyObject * list) { int ok = true; int ll = 0; PyObject *tmp; if(ok) ok = (list != NULL); if(ok) { if(!PyList_Check(list)) I->Active = false; else { if(ok) ok = PyList_Check(list); if(ok) ll = PyList_Size(list); /* TO SUPPORT BACKWARDS COMPATIBILITY... Always check ll when adding new PyList_GetItem's */ if(ok) ok = PConvPyIntToInt(PyList_GetItem(list, 0), &I->Active); if(ok) { tmp = PyList_GetItem(list, 1); if(tmp == Py_None) I->Symmetry = NULL; else ok = ((I->Symmetry = SymmetryNewFromPyList(G, tmp)) != NULL); } if(ok) { tmp = PyList_GetItem(list, 2); if(tmp == Py_None) I->Origin = NULL; else ok = PConvPyListToFloatArray(tmp, &I->Origin); } if(ok) { tmp = PyList_GetItem(list, 3); if(tmp == Py_None) I->Range = NULL; else ok = PConvPyListToFloatArray(tmp, &I->Range); } if(ok) { tmp = PyList_GetItem(list, 4); if(tmp == Py_None) I->Dim = NULL; else ok = PConvPyListToIntArray(tmp, &I->Dim); } if(ok) { tmp = PyList_GetItem(list, 5); if(tmp == Py_None) I->Grid = NULL; else ok = PConvPyListToFloatArray(tmp, &I->Grid); } if(ok) ok = PConvPyListToFloatArrayInPlace(PyList_GetItem(list, 6), I->Corner, 24); if(ok) ok = PConvPyListToFloatArrayInPlace(PyList_GetItem(list, 7), I->ExtentMin, 3); if(ok) ok = PConvPyListToFloatArrayInPlace(PyList_GetItem(list, 8), I->ExtentMax, 3); if(ok) ok = PConvPyIntToInt(PyList_GetItem(list, 9), &I->MapSource); if(ok) ok = PConvPyListToIntArrayInPlace(PyList_GetItem(list, 10), I->Div, 3); if(ok) ok = PConvPyListToIntArrayInPlace(PyList_GetItem(list, 11), I->Min, 3); if(ok) ok = PConvPyListToIntArrayInPlace(PyList_GetItem(list, 12), I->Max, 3); if(ok) ok = PConvPyListToIntArrayInPlace(PyList_GetItem(list, 13), I->FDim, 4); if(ok) ok = ((I->Field = IsosurfNewFromPyList(G, PyList_GetItem(list, 14))) != NULL); if(ok && (ll > 15)) ok = ObjectStateFromPyList(G, PyList_GetItem(list, 15), &I->State); if(ok) ObjectMapStateRegeneratePoints(I); } } return (ok); } static int ObjectMapAllStatesFromPyList(ObjectMap * I, PyObject * list) { int ok = true; int a; VLACheck(I->State, ObjectMapState, I->NState); if(ok) ok = PyList_Check(list); if(ok) { for(a = 0; a < I->NState; a++) { ok = ObjectMapStateFromPyList(I->Obj.G, I->State + a, PyList_GetItem(list, a)); if(!ok) break; } } return (ok); } PyObject *ObjectMapAsPyList(ObjectMap * I) { PyObject *result = NULL; result = PyList_New(3); PyList_SetItem(result, 0, ObjectAsPyList(&I->Obj)); PyList_SetItem(result, 1, PyInt_FromLong(I->NState)); PyList_SetItem(result, 2, ObjectMapAllStatesAsPyList(I)); return (PConvAutoNone(result)); } int ObjectMapNewFromPyList(PyMOLGlobals * G, PyObject * list, ObjectMap ** result) { int ok = true; ObjectMap *I = NULL; (*result) = NULL; if(ok) ok = (list != NULL); if(ok) ok = PyList_Check(list); /* TO SUPPORT BACKWARDS COMPATIBILITY... Always check ll when adding new PyList_GetItem's */ I = ObjectMapNew(G); if(ok) ok = (I != NULL); if(ok) ok = ObjectFromPyList(G, PyList_GetItem(list, 0), &I->Obj); if(ok) ok = PConvPyIntToInt(PyList_GetItem(list, 1), &I->NState); if(ok) ok = ObjectMapAllStatesFromPyList(I, PyList_GetItem(list, 2)); if(ok) { (*result) = I; ObjectMapUpdateExtents(I); } else { /* cleanup? */ } return (ok); } int ObjectMapNewCopy(PyMOLGlobals * G, const ObjectMap * src, ObjectMap ** result, int source_state, int target_state) { int ok = true; ObjectMap *I = NULL; I = ObjectMapNew(G); if(ok) ok = (I != NULL); if(ok) ok = ObjectCopyHeader(&I->Obj, &src->Obj); if(ok) { if(source_state == -1) { /* all states */ int state; I->NState = src->NState; VLACheck(I->State, ObjectMapState, I->NState); for(state = 0; state < src->NState; state++) { ok = ObjectMapStateCopy(G, src->State + state, I->State + state); } } else { if(target_state < 0) target_state = 0; if(source_state < 0) source_state = 0; VLACheck(I->State, ObjectMapState, target_state); if(source_state < src->NState) { ok = ObjectMapStateCopy(G, src->State + source_state, I->State + target_state); if(I->NState < target_state) I->NState = target_state; } else { ok = false; /* to do */ } } } if(ok) *result = I; return ok; } ObjectMapState *ObjectMapGetState(ObjectMap * I, int state) { for(StateIterator iter(I->Obj.G, I->Obj.Setting, state, I->NState); iter.next();) { return I->State + iter.state; } return NULL; } ObjectMapState *ObjectMapStatePrime(ObjectMap * I, int state) { ObjectMapState *ms = NULL; if(state < 0) state = I->NState; if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(I->Obj.G, ms); return (ms); } ObjectMapState *ObjectMapStateGetActive(ObjectMap * I, int state) { ObjectMapState *ms = NULL; if(state >= 0) { if(state < I->NState) { ms = &I->State[state]; if(!ms->Active) ms = NULL; } } return (ms); } void ObjectMapUpdateExtents(ObjectMap * I) { int a; float *min_ext, *max_ext; float tr_min[3], tr_max[3]; I->Obj.ExtentFlag = false; for(a = 0; a < I->NState; a++) { ObjectMapState *ms = I->State + a; if(ms->Active) { if(ms->State.Matrix) { transform44d3f(ms->State.Matrix, ms->ExtentMin, tr_min); transform44d3f(ms->State.Matrix, ms->ExtentMax, tr_max); { float tmp; int a; for(a = 0; a < 3; a++) if(tr_min[a] > tr_max[a]) { tmp = tr_min[a]; tr_min[a] = tr_max[a]; tr_max[a] = tmp; } } min_ext = tr_min; max_ext = tr_max; } else { min_ext = ms->ExtentMin; max_ext = ms->ExtentMax; } if(!I->Obj.ExtentFlag) { copy3f(min_ext, I->Obj.ExtentMin); copy3f(max_ext, I->Obj.ExtentMax); I->Obj.ExtentFlag = true; } else { min3f(min_ext, I->Obj.ExtentMin, I->Obj.ExtentMin); max3f(max_ext, I->Obj.ExtentMax, I->Obj.ExtentMax); } } } if(I->Obj.TTTFlag && I->Obj.ExtentFlag) { const float *ttt; double tttd[16]; if(ObjectGetTTT(&I->Obj, &ttt, -1)) { convertTTTfR44d(ttt, tttd); MatrixTransformExtentsR44d3f(tttd, I->Obj.ExtentMin, I->Obj.ExtentMax, I->Obj.ExtentMin, I->Obj.ExtentMax); } } PRINTFD(I->Obj.G, FB_ObjectMap) " ObjectMapUpdateExtents-DEBUG: ExtentFlag %d\n", I->Obj.ExtentFlag ENDFD; } void ObjectMapStateClamp(ObjectMapState * I, float clamp_floor, float clamp_ceiling) { int a, b, c; float *fp; for(a = 0; a < I->FDim[0]; a++) for(b = 0; b < I->FDim[1]; b++) for(c = 0; c < I->FDim[2]; c++) { fp = F3Ptr(I->Field->data, a, b, c); if(*fp < clamp_floor) *fp = clamp_floor; else if(*fp > clamp_ceiling) *fp = clamp_ceiling; } } int ObjectMapStateSetBorder(ObjectMapState * I, float level) { int result = true; int a, b, c; c = I->FDim[2] - 1; for(a = 0; a < I->FDim[0]; a++) for(b = 0; b < I->FDim[1]; b++) { F3(I->Field->data, a, b, 0) = level; F3(I->Field->data, a, b, c) = level; } a = I->FDim[0] - 1; for(b = 0; b < I->FDim[1]; b++) for(c = 0; c < I->FDim[2]; c++) { F3(I->Field->data, 0, b, c) = level; F3(I->Field->data, a, b, c) = level; } b = I->FDim[1] - 1; for(a = 0; a < I->FDim[0]; a++) for(c = 0; c < I->FDim[2]; c++) { F3(I->Field->data, a, 0, c) = level; F3(I->Field->data, a, b, c) = level; } return (result); } void ObjectMapStatePurge(PyMOLGlobals * G, ObjectMapState * I) { ObjectStatePurge(&I->State); if(I->Field) { IsosurfFieldFree(G, I->Field); I->Field = NULL; } FreeP(I->Origin); FreeP(I->Dim); FreeP(I->Range); FreeP(I->Grid); CGOFree(I->shaderCGO); if(I->Symmetry) { SymmetryFree(I->Symmetry); I->Symmetry = NULL; } I->Active = false; } static void ObjectMapFree(ObjectMap * I) { int a; for(a = 0; a < I->NState; a++) { if(I->State[a].Active) ObjectMapStatePurge(I->Obj.G, I->State + a); } VLAFreeP(I->State); ObjectPurge(&I->Obj); OOFreeP(I); } static void ObjectMapUpdate(ObjectMap * I) { if(!I->Obj.ExtentFlag) { ObjectMapUpdateExtents(I); if(I->Obj.ExtentFlag) SceneInvalidate(I->Obj.G); } } static void ObjectMapInvalidate(ObjectMap * I, int rep, int level, int state) { if(level >= cRepInvExtents) { I->Obj.ExtentFlag = false; } if((rep < 0) || (rep == cRepDot)) { int a; for(a = 0; a < I->NState; a++) { if(I->State[a].Active) I->State[a].have_range = false; CGOFree(I->State[a].shaderCGO); } } SceneInvalidate(I->Obj.G); } /* Has no prototype */ static CGO* ObjectMapCGOGenerate(PyMOLGlobals *G, float* corner) { int ok = true; CGO *convertCGO = NULL; CGO *shaderCGO = CGONewSized(G, 0); CGOBegin(shaderCGO, GL_LINES); CGOVertexv(shaderCGO, corner + 3 * 0); CGOVertexv(shaderCGO, corner + 3 * 1); CGOVertexv(shaderCGO, corner + 3 * 0); CGOVertexv(shaderCGO, corner + 3 * 2); CGOVertexv(shaderCGO, corner + 3 * 2); CGOVertexv(shaderCGO, corner + 3 * 3); CGOVertexv(shaderCGO, corner + 3 * 1); CGOVertexv(shaderCGO, corner + 3 * 3); CGOVertexv(shaderCGO, corner + 3 * 0); CGOVertexv(shaderCGO, corner + 3 * 4); CGOVertexv(shaderCGO, corner + 3 * 1); CGOVertexv(shaderCGO, corner + 3 * 5); CGOVertexv(shaderCGO, corner + 3 * 2); CGOVertexv(shaderCGO, corner + 3 * 6); CGOVertexv(shaderCGO, corner + 3 * 3); CGOVertexv(shaderCGO, corner + 3 * 7); CGOVertexv(shaderCGO, corner + 3 * 4); CGOVertexv(shaderCGO, corner + 3 * 5); CGOVertexv(shaderCGO, corner + 3 * 4); CGOVertexv(shaderCGO, corner + 3 * 6); CGOVertexv(shaderCGO, corner + 3 * 6); CGOVertexv(shaderCGO, corner + 3 * 7); CGOVertexv(shaderCGO, corner + 3 * 5); CGOVertexv(shaderCGO, corner + 3 * 7); CGOEnd(shaderCGO); CGOStop(shaderCGO); convertCGO = CGOCombineBeginEnd(shaderCGO, 0); CHECKOK(ok, convertCGO); CGOFree(shaderCGO); shaderCGO = convertCGO; if (ok) convertCGO = CGOOptimizeToVBONotIndexedWithReturnedData(shaderCGO, 0, 0, NULL); else return NULL; CHECKOK(ok, convertCGO); if (!ok) return NULL; CGOFree(shaderCGO); shaderCGO = convertCGO; shaderCGO->use_shader = true; return shaderCGO; } static void ObjectMapRender(ObjectMap * I, RenderInfo * info) { PyMOLGlobals *G = I->Obj.G; int state = info->state; CRay *ray = info->ray; auto pick = info->pick; int pass = info->pass; ObjectMapState *ms = NULL; if(pass) return; for(StateIterator iter(G, I->Obj.Setting, state, I->NState); iter.next();) { state = iter.state; if(I->State[state].Active) ms = &I->State[state]; if(ms) { float *corner = ms->Corner; float tr_corner[24]; ObjectPrepareContext(&I->Obj, info); if(ms->State.Matrix) { /* transform the corners before drawing */ int a; for(a = 0; a < 8; a++) { transform44d3f(ms->State.Matrix, corner + 3 * a, tr_corner + 3 * a); } corner = tr_corner; } if((I->Obj.visRep & cRepExtentBit)) { if(ray) { const float *vc; float radius = ray->PixelRadius / 1.4142F; vc = ColorGet(G, I->Obj.Color); ray->color3fv(vc); ray->sausage3fv(corner + 3 * 0, corner + 3 * 1, radius, vc, vc); ray->sausage3fv(corner + 3 * 0, corner + 3 * 2, radius, vc, vc); ray->sausage3fv(corner + 3 * 2, corner + 3 * 3, radius, vc, vc); ray->sausage3fv(corner + 3 * 1, corner + 3 * 3, radius, vc, vc); ray->sausage3fv(corner + 3 * 0, corner + 3 * 4, radius, vc, vc); ray->sausage3fv(corner + 3 * 1, corner + 3 * 5, radius, vc, vc); ray->sausage3fv(corner + 3 * 2, corner + 3 * 6, radius, vc, vc); ray->sausage3fv(corner + 3 * 3, corner + 3 * 7, radius, vc, vc); ray->sausage3fv(corner + 3 * 4, corner + 3 * 5, radius, vc, vc); ray->sausage3fv(corner + 3 * 4, corner + 3 * 6, radius, vc, vc); ray->sausage3fv(corner + 3 * 6, corner + 3 * 7, radius, vc, vc); ray->sausage3fv(corner + 3 * 5, corner + 3 * 7, radius, vc, vc); } else if(G->HaveGUI && G->ValidContext) { if(pick) { #ifndef PURE_OPENGL_ES_2 } else if (!info->use_shaders) { // immediate ObjectUseColor(&I->Obj); glDisable(GL_LIGHTING); glBegin(GL_LINES); glVertex3fv(corner + 3 * 0); glVertex3fv(corner + 3 * 1); glVertex3fv(corner + 3 * 0); glVertex3fv(corner + 3 * 2); glVertex3fv(corner + 3 * 2); glVertex3fv(corner + 3 * 3); glVertex3fv(corner + 3 * 1); glVertex3fv(corner + 3 * 3); glVertex3fv(corner + 3 * 0); glVertex3fv(corner + 3 * 4); glVertex3fv(corner + 3 * 1); glVertex3fv(corner + 3 * 5); glVertex3fv(corner + 3 * 2); glVertex3fv(corner + 3 * 6); glVertex3fv(corner + 3 * 3); glVertex3fv(corner + 3 * 7); glVertex3fv(corner + 3 * 4); glVertex3fv(corner + 3 * 5); glVertex3fv(corner + 3 * 4); glVertex3fv(corner + 3 * 6); glVertex3fv(corner + 3 * 6); glVertex3fv(corner + 3 * 7); glVertex3fv(corner + 3 * 5); glVertex3fv(corner + 3 * 7); glEnd(); glEnable(GL_LIGHTING); } else { #endif // shader if (!ms->shaderCGO) { ms->shaderCGO = ObjectMapCGOGenerate(G, corner); } if (ms->shaderCGO) { CShaderPrg* shaderPrg = G->ShaderMgr->Enable_DefaultShader(info->pass); if (shaderPrg) { shaderPrg->SetLightingEnabled(0); CGORenderGL(ms->shaderCGO, ColorGet(G, I->Obj.Color), NULL, NULL, info, NULL); shaderPrg->Disable(); } } } } } if((I->Obj.visRep & cRepDotBit)) { if(!ms->have_range) { double sum = 0.0, sumsq = 0.0; CField *data = ms->Field->data; int cnt = data->dim[0] * data->dim[1] * data->dim[2]; float *raw_data = (float *) data->data; int a; for(a = 0; a < cnt; a++) { double f_val = *(raw_data++); sum += f_val; sumsq += (f_val * f_val); } if(cnt) { float mean, stdev; mean = (float) (sum / cnt); stdev = (float) sqrt1d((sumsq - (sum * sum / cnt)) / (cnt)); ms->high_cutoff = mean + stdev; ms->low_cutoff = mean - stdev; ms->have_range = true; } } if(ms->have_range && SettingGet_b(G, NULL, I->Obj.Setting, cSetting_dot_normals)) { IsofieldComputeGradients(G, ms->Field); } if(ms->have_range) { int a; CField *data = ms->Field->data; int cnt = data->dim[0] * data->dim[1] * data->dim[2]; CField *points = ms->Field->points; CField *gradients = NULL; if(SettingGet_b(G, NULL, I->Obj.Setting, cSetting_dot_normals)) { gradients = ms->Field->gradients; } if(data && points) { float *raw_data = (float *) data->data; float raw_point[3], *raw_point_ptr = (float *) points->data; #define RAW_POINT_TRANSFORM(ptr, v3f) { \ if(ms->State.Matrix) \ transform44d3f(ms->State.Matrix, ptr, v3f); \ else \ copy3f(ptr, v3f); \ ptr += 3; \ } float *raw_gradient = NULL; float high_cut = ms->high_cutoff, low_cut = ms->low_cutoff; float width = SettingGet_f(G, NULL, I->Obj.Setting, cSetting_dot_width); if(ray) { float radius = ray->PixelRadius * width / 1.4142F; float vc[3]; int color = I->Obj.Color; int ramped = ColorCheckRamped(G, I->Obj.Color); { const float *tmp = ColorGet(G, I->Obj.Color); copy3f(tmp, vc); } for(a = 0; a < cnt; a++) { float f_val = *(raw_data++); RAW_POINT_TRANSFORM(raw_point_ptr, raw_point); if((f_val >= high_cut) || (f_val <= low_cut)) { if(ramped) { ColorGetRamped(G, color, raw_point, vc, state); ray->color3fv(vc); } ray->sphere3fv(raw_point, radius); } } } else if(G->HaveGUI && G->ValidContext) { if(pick) { } else if (ALWAYS_IMMEDIATE_OR(!info->use_shaders)) { if(gradients) { raw_gradient = (float *) gradients->data; } else { glDisable(GL_LIGHTING); } { int ramped = ColorCheckRamped(G, I->Obj.Color); float vc[3]; int color = I->Obj.Color; float gt[3]; glPointSize(width); glDisable(GL_POINT_SMOOTH); glBegin(GL_POINTS); ObjectUseColor(&I->Obj); for(a = 0; a < cnt; a++) { float f_val = *(raw_data++); RAW_POINT_TRANSFORM(raw_point_ptr, raw_point); if(f_val >= high_cut) { if(raw_gradient) { normalize23f(raw_gradient, gt); invert3f(gt); glNormal3fv(gt); } if(ramped) { ColorGetRamped(G, color, raw_point, vc, state); glColor3fv(vc); } glVertex3fv(raw_point); } else if(f_val <= low_cut) { if(raw_gradient) { normalize23f(raw_gradient, gt); glNormal3fv(gt); } if(ramped) { ColorGetRamped(G, color, raw_point, vc, state); glColor3fv(vc); } glVertex3fv(raw_point); } if(raw_gradient) raw_gradient += 3; } glEnd(); glEnable(GL_POINT_SMOOTH); } } } } } } } } } void ObjectMapStateInit(PyMOLGlobals * G, ObjectMapState * I) { ObjectMapStatePurge(G, I); ObjectStateInit(G, &I->State); I->Symmetry = SymmetryNew(G); I->Field = NULL; I->Origin = NULL; I->Dim = NULL; I->Range = NULL; I->Grid = NULL; I->MapSource = cMapSourceUndefined; I->have_range = false; } int ObjectMapGetNStates(ObjectMap * I) { return (I->NState); } /*========================================================================*/ ObjectMap *ObjectMapNew(PyMOLGlobals * G) { OOAlloc(G, ObjectMap); ObjectInit(G, (CObject *) I); I->Obj.type = cObjectMap; I->NState = 0; I->State = VLACalloc(ObjectMapState, 1); /* autozero important */ I->Obj.visRep = cRepExtentBit; I->Obj.fFree = (void (*)(CObject *)) ObjectMapFree; I->Obj.fUpdate = (void (*)(CObject *)) ObjectMapUpdate; I->Obj.fRender = (void (*)(CObject *, RenderInfo *)) ObjectMapRender; I->Obj.fInvalidate = (void (*)(CObject *, int, int, int)) ObjectMapInvalidate; I->Obj.fGetNFrame = (int (*)(CObject *)) ObjectMapGetNStates; return (I); } /*========================================================================*/ ObjectMapState *ObjectMapNewStateFromDesc(PyMOLGlobals * G, ObjectMap * I, ObjectMapDesc * inp_md, int state, int quiet) { int ok = true; float v[3]; int a, b, c, d; float *fp; ObjectMapState *ms = NULL; ObjectMapDesc _md, *md; ms = ObjectMapStatePrime(I, state); md = &_md; *(md) = *(inp_md); if(I) { ms->Origin = Alloc(float, 3); ms->Range = Alloc(float, 3); ms->Grid = Alloc(float, 3); ms->MapSource = cMapSourceDesc; } switch (md->mode) { case cObjectMap_OrthoMinMaxGrid: /* Orthorhombic: min, max, spacing, centered over range */ subtract3f(md->MaxCorner, md->MinCorner, v); for(a = 0; a < 3; a++) { if(v[a] < 0.0) std::swap(md->MaxCorner[a], md->MinCorner[a]); }; subtract3f(md->MaxCorner, md->MinCorner, v); for(a = 0; a < 3; a++) { md->Dim[a] = (int) (v[a] / md->Grid[a]); if(md->Dim[a] < 1) md->Dim[a] = 1; if((md->Dim[a] * md->Grid[a]) < v[a]) md->Dim[a]++; } PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMap: Dim %d %d %d\n", md->Dim[0], md->Dim[1], md->Dim[2] ENDFB(I->Obj.G); average3f(md->MaxCorner, md->MinCorner, v); for(a = 0; a < 3; a++) { md->MinCorner[a] = v[a] - 0.5F * md->Dim[a] * md->Grid[a]; } if(Feedback(I->Obj.G, FB_ObjectMap, FB_Blather)) { dump3f(md->MinCorner, " ObjectMap: MinCorner:"); dump3f(md->MaxCorner, " ObjectMap: MaxCorner:"); dump3f(md->Grid, " ObjectMap: Grid:"); } /* now populate the map data structure */ copy3f(md->MinCorner, ms->Origin); copy3f(md->Grid, ms->Grid); for(a = 0; a < 3; a++) ms->Range[a] = md->Grid[a] * (md->Dim[a] - 1); /* these maps start at zero */ for(a = 0; a < 3; a++) { ms->Min[a] = 0; ms->Max[a] = md->Dim[a] - 1; ms->Div[a] = md->Dim[a] - 1; } /* define corners */ for(a = 0; a < 8; a++) copy3f(ms->Origin, ms->Corner + 3 * a); d = 0; for(c = 0; c < 2; c++) { { v[2] = (c ? ms->Range[2] : 0.0F); for(b = 0; b < 2; b++) { v[1] = (b ? ms->Range[1] : 0.0F); for(a = 0; a < 2; a++) { v[0] = (a ? ms->Range[0] : 0.0F); add3f(v, ms->Corner + 3 * d, ms->Corner + 3 * d); d++; } } } } for(a = 0; a < 3; a++) ms->FDim[a] = ms->Max[a] - ms->Min[a] + 1; ms->FDim[3] = 3; ms->Field = IsosurfFieldAlloc(I->Obj.G, ms->FDim); if(!ms->Field) ok = false; else { for(a = 0; a < md->Dim[0]; a++) { v[0] = md->MinCorner[0] + a * md->Grid[0]; for(b = 0; b < md->Dim[1]; b++) { v[1] = md->MinCorner[1] + b * md->Grid[1]; for(c = 0; c < md->Dim[2]; c++) { v[2] = md->MinCorner[2] + c * md->Grid[2]; fp = F4Ptr(ms->Field->points, a, b, c, 0); copy3f(v, fp); } } } } break; default: ok = false; } if(ok) { switch (md->init_mode) { case 0: for(a = 0; a < md->Dim[0]; a++) { for(b = 0; b < md->Dim[1]; b++) { for(c = 0; c < md->Dim[2]; c++) { F3(ms->Field->data, a, b, c) = 0.0F; } } } break; case 1: for(a = 0; a < md->Dim[0]; a++) { for(b = 0; b < md->Dim[1]; b++) { for(c = 0; c < md->Dim[2]; c++) { F3(ms->Field->data, a, b, c) = 1.0F; } } } break; case -2: /* for testing... */ for(a = 0; a < md->Dim[0]; a++) { for(b = 0; b < md->Dim[1]; b++) { for(c = 0; c < md->Dim[2]; c++) { F3(ms->Field->data, a, b, c) = (float) sqrt1d(a * a + b * b + c * c); } } } break; } } if(ok) { copy3f(ms->Origin, ms->ExtentMin); copy3f(ms->Origin, ms->ExtentMax); add3f(ms->Range, ms->ExtentMax, ms->ExtentMax); ObjectMapUpdateExtents(I); } if(!ok) { ErrMessage(I->Obj.G, "ObjectMap", "Unable to create map"); ObjectMapFree(I); I = NULL; } else { if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Actions) " ObjectMap: Map created.\n" ENDFB(I->Obj.G); } } return (ms); } /*========================================================================*/ static float ccp4_next_value(char ** pp, int mode) { char * p = *pp; switch(mode) { case 0: *pp += 1; return (float) *((int8_t *) p); case 1: *pp += 2; return (float) *((int16_t *) p); case 2: *pp += 4; return *((float *) p); } printf("ERROR unsupported mode\n"); return 0.f; } /* swaps n*width bytes in memory starting at p */ static void swap_endian(char * p, int n, int width) { char tmp, *q, *pstop = p + (n - 1) * width + 1; int w2 = width/2, wm1 = width - 1; for(; p < pstop; p += w2) { for(q = p + wm1; p < q; p++, q--) { tmp = *p; *p = *q; *q = tmp; } } } static int ObjectMapCCP4StrToMap(ObjectMap * I, char *CCP4Str, int bytes, int state, int quiet) { char *p; int *i; size_t bytes_per_pt; char *q; float dens; int a, b, c, d, e; float v[3], vr[3], maxd, mind; int ok = true; int little_endian = 1, map_endian; /* CCP4 named from their docs */ int nc, nr, ns; int map_mode; int ncstart, nrstart, nsstart; int nx, ny, nz; float xlen, ylen, zlen, alpha, beta, gamma; int ispg; // space group number int sym_skip; int mapc, mapr, maps; int cc[3]; int n_pts; double sum, sumsq; float mean, stdev; int normalize; ObjectMapState *ms; int expectation; if(bytes < 256 * sizeof(int)) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Errors) " ObjectMapCCP4: Map appears to be truncated -- aborting." ENDFB(I->Obj.G); return (0); } /* state check */ if(state < 0) state = I->NState; /* alloc/init a new MapState */ if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(I->Obj.G, ms); normalize = SettingGetGlobal_b(I->Obj.G, cSetting_normalize_ccp4_maps); p = CCP4Str; little_endian = *((char *) &little_endian); map_endian = (*p || *(p + 1)); // NOTE: this assumes 0x0 < NC < 0x10000 if(little_endian != map_endian) { if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: Map appears to be reverse endian, swapping...\n" ENDFB(I->Obj.G); } swap_endian(p, 256, sizeof(int)); } i = (int *) p; nc = *(i++); /* columns */ nr = *(i++); /* rows */ ns = *(i++); /* sections */ if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: NC %d NR %d NS %d\n", nc, nr, ns ENDFB(I->Obj.G); } map_mode = *(i++); /* mode */ switch(map_mode) { case 0: bytes_per_pt = 1; // int8_t break; case 1: bytes_per_pt = 2; // int16_t break; case 2: bytes_per_pt = 4; // float break; default: PRINTFB(I->Obj.G, FB_ObjectMap, FB_Errors) "ObjectMapCCP4-ERR: Only map mode 0-2 currently supported (this map is mode %d)", map_mode ENDFB(I->Obj.G); return (0); } if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: Map is mode %d.\n", map_mode ENDFB(I->Obj.G); } ncstart = *(i++); nrstart = *(i++); nsstart = *(i++); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: NCSTART %d NRSTART %d NSSTART %d\n", ncstart, nrstart, nsstart ENDFB(I->Obj.G); } nx = *(i++); ny = *(i++); nz = *(i++); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: NX %d NY %d NZ %d \n", nx, ny, nz ENDFB(I->Obj.G); } xlen = *(float *) (i++); ylen = *(float *) (i++); zlen = *(float *) (i++); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: X %8.3f Y %8.3f Z %8.3f \n", xlen, ylen, zlen ENDFB(I->Obj.G); } alpha = *(float *) (i++); beta = *(float *) (i++); gamma = *(float *) (i++); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: alpha %8.3f beta %8.3f gamma %8.3f \n", alpha, beta, gamma ENDFB(I->Obj.G); } mapc = *(i++); mapr = *(i++); maps = *(i++); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: MAPC %d MAPR %d MAPS %d \n", mapc, mapr, maps ENDFB(I->Obj.G); } // AMIN, AMAX, AMEAN mind = *(float *) (i++); maxd = *(float *) (i++); mean = *(float *) (i++); ispg = *(i++); sym_skip = *(i++); // CCP4 Format: // 25-37 skew transformation // 38-52 future use "Storage space sometimes used by specific programs (default = 0)" // MRC 2000 Format: // 25-49 "Extra, user defined storage space (default = 0)" // 50-52 ORIGIN { int skew = *(i++); if(skew) { double matrix[16]; auto i_float = (const float *) i; // SKWMAT Skew matrix S (in order S11, S12, S13, S21 etc) copy33f44d(i_float, matrix); xx_matrix_invert(matrix, matrix, 4); // SKWTRN Skew translation t matrix[3] = i_float[9]; matrix[7] = i_float[10]; matrix[11] = i_float[11]; // Xo(map) = S * (Xo(atoms) - t) ObjectStateSetMatrix(&ms->State, matrix); PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ObjectMapCCP4: Applied skew transformation\n" ENDFB(I->Obj.G); } } // XORIGIN, YORIGIN, ZORIGIN (50 - 52) // TODO See "Origin Conventions" in http://situs.biomachina.org/fmap.pdf float * mrc2000origin = (float *)(i + 49 - 25); if (lengthsq3f(mrc2000origin) > R_SMALL4) { double matrix[] = { 1., 0., 0., mrc2000origin[0], 0., 1., 0., mrc2000origin[1], 0., 0., 1., mrc2000origin[2], 0., 0., 0., 1.}; ObjectStateSetMatrix(&ms->State, matrix); if (!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ObjectMapCCP4: Applied MRC 2000 ORIGIN %.2f %.2f %.2f\n", mrc2000origin[0], mrc2000origin[1], mrc2000origin[2] ENDFB(I->Obj.G); } } i += 54 - 25; stdev = *(float *) (i++); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: AMIN %f AMAX %f AMEAN %f ARMS %f\n", mind, maxd, mean, stdev ENDFB(I->Obj.G); } n_pts = nc * ns * nr; /* at least one EM map encountered lacks NZ, so we'll try to guess it */ if((nx == ny) && (!nz)) { nz = nx; if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Warnings) " ObjectMapCCP4: NZ value is zero, but NX = NY, so we'll guess NZ = NX = NY.\n" ENDFB(I->Obj.G); } } expectation = sym_skip + sizeof(int) * 256 + bytes_per_pt * n_pts; if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: sym_skip %d bytes %d expectation %d\n", sym_skip, bytes, expectation ENDFB(I->Obj.G); } if(bytes < expectation) { if(bytes == (expectation - sym_skip)) { /* accomodate bogus CCP4 map files with bad symmetry length information */ if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " ObjectMapCCP4: Map has invalid symmetry length -- working around.\n" ENDFB(I->Obj.G); } expectation -= sym_skip; sym_skip = 0; } else { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Errors) " ObjectMapCCP4: Map appears to be truncated -- aborting.\n" ENDFB(I->Obj.G); return (0); } } q = p + (sizeof(int) * 256) + sym_skip; if(little_endian != map_endian && bytes_per_pt > 1) { swap_endian(q, n_pts, bytes_per_pt); } // with normalize == 2, use mean and stdev from file header if(normalize == 1 && n_pts > 1) { c = n_pts; sum = 0.0; sumsq = 0.0; while(c--) { dens = ccp4_next_value(&q, map_mode); sumsq += dens * dens; sum += dens; } mean = (float) (sum / n_pts); stdev = (float) sqrt1d((sumsq - (sum * sum / n_pts)) / (n_pts - 1)); if(stdev < 0.000001) stdev = 1.0; } q = p + (sizeof(int) * 256) + sym_skip; mapc--; /* convert to C indexing... */ mapr--; maps--; ms->Div[0] = nx; ms->Div[1] = ny; ms->Div[2] = nz; ms->FDim[mapc] = nc; ms->Min[mapc] = ncstart; ms->Max[mapc] = nc + ncstart - 1; ms->FDim[mapr] = nr; ms->Min[mapr] = nrstart; ms->Max[mapr] = nr + nrstart - 1; ms->FDim[maps] = ns; ms->Min[maps] = nsstart; ms->Max[maps] = ns + nsstart - 1; if(!quiet) { if(Feedback(I->Obj.G, FB_ObjectMap, FB_Blather)) { dump3i(ms->Div, " ObjectMapCCP4: ms->Div"); dump3i(ms->Min, " ObjectMapCCP4: ms->Min"); dump3i(ms->Max, " ObjectMapCCP4: ms->Max"); dump3i(ms->FDim, " ObjectMapCCP4: ms->FDim"); } } ms->Symmetry->Crystal->Dim[0] = xlen; ms->Symmetry->Crystal->Dim[1] = ylen; ms->Symmetry->Crystal->Dim[2] = zlen; ms->Symmetry->Crystal->Angle[0] = alpha; ms->Symmetry->Crystal->Angle[1] = beta; ms->Symmetry->Crystal->Angle[2] = gamma; if(ispg < n_space_group_numbers) { UtilNCopy(ms->Symmetry->SpaceGroup, space_group_numbers[ispg], WordLength); } /* -- JV; for vol ms->Mean = mean; ms->SD = stdev; ms->MaxValue = maxd; ms->MinValue = mind; */ ms->FDim[3] = 3; if(!(ms->FDim[0] && ms->FDim[1] && ms->FDim[2])) ok = false; else { SymmetryUpdate(ms->Symmetry); /* CrystalDump(ms->Crystal); */ ms->Field = IsosurfFieldAlloc(I->Obj.G, ms->FDim); ms->MapSource = cMapSourceCCP4; ms->Field->save_points = false; maxd = -FLT_MAX; mind = FLT_MAX; for(cc[maps] = 0; cc[maps] < ms->FDim[maps]; cc[maps]++) { v[maps] = (cc[maps] + ms->Min[maps]) / ((float) ms->Div[maps]); for(cc[mapr] = 0; cc[mapr] < ms->FDim[mapr]; cc[mapr]++) { v[mapr] = (cc[mapr] + ms->Min[mapr]) / ((float) ms->Div[mapr]); for(cc[mapc] = 0; cc[mapc] < ms->FDim[mapc]; cc[mapc]++) { v[mapc] = (cc[mapc] + ms->Min[mapc]) / ((float) ms->Div[mapc]); dens = ccp4_next_value(&q, map_mode); if(normalize) dens = (dens - mean) / stdev; F3(ms->Field->data, cc[0], cc[1], cc[2]) = dens; if(maxd < dens) maxd = dens; if(mind > dens) mind = dens; transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); for(e = 0; e < 3; e++) F4(ms->Field->points, cc[0], cc[1], cc[2], e) = vr[e]; } } } } if(ok) { d = 0; for(c = 0; c < 2; c++) { v[2] = (c * (ms->FDim[2] - 1) + ms->Min[2]) / ((float) ms->Div[2]); for(b = 0; b < 2; b++) { v[1] = (b * (ms->FDim[1] - 1) + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < 2; a++) { v[0] = (a * (ms->FDim[0] - 1) + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); copy3f(vr, ms->Corner + 3 * d); d++; } } } } if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ObjectMapCCP4: Map Size %d x %d x %d\n", ms->FDim[0], ms->FDim[1], ms->FDim[2] ENDFB(I->Obj.G); } if(!quiet) { if(n_pts > 1) { if(normalize) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ObjectMapCCP4: Normalizing with mean = %8.6f and stdev = %8.6f.\n", mean, stdev ENDFB(I->Obj.G); } else { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ObjectMapCCP4: Map will not be normalized.\n ObjectMapCCP4: Current mean = %8.6f and stdev = %8.6f.\n", mean, stdev ENDFB(I->Obj.G); } } } if(ok) { v[2] = (ms->Min[2]) / ((float) ms->Div[2]); v[1] = (ms->Min[1]) / ((float) ms->Div[1]); v[0] = (ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMin); v[2] = ((ms->FDim[2] - 1) + ms->Min[2]) / ((float) ms->Div[2]); v[1] = ((ms->FDim[1] - 1) + ms->Min[1]) / ((float) ms->Div[1]); v[0] = ((ms->FDim[0] - 1) + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMax); } #ifdef _UNDEFINED printf("%d %d %d %d %d %d %d %d %d\n", ms->Div[0], ms->Min[0], ms->Max[0], ms->Div[1], ms->Min[1], ms->Max[1], ms->Div[2], ms->Min[2], ms->Max[2]); printf("Okay? %d\n", ok); fflush(stdout); #endif if(!ok) { ErrMessage(I->Obj.G, "ObjectMap", "Error reading map"); } else { ms->Active = true; ObjectMapUpdateExtents(I); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Results) " ObjectMap: Map read. Range: %5.3f to %5.3f\n", mind, maxd ENDFB(I->Obj.G); } } return (ok); } /*========================================================================*/ ObjectMapState * getObjectMapState(PyMOLGlobals * G, const char * name, int state) { return getObjectMapState(G, ExecutiveFindObjectByName(G, name), state); } /*========================================================================*/ std::vector<char> ObjectMapStateToCCP4Str(const ObjectMapState * ms, int quiet) { std::vector<char> buffer; if (!ms || !ms->Active) return buffer; // empty auto G = ms->State.G; auto field = ms->Field->data; if (field->type != cFieldFloat || field->base_size != 4) { PRINTFB(G, FB_ObjectMap, FB_Errors) " MapStateToCCP4-Error: Unsupported field type\n" ENDFB(G); return buffer; // empty } buffer.resize(1024 + field->size, 0); auto buffer_s = reinterpret_cast<char*>(&buffer.front()); auto buffer_i = reinterpret_cast<int32_t*>(&buffer.front()); auto buffer_f = reinterpret_cast<float*>(&buffer.front()); buffer_i[0] = ms->FDim[2]; // NC / NX buffer_i[1] = ms->FDim[1]; // NR / NY buffer_i[2] = ms->FDim[0]; // NS / NZ buffer_i[3] = 2; // MODE (2 = 32-bit reals) buffer_i[4] = ms->Min[2]; // NCSTART / NXSTART buffer_i[5] = ms->Min[1]; // NRSTART / NYSTART buffer_i[6] = ms->Min[0]; // NSSTART / NZSTART buffer_i[7] = ms->Div[0]; // NX / MX buffer_i[8] = ms->Div[1]; // NY / MY buffer_i[9] = ms->Div[2]; // NZ / MZ if (ms->Div[0] == 0) { // fallback buffer_i[7] = ms->FDim[0] - 1; // NX / MX buffer_i[8] = ms->FDim[1] - 1; // NY / MY buffer_i[9] = ms->FDim[2] - 1; // NZ / MZ } bool cell_fallback = true; // Cell if (ms->Symmetry && ms->Symmetry->Crystal) { auto crystal = ms->Symmetry->Crystal; buffer_f[10] = crystal->Dim[0]; // X length / CELL A buffer_f[11] = crystal->Dim[1]; // Y length buffer_f[12] = crystal->Dim[2]; // Z length buffer_f[13] = crystal->Angle[0]; // Alpha / CELL B buffer_f[14] = crystal->Angle[1]; // Beta buffer_f[15] = crystal->Angle[2]; // Gamma // check for 1x1x1 dummy cell cell_fallback = fabs(lengthsq3f(crystal->Dim) - 3.f) < R_SMALL4; } if (cell_fallback) { // fallback: orthogonal extents box subtract3f(ms->ExtentMax, ms->ExtentMin, buffer_f + 10); // CELL A set3f(buffer_f + 13, 90.f, 90.f, 90.f); // CELL B } buffer_i[16] = 3; // MAPC buffer_i[17] = 2; // MAPR buffer_i[18] = 1; // MAPS // dummy values buffer_f[19] = -5.f; // AMIN buffer_f[20] = 5.f; // AMAX buffer_f[21] = 0.f; // AMEAN // Space group number if (ms->Symmetry) { for (int ispg = 0; ispg < n_space_group_numbers; ++ispg) { if (strcmp(ms->Symmetry->SpaceGroup, space_group_numbers[ispg]) == 0) { buffer_i[22] = ispg; // ISPG break; } } } buffer_i[23] = 0; // NSYMBT // skew transformation if (ms->State.Matrix) { double m[16]; copy44d(ms->State.Matrix, m); // Skew translation t set3f(buffer_f + 34, m[3], m[7], m[11]); // SKWTRN // Skew matrix S (in order S11, S12, S13, S21 etc) m[3] = m[7] = m[11] = 0.; xx_matrix_invert(m, m, 4); copy44d33f(m, buffer_f + 25); // SKWMAT buffer_i[24] = 1; // LSKFLG } // origin (stored with skew transformation) if (ms->Origin && lengthsq3f(ms->Origin) > R_SMALL4) { auto skwtrn = buffer_f + 34; add3f(ms->Origin, skwtrn, skwtrn); // add to SKWTRN if (!buffer_i[24]) { identity33f(buffer_f + 25); // SKWMAT (identity) buffer_i[24] = 1; // LSKFLG } } // Character string 'MAP ' to identify file type memcpy(buffer_s + 52 * 4, "MAP ", 4); // MAP // Machine stamp indicating the machine type which wrote file if (1 == *(int32_t*)"\1\0\0\0") { buffer_i[53] = 0x00004144; // MACHST (little endian) } else { buffer_i[53] = 0x11110000; // MACHST (big endian) } buffer_f[54] = 1.f; // ARMS buffer_i[55] = 1; // NLABL strcpy(buffer_s + 56 * 4, "PyMOL"); // 57-256 LABEL(20,10) // Map data array follows memcpy(buffer_s + 1024, field->data, field->size); return buffer; } /*========================================================================*/ static int ObjectMapPHIStrToMap(ObjectMap * I, char *PHIStr, int bytes, int state, int quiet) { char *p; float dens, dens_rev; int a, b, c, d, e; float v[3], maxd, mind; int ok = true; int little_endian = 1; /* PHI named from their docs */ int map_endian = 0; int map_dim; int map_bytes; ObjectMapState *ms; char cc[MAXLINELEN]; char *rev; little_endian = *((char *) &little_endian); if(state < 0) state = I->NState; if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(I->Obj.G, ms); maxd = -FLT_MAX; mind = FLT_MAX; p = PHIStr; if(*p) /* use FORMATTED IO record to determine map endiness */ map_endian = 1; else map_endian = 0; p += 4; ParseNCopy(cc, p, 20); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " PHIStrToMap: %s\n", cc ENDFB(I->Obj.G); } p += 20; p += 4; p += 4; ParseNCopy(cc, p, 10); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " PHIStrToMap: %s\n", cc ENDFB(I->Obj.G); } p += 10; ParseNCopy(cc, p, 60); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " PHIStrToMap: %s\n", cc ENDFB(I->Obj.G); } p += 60; p += 4; rev = (char *) &dens_rev; if(little_endian != map_endian) { rev[0] = p[3]; rev[1] = p[2]; rev[2] = p[1]; rev[3] = p[0]; } else { rev[0] = p[0]; /* gotta go char by char because of memory alignment issues ... */ rev[1] = p[1]; rev[2] = p[2]; rev[3] = p[3]; } map_bytes = *((int *) rev); map_dim = (int) (pow((map_bytes / 4.0), 1 / 3.0) + 0.5); if((4 * map_dim * map_dim * map_dim) != map_bytes) /* consistency check */ map_dim = 65; if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " PHIStrToMap: Map Size %d x %d x %d\n", map_dim, map_dim, map_dim ENDFB(I->Obj.G); } p += 4; ms->FDim[0] = map_dim; ms->FDim[1] = map_dim; ms->FDim[2] = map_dim; ms->FDim[3] = 3; ms->Div[0] = (map_dim - 1) / 2; ms->Div[1] = (map_dim - 1) / 2; ms->Div[2] = (map_dim - 1) / 2; ms->Min[0] = -ms->Div[0]; ms->Min[1] = -ms->Div[1]; ms->Min[2] = -ms->Div[2]; ms->Max[0] = ms->Div[0]; ms->Max[1] = ms->Div[1]; ms->Max[2] = ms->Div[2]; ms->Field = IsosurfFieldAlloc(I->Obj.G, ms->FDim); ms->MapSource = cMapSourceGeneralPurpose; ms->Field->save_points = false; for(c = 0; c < ms->FDim[2]; c++) { /* z y x ordering into c b a so that x = a, etc. */ for(b = 0; b < ms->FDim[1]; b++) { for(a = 0; a < ms->FDim[0]; a++) { if(little_endian != map_endian) { rev[0] = p[3]; rev[1] = p[2]; rev[2] = p[1]; rev[3] = p[0]; } else { rev[0] = p[0]; /* gotta go char by char because of memory alignment issues ... */ rev[1] = p[1]; rev[2] = p[2]; rev[3] = p[3]; } dens = *((float *) rev); F3(ms->Field->data, a, b, c) = dens; if(maxd < dens) maxd = dens; if(mind > dens) mind = dens; p += 4; } } } p += 4; p += 4; ParseNCopy(cc, p, 16); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " PHIStrToMap: %s\n", cc ENDFB(I->Obj.G); } p += 16; p += 4; ms->Grid = Alloc(float, 3); p += 4; if(little_endian != map_endian) { rev[0] = p[3]; rev[1] = p[2]; rev[2] = p[1]; rev[3] = p[0]; } else { rev[0] = p[0]; /* gotta go char by char because of memory alignment issues ... */ rev[1] = p[1]; rev[2] = p[2]; rev[3] = p[3]; } ms->Grid[0] = 1.0F / (*((float *) rev)); ms->Grid[1] = ms->Grid[0]; ms->Grid[2] = ms->Grid[0]; p += 4; ms->Origin = Alloc(float, 3); if(little_endian != map_endian) { rev[0] = p[3]; rev[1] = p[2]; rev[2] = p[1]; rev[3] = p[0]; } else { rev[0] = p[0]; /* gotta go char by char because of memory alignment issues ... */ rev[1] = p[1]; rev[2] = p[2]; rev[3] = p[3];; } ms->Origin[0] = *((float *) rev); p += 4; if(little_endian != map_endian) { rev[0] = p[3]; rev[1] = p[2]; rev[2] = p[1]; rev[3] = p[0]; } else { rev[0] = p[0]; /* gotta go char by char because of memory alignment issues ... */ rev[1] = p[1]; rev[2] = p[2]; rev[3] = p[3];; } ms->Origin[1] = *((float *) rev); p += 4; if(little_endian != map_endian) { rev[0] = p[3]; rev[1] = p[2]; rev[2] = p[1]; rev[3] = p[0]; } else { rev[0] = p[0]; /* gotta go char by char because of memory alignment issues ... */ rev[1] = p[1]; rev[2] = p[2]; rev[3] = p[3];; } ms->Origin[2] = *((float *) rev); p += 4; p += 4; if(ok) { for(e = 0; e < 3; e++) { ms->ExtentMin[e] = ms->Origin[e] + ms->Grid[e] * ms->Min[e]; ms->ExtentMax[e] = ms->Origin[e] + ms->Grid[e] * ms->Max[e]; } } for(c = 0; c < ms->FDim[2]; c++) { v[2] = ms->Origin[2] + ms->Grid[2] * (c + ms->Min[2]); for(b = 0; b < ms->FDim[1]; b++) { v[1] = ms->Origin[1] + ms->Grid[1] * (b + ms->Min[1]); for(a = 0; a < ms->FDim[0]; a++) { v[0] = ms->Origin[0] + ms->Grid[0] * (a + ms->Min[0]); for(e = 0; e < 3; e++) { F4(ms->Field->points, a, b, c, e) = v[e]; } } } } d = 0; for(c = 0; c < ms->FDim[2]; c += ms->FDim[2] - 1) { v[2] = ms->Origin[2] + ms->Grid[2] * (c + ms->Min[2]); for(b = 0; b < ms->FDim[1]; b += ms->FDim[1] - 1) { v[1] = ms->Origin[1] + ms->Grid[1] * (b + ms->Min[1]); for(a = 0; a < ms->FDim[0]; a += ms->FDim[0] - 1) { v[0] = ms->Origin[0] + ms->Grid[0] * (a + ms->Min[0]); copy3f(v, ms->Corner + 3 * d); d++; } } } /* interpolation test code { float test[3]; float result; float cmp; for(c=0;c<ms->FDim[0]-1;c++) { for(b=0;b<ms->FDim[1]-1;b++) { for(a=0;a<ms->FDim[2]-1;a++) { for(e=0;e<3;e++) { test[e] = (F4(ms->Field->points,a,b,c,e)+ F4(ms->Field->points,a,b,c,e))/2.0; } ObjectMapStateInterpolate(ms,test,&result,1); cmp = (F3(ms->Field->data,a,b,c)+ F3(ms->Field->data,a,b,c))/2.0; if(fabs(cmp-result)>0.001) { printf("%d %d %d\n",a,b,c); printf("%8.5f %8.5f\n", cmp, result); } } } } } */ if(!ok) { ErrMessage(I->Obj.G, "ObjectMap", "Error reading map"); } else { ms->Active = true; ObjectMapUpdateExtents(I); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Results) " ObjectMap: Map read. Range: %5.3f to %5.3f\n", mind, maxd ENDFB(I->Obj.G); } } return (ok); } /*========================================================================*/ static int ObjectMapXPLORStrToMap(ObjectMap * I, char *XPLORStr, int state, int quiet) { char *p; int a, b, c, d, e; float v[3], vr[3], dens, maxd, mind; char cc[MAXLINELEN]; int n; int ok = true; ObjectMapState *ms; if(state < 0) state = I->NState; if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(I->Obj.G, ms); maxd = -FLT_MAX; mind = FLT_MAX; p = XPLORStr; while(*p) { p = ParseNCopy(cc, p, 8); if(!*cc) p = ParseNextLine(p); else if(sscanf(cc, "%i", &n) == 1) { p = ParseWordCopy(cc, p, MAXLINELEN); if(strstr(cc, "!NTITLE") || (!*cc)) { p = ParseNextLine(p); while(n--) { p = ParseNextLine(p); } } else if(strstr(cc, "REMARKS")) { p = ParseNextLine(p); } else { break; } } } if(*p) { /* n contains first dimension */ ms->Div[0] = n; if(sscanf(cc, "%i", &ms->Min[0]) != 1) ok = false; p = ParseNCopy(cc, p, 8); if(sscanf(cc, "%i", &ms->Max[0]) != 1) ok = false; p = ParseNCopy(cc, p, 8); if(sscanf(cc, "%i", &ms->Div[1]) != 1) ok = false; p = ParseNCopy(cc, p, 8); if(sscanf(cc, "%i", &ms->Min[1]) != 1) ok = false; p = ParseNCopy(cc, p, 8); if(sscanf(cc, "%i", &ms->Max[1]) != 1) ok = false; p = ParseNCopy(cc, p, 8); if(sscanf(cc, "%i", &ms->Div[2]) != 1) ok = false; p = ParseNCopy(cc, p, 8); if(sscanf(cc, "%i", &ms->Min[2]) != 1) ok = false; p = ParseNCopy(cc, p, 8); if(sscanf(cc, "%i", &ms->Max[2]) != 1) ok = false; p = ParseNextLine(p); p = ParseNCopy(cc, p, 12); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Dim[0]) != 1) ok = false; p = ParseNCopy(cc, p, 12); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Dim[1]) != 1) ok = false; p = ParseNCopy(cc, p, 12); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Dim[2]) != 1) ok = false; p = ParseNCopy(cc, p, 12); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Angle[0]) != 1) ok = false; p = ParseNCopy(cc, p, 12); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Angle[1]) != 1) ok = false; p = ParseNCopy(cc, p, 12); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Angle[2]) != 1) ok = false; p = ParseNextLine(p); p = ParseNCopy(cc, p, 3); if(strcmp(cc, "ZYX")) ok = false; p = ParseNextLine(p); } else { ok = false; } if(ok) { ms->FDim[0] = ms->Max[0] - ms->Min[0] + 1; ms->FDim[1] = ms->Max[1] - ms->Min[1] + 1; ms->FDim[2] = ms->Max[2] - ms->Min[2] + 1; ms->FDim[3] = 3; if(!(ms->FDim[0] && ms->FDim[1] && ms->FDim[2])) ok = false; else { SymmetryUpdate(ms->Symmetry); ms->Field = IsosurfFieldAlloc(I->Obj.G, ms->FDim); ms->MapSource = cMapSourceCrystallographic; ms->Field->save_points = false; for(c = 0; c < ms->FDim[2]; c++) { v[2] = (c + ms->Min[2]) / ((float) ms->Div[2]); p = ParseNextLine(p); for(b = 0; b < ms->FDim[1]; b++) { v[1] = (b + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < ms->FDim[0]; a++) { v[0] = (a + ms->Min[0]) / ((float) ms->Div[0]); p = ParseNCopy(cc, p, 12); if(!cc[0]) { p = ParseNextLine(p); p = ParseNCopy(cc, p, 12); } if(sscanf(cc, "%f", &dens) != 1) { ok = false; } else { F3(ms->Field->data, a, b, c) = dens; if(maxd < dens) maxd = dens; if(mind > dens) mind = dens; } transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); for(e = 0; e < 3; e++) { F4(ms->Field->points, a, b, c, e) = vr[e]; } } } p = ParseNextLine(p); } if(ok) { d = 0; for(c = 0; c < ms->FDim[2]; c += (ms->FDim[2] - 1)) { v[2] = (c + ms->Min[2]) / ((float) ms->Div[2]); for(b = 0; b < ms->FDim[1]; b += (ms->FDim[1] - 1)) { v[1] = (b + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < ms->FDim[0]; a += (ms->FDim[0] - 1)) { v[0] = (a + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); copy3f(vr, ms->Corner + 3 * d); d++; } } } } } } if(ok) { v[2] = (ms->Min[2]) / ((float) ms->Div[2]); v[1] = (ms->Min[1]) / ((float) ms->Div[1]); v[0] = (ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMin); v[2] = ((ms->FDim[2] - 1) + ms->Min[2]) / ((float) ms->Div[2]); v[1] = ((ms->FDim[1] - 1) + ms->Min[1]) / ((float) ms->Div[1]); v[0] = ((ms->FDim[0] - 1) + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMax); } #ifdef _UNDEFINED printf("%d %d %d %d %d %d %d %d %d\n", ms->Div[0], ms->Min[0], ms->Max[0], ms->Div[1], ms->Min[1], ms->Max[1], ms->Div[2], ms->Min[2], ms->Max[2]); printf("Okay? %d\n", ok); fflush(stdout); #endif if(!ok) { ErrMessage(I->Obj.G, "ObjectMap", "Error reading map"); } else { ms->Active = true; ObjectMapUpdateExtents(I); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Results) " ObjectMap: Map read. Range = %5.3f to %5.3f\n", mind, maxd ENDFB(I->Obj.G); } } return (ok); } /*========================================================================*/ static int ObjectMapFLDStrToMap(ObjectMap * I, char *PHIStr, int bytes, int state, int quiet) { char *p; float dens, dens_rev; int a, b, c, d, e; float v[3], maxd, mind; int ok = true; int little_endian = 1; /* PHI named from their docs */ int map_endian = 1; char cc[MAXLINELEN]; char *rev; int ndim = 0; int veclen = 0; int nspace = 0; ObjectMapState *ms; int got_ndim = false; int got_dim1 = false; int got_dim2 = false; int got_dim3 = false; int got_data = false; int got_veclen = false; int got_min_ext = false; int got_max_ext = false; int got_field = false; int got_nspace = false; little_endian = *((char *) &little_endian); map_endian = little_endian; if(state < 0) state = I->NState; if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(I->Obj.G, ms); maxd = -FLT_MAX; mind = FLT_MAX; p = PHIStr; while((*p) && (!(got_ndim && got_dim1 && got_dim2 && got_dim3 && got_veclen && got_min_ext && got_max_ext && got_field && got_nspace && got_data))) { if(!got_ndim) { ParseWordCopy(cc, p, 4); if(!strcmp(cc, "ndim")) { p = ParseSkipEquals(p); p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ndim) == 1) got_ndim = true; } } if(!got_dim1) { ParseWordCopy(cc, p, 4); if(!strcmp(cc, "dim1")) { p = ParseSkipEquals(p); p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->FDim[0]) == 1) got_dim1 = true; } } if(!got_dim2) { ParseWordCopy(cc, p, 4); if(!strcmp(cc, "dim2")) { p = ParseSkipEquals(p); p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->FDim[1]) == 1) got_dim2 = true; } } if(!got_dim3) { ParseWordCopy(cc, p, 4); if(!strcmp(cc, "dim3")) { p = ParseSkipEquals(p); p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->FDim[2]) == 1) got_dim3 = true; } } if(!got_nspace) { ParseWordCopy(cc, p, 6); if(!strcmp(cc, "nspace")) { p = ParseSkipEquals(p); p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &nspace) == 1) got_nspace = true; } } if(!got_veclen) { ParseWordCopy(cc, p, 6); if(!strcmp(cc, "veclen")) { p = ParseSkipEquals(p); p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &veclen) == 1) got_veclen = true; } } if(!got_data) { ParseWordCopy(cc, p, 4); if(!strcmp(cc, "data")) { p = ParseSkipEquals(p); p = ParseWordCopy(cc, p, 50); if(!strcmp(cc, "float")) got_data = true; } } if(!got_min_ext) { ParseWordCopy(cc, p, 7); if(!strcmp(cc, "min_ext")) { p = ParseSkipEquals(p); p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->ExtentMin[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->ExtentMin[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->ExtentMin[2]) == 1) { got_min_ext = true; } } } } } if(!got_max_ext) { ParseWordCopy(cc, p, 7); if(!strcmp(cc, "max_ext")) { p = ParseSkipEquals(p); p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->ExtentMax[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->ExtentMax[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->ExtentMax[2]) == 1) { got_max_ext = true; } } } } } if(!got_field) { ParseWordCopy(cc, p, 5); if(!strcmp(cc, "field")) { p = ParseSkipEquals(p); p = ParseWordCopy(cc, p, 50); if(!strcmp(cc, "uniform")) got_field = true; } } p = ParseNextLine(p); } if(got_ndim && got_dim1 && got_dim2 && got_dim3 && got_veclen && got_min_ext && got_max_ext && got_field && got_nspace && got_data) { int pass = 0; ms->Origin = Alloc(float, 3); ms->Range = Alloc(float, 3); ms->Grid = Alloc(float, 3); copy3f(ms->ExtentMin, ms->Origin); subtract3f(ms->ExtentMax, ms->ExtentMin, ms->Range); ms->FDim[3] = 3; PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " FLDStrToMap: Map Size %d x %d x %d\n", ms->FDim[0], ms->FDim[1], ms->FDim[2] ENDFB(I->Obj.G); for(a = 0; a < 3; a++) { ms->Min[a] = 0; ms->Max[a] = ms->FDim[a] - 1; ms->Div[a] = ms->FDim[a] - 1; if(ms->FDim[a]) ms->Grid[a] = ms->Range[a] / (ms->Max[a]); else ms->Grid[a] = 0.0F; } ms->Field = IsosurfFieldAlloc(I->Obj.G, ms->FDim); ms->MapSource = cMapSourceFLD; ms->Field->save_points = false; while(1) { maxd = -FLT_MAX; mind = FLT_MAX; p = PHIStr; while(*p) { /* ^L^L sentinel */ if((p[0] == 12) && (p[1] == 12)) { p += 2; break; } p++; } rev = (char *) &dens_rev; for(c = 0; c < ms->FDim[2]; c++) { /* z y x ordering into c b a so that x = a, etc. */ for(b = 0; b < ms->FDim[1]; b++) { for(a = 0; a < ms->FDim[0]; a++) { if(little_endian != map_endian) { rev[0] = p[3]; rev[1] = p[2]; rev[2] = p[1]; rev[3] = p[0]; } else { rev[0] = p[0]; /* gotta go char by char because of memory alignment issues ... */ rev[1] = p[1]; rev[2] = p[2]; rev[3] = p[3]; } dens = *((float *) rev); F3(ms->Field->data, a, b, c) = dens; if(maxd < dens) maxd = dens; if(mind > dens) mind = dens; p += 4; } } } /* There's no way to determine the original handedness of input field files. So instead, we simplymake an educated guess about whether we're byte-swapped based on the range of the density values obtained. */ if(((maxd / FLT_MAX) > 0.1F) && ((mind / (-FLT_MAX)) > 0.1F)) { if(pass == 0) { map_endian = (!map_endian); /* okay, try again swapped */ } else if(pass == 1) { /* didn't help, so resort to original order */ map_endian = (!map_endian); } else { break; } } else { break; } pass++; } for(c = 0; c < ms->FDim[2]; c++) { v[2] = ms->Origin[2] + ms->Grid[2] * (c + ms->Min[2]); for(b = 0; b < ms->FDim[1]; b++) { v[1] = ms->Origin[1] + ms->Grid[1] * (b + ms->Min[1]); for(a = 0; a < ms->FDim[0]; a++) { v[0] = ms->Origin[0] + ms->Grid[0] * (a + ms->Min[0]); for(e = 0; e < 3; e++) { F4(ms->Field->points, a, b, c, e) = v[e]; } } } } d = 0; for(c = 0; c < ms->FDim[2]; c += ms->FDim[2] - 1) { v[2] = ms->Origin[2] + ms->Grid[2] * (c + ms->Min[2]); if(!c) v[2] = ms->ExtentMin[2]; else v[2] = ms->ExtentMax[2]; for(b = 0; b < ms->FDim[1]; b += ms->FDim[1] - 1) { v[1] = ms->Origin[1] + ms->Grid[1] * (b + ms->Min[1]); if(!b) v[1] = ms->ExtentMin[1]; else v[1] = ms->ExtentMax[1]; for(a = 0; a < ms->FDim[0]; a += ms->FDim[0] - 1) { v[0] = ms->Origin[0] + ms->Grid[0] * (a + ms->Min[0]); if(!a) v[0] = ms->ExtentMin[0]; else v[0] = ms->ExtentMax[0]; copy3f(v, ms->Corner + 3 * d); d++; } } } ms->Active = true; ObjectMapUpdateExtents(I); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Results) " ObjectMap: Map read. Range: %5.3f to %5.3f\n", mind, maxd ENDFB(I->Obj.G); } } else { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Errors) " Error: unable to read FLD file.\n" ENDFB(I->Obj.G); /* printf(" got_ndim %d\n",got_ndim); printf(" got_dim1 %d\n",got_dim1); printf(" got_dim2 %d\n",got_dim2); printf(" got_dim3 %d\n",got_dim3); printf(" got_veclen %d\n",got_veclen); printf(" got_min_ext %d\n",got_min_ext); printf(" got_max_ext %d\n",got_max_ext); printf(" got_field %d\n",got_field); printf(" got_nspace %d\n",got_nspace); printf(" got_data %d\n",got_data); */ } return (ok); } /*========================================================================*/ static int ObjectMapBRIXStrToMap(ObjectMap * I, char *BRIXStr, int bytes, int state, int quiet) { char *p, *pp; float dens; int a, b, c, d, e; float v[3], vr[3], maxd, mind; int ok = true; char cc[MAXLINELEN]; ObjectMapState *ms; int got_origin = false; int got_extent = false; int got_grid = false; int got_cell = false; int got_prod = false; int got_plus = false; int got_sigma = false; int got_smiley = false; float prod = 1.0F; float plus = 0.0F; float sigma = 0.0F; float calc_sigma = 0.0F; float calc_mean = 0.0F; int normalize; int swap_bytes; normalize = SettingGetGlobal_b(I->Obj.G, cSetting_normalize_o_maps); swap_bytes = SettingGetGlobal_b(I->Obj.G, cSetting_swap_dsn6_bytes); if(state < 0) state = I->NState; if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(I->Obj.G, ms); maxd = -FLT_MAX; mind = FLT_MAX; p = BRIXStr; ParseNCopy(cc, p, 3); got_smiley = (strcmp(cc, ":-)") == 0); if(got_smiley) { /* ASCII BRIX format header */ while((*p) && (!(got_origin && got_extent && got_grid && got_cell && got_prod && got_plus && got_sigma))) { if(!got_origin) { pp = ParseWordCopy(cc, p, 6); if(WordMatch(I->Obj.G, "origin", cc, true) < 0) { p = ParseWordCopy(cc, pp, 50); if(sscanf(cc, "%d", &ms->Min[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Min[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Min[2]) == 1) { got_origin = true; } } } } } if(!got_extent) { pp = ParseWordCopy(cc, p, 6); if(WordMatch(I->Obj.G, "extent", cc, true) < 0) { p = ParseWordCopy(cc, pp, 50); if(sscanf(cc, "%d", &ms->Max[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Max[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Max[2]) == 1) { got_extent = true; ms->Max[0] += ms->Min[0] - 1; ms->Max[1] += ms->Min[1] - 1; ms->Max[2] += ms->Min[2] - 1; } } } } } if(!got_grid) { pp = ParseWordCopy(cc, p, 4); if(WordMatch(I->Obj.G, "grid", cc, true) < 0) { p = ParseWordCopy(cc, pp, 50); if(sscanf(cc, "%d", &ms->Div[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Div[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Div[2]) == 1) { got_grid = true; } } } } } if(!got_cell) { pp = ParseWordCopy(cc, p, 4); if(WordMatch(I->Obj.G, "cell", cc, true) < 0) { p = ParseWordCopy(cc, pp, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Dim[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Dim[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Dim[2]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Angle[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Angle[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Angle[2]) == 1) { got_cell = true; } } } } } } } } if(!got_plus) { pp = ParseWordCopy(cc, p, 4); if(WordMatch(I->Obj.G, "plus", cc, true) < 0) { p = ParseWordCopy(cc, pp, 50); if(sscanf(cc, "%f", &plus) == 1) { got_plus = true; } } } if(!got_prod) { pp = ParseWordCopy(cc, p, 4); if(WordMatch(I->Obj.G, "prod", cc, true) < 0) { p = ParseWordCopy(cc, pp, 50); if(sscanf(cc, "%f", &prod) == 1) { got_prod = true; } } } if(!got_sigma) { pp = ParseWordCopy(cc, p, 5); if(WordMatch(I->Obj.G, "sigma", cc, true) < 0) { p = ParseWordCopy(cc, pp, 50); if(sscanf(cc, "%f", &sigma) == 1) { got_sigma = true; } } } p++; } } else { /* Binary DSN6 format */ /* first, determine whether or not we need to byte-swap the header... */ int passed_endian_check = false; short int *shint_ptr; float scale_factor; char tmp_char; int a; int start_swap_at = 0; int stop_swap_at = bytes; shint_ptr = (short int *) (p + 18 * 2); if(*shint_ptr == 100) { passed_endian_check = true; start_swap_at = 512; /* don't byte-swap header */ } if(!swap_bytes) { stop_swap_at = 512; } /* for DSN6, always swap the bricks */ p = BRIXStr + start_swap_at; for(a = start_swap_at; a < stop_swap_at; a += 2) { tmp_char = *p; *p = *(p + 1); *(p + 1) = tmp_char; p += 2; } p = BRIXStr; if(*shint_ptr == 100) { passed_endian_check = true; } if(!passed_endian_check) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Errors) " Error: This looks like a DSN6 map file, but I can't match endianness.\n" ENDFB(I->Obj.G); } else { shint_ptr = (short int *) p; ms->Min[0] = *(shint_ptr++); ms->Min[1] = *(shint_ptr++); ms->Min[2] = *(shint_ptr++); got_origin = true; ms->Max[0] = *(shint_ptr++); ms->Max[1] = *(shint_ptr++); ms->Max[2] = *(shint_ptr++); got_extent = true; ms->Max[0] += ms->Min[0] - 1; ms->Max[1] += ms->Min[1] - 1; ms->Max[2] += ms->Min[2] - 1; ms->Div[0] = *(shint_ptr++); ms->Div[1] = *(shint_ptr++); ms->Div[2] = *(shint_ptr++); got_grid = true; ms->Symmetry->Crystal->Dim[0] = (float) (*(shint_ptr++)); ms->Symmetry->Crystal->Dim[1] = (float) (*(shint_ptr++)); ms->Symmetry->Crystal->Dim[2] = (float) (*(shint_ptr++)); ms->Symmetry->Crystal->Angle[0] = (float) (*(shint_ptr++)); ms->Symmetry->Crystal->Angle[1] = (float) (*(shint_ptr++)); ms->Symmetry->Crystal->Angle[2] = (float) (*(shint_ptr++)); got_cell = true; prod = (float) (*(shint_ptr++)) / 100.0F; got_prod = true; plus = (float) (*(shint_ptr++)); got_plus = true; scale_factor = (float) (*(shint_ptr++)); for(a = 0; a < 3; a++) { ms->Symmetry->Crystal->Dim[a] /= scale_factor; ms->Symmetry->Crystal->Angle[a] /= scale_factor; } } } if(got_origin && got_extent && got_grid && got_cell && got_plus && got_prod) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Blather) " BRIXStrToMap: Prod = %8.3f, Plus = %8.3f\n", prod, plus ENDFB(I->Obj.G); ms->FDim[0] = ms->Max[0] - ms->Min[0] + 1; ms->FDim[1] = ms->Max[1] - ms->Min[1] + 1; ms->FDim[2] = ms->Max[2] - ms->Min[2] + 1; ms->FDim[3] = 3; if(!(ms->FDim[0] && ms->FDim[1] && ms->FDim[2])) ok = false; else { SymmetryUpdate(ms->Symmetry); ms->Field = IsosurfFieldAlloc(I->Obj.G, ms->FDim); ms->MapSource = cMapSourceBRIX; ms->Field->save_points = false; { int block_size = 8; int xblocks = ((ms->FDim[0] - 1) / block_size) + 1; int yblocks = ((ms->FDim[1] - 1) / block_size) + 1; int zblocks = ((ms->FDim[2] - 1) / block_size) + 1; int cc, bb, aa, ia, ib, ic, xa, xb, xc; double sum = 0.0; double sumsq = 0.0; int n_pts = 0; p = BRIXStr + 512; for(cc = 0; cc < zblocks; cc++) { for(bb = 0; bb < yblocks; bb++) { for(aa = 0; aa < xblocks; aa++) { for(c = 0; c < block_size; c++) { xc = c + cc * block_size; ic = xc + ms->Min[2]; v[2] = ic / ((float) ms->Div[2]); for(b = 0; b < block_size; b++) { xb = b + bb * block_size; ib = xb + ms->Min[1]; v[1] = ib / ((float) ms->Div[1]); for(a = 0; a < block_size; a++) { xa = a + aa * block_size; ia = xa + ms->Min[0]; v[0] = ia / ((float) ms->Div[0]); dens = (((float) (*((unsigned char *) (p++)))) - plus) / prod; if((ia <= ms->Max[0]) && (ib <= ms->Max[1]) && (ic <= ms->Max[2])) { F3(ms->Field->data, xa, xb, xc) = dens; sumsq += dens * dens; sum += dens; n_pts++; if(maxd < dens) maxd = dens; if(mind > dens) mind = dens; transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); for(e = 0; e < 3; e++) { F4(ms->Field->points, xa, xb, xc, e) = vr[e]; } } } } } } } } if(n_pts > 1) { calc_mean = (float) (sum / n_pts); calc_sigma = (float) sqrt1d((sumsq - (sum * sum / n_pts)) / (n_pts - 1)); } } if(ok) { d = 0; for(c = 0; c < ms->FDim[2]; c += (ms->FDim[2] - 1)) { v[2] = (c + ms->Min[2]) / ((float) ms->Div[2]); for(b = 0; b < ms->FDim[1]; b += (ms->FDim[1] - 1)) { v[1] = (b + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < ms->FDim[0]; a += (ms->FDim[0] - 1)) { v[0] = (a + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); copy3f(vr, ms->Corner + 3 * d); d++; } } } } if(ok && normalize) { if(calc_sigma > R_SMALL8) { for(c = 0; c < ms->FDim[2]; c++) { for(b = 0; b < ms->FDim[1]; b++) { for(a = 0; a < ms->FDim[0]; a++) { F3(ms->Field->data, a, b, c) = (F3(ms->Field->data, a, b, c) - calc_mean) / calc_sigma; } } } } } v[2] = (ms->Min[2]) / ((float) ms->Div[2]); v[1] = (ms->Min[1]) / ((float) ms->Div[1]); v[0] = (ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMin); v[2] = ((ms->FDim[2] - 1) + ms->Min[2]) / ((float) ms->Div[2]); v[1] = ((ms->FDim[1] - 1) + ms->Min[1]) / ((float) ms->Div[1]); v[0] = ((ms->FDim[0] - 1) + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMax); PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " BRIXStrToMap: Map Size %d x %d x %d\n", ms->FDim[0], ms->FDim[1], ms->FDim[2] ENDFB(I->Obj.G); if(got_sigma) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " BRIXStrToMap: Reported Sigma = %8.3f\n", sigma ENDFB(I->Obj.G); } PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " BRIXStrToMap: Range = %5.6f to %5.6f\n", mind, maxd ENDFB(I->Obj.G); PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " BRIXStrToMap: Calculated Mean = %8.3f, Sigma = %8.3f\n", calc_mean, calc_sigma ENDFB(I->Obj.G); if(normalize) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " BRIXStrToMap: Normalizing...\n" ENDFB(I->Obj.G); } ms->Active = true; ObjectMapUpdateExtents(I); } } else { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Errors) " Error: unable to read BRIX/DSN6 file.\n" ENDFB(I->Obj.G); } return (ok); } /*========================================================================*/ static int ObjectMapGRDStrToMap(ObjectMap * I, char *GRDStr, int bytes, int state, int quiet) { /* NOTE: binary GRD reader not yet validated */ char *p; float dens; float *f = NULL; int a, b, c, d, e; float v[3], vr[3], maxd, mind; int ok = true; char cc[MAXLINELEN]; ObjectMapState *ms; int got_cell = false; int got_brick = false; int fast_axis = 1; /* assumes fast X */ int got_ranges = false; int normalize = false; float mean, stdev; double sum = 0.0; double sumsq = 0.0; int n_pts = 0; int ascii = true; int little_endian = 1, map_endian = 0; union int_or_char_array { int block_len; char rev[4]; }; union int_or_char_array rev_union; rev_union.block_len = 0; if(state < 0) state = I->NState; if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(I->Obj.G, ms); normalize = SettingGetGlobal_b(I->Obj.G, cSetting_normalize_grd_maps); maxd = -FLT_MAX; mind = FLT_MAX; p = GRDStr; if(bytes > 4) { if((!p[0]) || (!p[1]) || (!p[2]) || (!p[3])) { /* if zero appears in the first four bytes, then this is a binary map */ ascii = false; little_endian = *((char *) &little_endian); map_endian = (*p || *(p + 1)); } } /* print map title */ if(ascii) { p = ParseNCopy(cc, p, 100); } else { /* according to one site on the internet...GRD binary formats look like this: write(14) title write(14) scale,oldmid write(14) ivary,nbyte,intdat,extent,extent write(14) extent,xang,yang,zang,xstart write(14) xend,ystart,yend,zstart,zend write(14) intx,inty,intz do 100 i = 1,intz+1 do 100 j = 1,inty+1 100 write(14)(phimap(k,j,i),k=1,intx+1) where: scale is the inverse grid spacing, oldmid are x,y,z coordinates of the grid center, intx,inty,intz = grid points per side - 1 ivary = 0 nbyte = 4 intdat = 0 xang,yang,zang = 90 extent is the absolute value of the x,y, or z coordinate of the grid corners with the largest absolute value xstart,xend,ystart, yend,zstart,zend are the fractional limits (-1 to 1) of the molecule in each direction. title is a descriptive header for the molecule However, that doesn't make sense...in the files I see, scale and oldmid don't seem to exist! So here's another claim which I find more credible... character*132 toplbl !ascii header integer*4 ivary !0 => x index varys most rapidly integer*4 nbyte !=4, # of bytes in data integer*4 inddat !=0, floating point data real*4 xang,yang,zang !=90,90,90 unit cell angles integer*4 intx,inty,intz !=igrid-1, # of intervals/grid side real*4 extent !maximum extent of grid real*4 xstart,xend !beginning, end of grid sides real*4 ystart,yend !in fractional real*4 zstart,zend !units of extent write(14)toplbl write(14)ivary, nbyte, intdat, extent, extent, extent, xang, yang, zang, xstart, xend, ystart, yend, zstart, zend, intx, inty, intz do k = 1,igrid do j = 1,igrid write(14)(phimap(i,j,k),i=1,igrid) end do end d */ if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Warnings) " ObjectMapGRD-Warning: Binary GRD reader not yet validated.\n" ENDFB(I->Obj.G); } if(little_endian != map_endian) { rev_union.rev[0] = p[3]; rev_union.rev[1] = p[2]; rev_union.rev[2] = p[1]; rev_union.rev[3] = p[0]; } else { rev_union.rev[0] = p[0]; /* gotta go char by char because of memory alignment issues ... */ rev_union.rev[1] = p[1]; rev_union.rev[2] = p[2]; rev_union.rev[3] = p[3]; } ParseNCopy(cc, p + 4, rev_union.block_len); /* now flip file to correct endianess */ if(little_endian != map_endian) { char *c = p; int cnt = bytes >> 2; unsigned char c0, c1, c2, c3; while(cnt) { c0 = c[0]; c1 = c[1]; c2 = c[2]; c3 = c[3]; c[0] = c3; c[1] = c2; c[2] = c1; c[3] = c0; c += 4; cnt--; } } p += 4 + rev_union.block_len; f = (float *) p; } PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ObjectMap: %s\n", cc ENDFB(I->Obj.G); if(ascii) p = ParseNextLine(p); /* skip format -- we're reading float regardless... */ if(ascii) p = ParseNextLine(p); else { { int block_len_check; int ivary; int nbyte; int intdat; block_len_check = *((int *) (f++)); if(rev_union.block_len != block_len_check) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Warnings) " ObjectMapGRD-Warning: block length not matched -- not a true GRD binary?\n" ENDFB(I->Obj.G); } rev_union.block_len = *((int *) (f++)); ivary = *((int *) (f++)); nbyte = *((int *) (f++)); intdat = *((int *) (f++)); if((ivary) || (nbyte != 4) || (intdat)) { if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Warnings) " ObjectMapGRD-Warning: funky ivary, nbyte, intdat -- not a true GRD binary?\n" ENDFB(I->Obj.G); } } } } /* read unit cell */ if(ok) { if(ascii) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Dim[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Dim[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Dim[2]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Angle[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Angle[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%f", &ms->Symmetry->Crystal->Angle[2]) == 1) { got_cell = true; } } } } } } ok = got_cell; } else { ms->Symmetry->Crystal->Dim[0] = *(f++); /* x-extent */ ms->Symmetry->Crystal->Dim[1] = *(f++); /* y-extent */ ms->Symmetry->Crystal->Dim[2] = *(f++); /* z-extent */ ms->Symmetry->Crystal->Angle[0] = (*f++); /* xang */ ms->Symmetry->Crystal->Angle[1] = (*f++); /* yang */ ms->Symmetry->Crystal->Angle[2] = (*f++); /* zang */ got_cell = 1; } } if(ascii) p = ParseNextLine(p); if(ascii) { /* read brick dimensions */ if(ok) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->FDim[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->FDim[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->FDim[2]) == 1) { got_brick = true; ms->FDim[0]++; ms->FDim[1]++; ms->FDim[2]++; /* stupid 0-based counters */ } } } ok = got_brick; } p = ParseNextLine(p); /* read ranges */ if(ok) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &fast_axis) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Min[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Div[0]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Min[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Div[1]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Min[2]) == 1) { p = ParseWordCopy(cc, p, 50); if(sscanf(cc, "%d", &ms->Div[2]) == 1) { got_ranges = true; } } } } } } } ok = got_ranges; } } else { float fmin[3]; float fmax[3]; fmin[0] = *(f++); fmax[0] = *(f++); fmin[1] = *(f++); fmax[1] = *(f++); fmin[2] = *(f++); fmax[2] = *(f++); dump3f(fmin, "fmin"); dump3f(fmax, "fmax"); ms->FDim[0] = *((int *) f++) + 1; ms->FDim[1] = *((int *) f++) + 1; ms->FDim[2] = *((int *) f++) + 1; ms->Div[0] = pymol_roundf((ms->FDim[0] - 1) / (fmax[0] - fmin[0])); ms->Div[1] = pymol_roundf((ms->FDim[1] - 1) / (fmax[1] - fmin[1])); ms->Div[2] = pymol_roundf((ms->FDim[2] - 1) / (fmax[2] - fmin[2])); ms->Min[0] = pymol_roundf(ms->Div[0] * fmin[0]); ms->Min[1] = pymol_roundf(ms->Div[1] * fmin[1]); ms->Min[2] = pymol_roundf(ms->Div[2] * fmin[2]); ms->Max[0] = ms->Min[0] + ms->FDim[0] - 1; ms->Max[1] = ms->Min[1] + ms->FDim[1] - 1; ms->Max[2] = ms->Min[2] + ms->FDim[2] - 1; got_ranges = true; { int block_len_check; block_len_check = *((int *) (f++)); if(rev_union.block_len != block_len_check) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Warnings) " ObjectMapGRD-Warning: block length not matched -- not a true GRD binary?\n" ENDFB(I->Obj.G); } } } if(ok) { if(ascii) { ms->Div[0] = ms->Div[0] - ms->Min[0]; ms->Div[1] = ms->Div[1] - ms->Min[1]; ms->Div[2] = ms->Div[2] - ms->Min[2]; ms->Max[0] = ms->Min[0] + ms->FDim[0] - 1; ms->Max[1] = ms->Min[1] + ms->FDim[1] - 1; ms->Max[2] = ms->Min[2] + ms->FDim[2] - 1; } ms->FDim[3] = 3; if(Feedback(I->Obj.G, FB_ObjectMap, FB_Blather)) { dump3i(ms->Div, "ms->Div"); dump3i(ms->Min, "ms->Min"); dump3i(ms->Max, "ms->Max"); dump3i(ms->FDim, "ms->FDim"); } SymmetryUpdate(ms->Symmetry); ms->Field = IsosurfFieldAlloc(I->Obj.G, ms->FDim); ms->MapSource = cMapSourceGRD; ms->Field->save_points = false; switch (fast_axis) { case 3: /* Fast Y - BROKEN! */ PRINTFB(I->Obj.G, FB_ObjectMap, FB_Warnings) " ObjectMapGRD-Warning: fast_axis %d unsupported!\n", fast_axis ENDFB(I->Obj.G); /* intentional fall though... */ case 1: /* Fast X */ default: for(c = 0; c < ms->FDim[2]; c++) { v[2] = (c + ms->Min[2]) / ((float) ms->Div[2]); for(b = 0; b < ms->FDim[1]; b++) { if(!ascii) f++; /* skip block delimiter */ v[1] = (b + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < ms->FDim[0]; a++) { v[0] = (a + ms->Min[0]) / ((float) ms->Div[0]); if(ascii) { p = ParseNextLine(p); p = ParseNCopy(cc, p, 24); if(sscanf(cc, "%f", &dens) != 1) { ok = false; } } else { dens = *(f++); } if(ok) { sumsq += dens * dens; sum += dens; n_pts++; F3(ms->Field->data, a, b, c) = dens; if(maxd < dens) maxd = dens; if(mind > dens) mind = dens; } transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); for(e = 0; e < 3; e++) { F4(ms->Field->points, a, b, c, e) = vr[e]; } } if(!ascii) f++; /* skip fortran block delimiter */ } } break; } } if(n_pts > 1) { mean = (float) (sum / n_pts); stdev = (float) sqrt1d((sumsq - (sum * sum / n_pts)) / (n_pts - 1)); if(normalize) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ObjectMapGRDStrToMap: Normalizing: mean = %8.6f and stdev = %8.6f.\n", mean, stdev ENDFB(I->Obj.G); if(stdev < R_SMALL8) stdev = 1.0F; for(c = 0; c < ms->FDim[2]; c++) for(b = 0; b < ms->FDim[1]; b++) { for(a = 0; a < ms->FDim[0]; a++) { dens = F3(ms->Field->data, a, b, c); F3(ms->Field->data, a, b, c) = (dens - mean) / stdev; } } } else { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ObjectMapGRDStrToMap: Mean = %8.6f and stdev = %8.6f.\n", mean, stdev ENDFB(I->Obj.G); } } if(ok) { d = 0; for(c = 0; c < ms->FDim[2]; c += (ms->FDim[2] - 1)) { v[2] = (c + ms->Min[2]) / ((float) ms->Div[2]); for(b = 0; b < ms->FDim[1]; b += (ms->FDim[1] - 1)) { v[1] = (b + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < ms->FDim[0]; a += (ms->FDim[0] - 1)) { v[0] = (a + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); copy3f(vr, ms->Corner + 3 * d); d++; } } } v[2] = (ms->Min[2]) / ((float) ms->Div[2]); v[1] = (ms->Min[1]) / ((float) ms->Div[1]); v[0] = (ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMin); v[2] = ((ms->FDim[2] - 1) + ms->Min[2]) / ((float) ms->Div[2]); v[1] = ((ms->FDim[1] - 1) + ms->Min[1]) / ((float) ms->Div[1]); v[0] = ((ms->FDim[0] - 1) + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMax); PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " GRDXStrToMap: Map Size %d x %d x %d\n", ms->FDim[0], ms->FDim[1], ms->FDim[2] ENDFB(I->Obj.G); ms->Active = true; ObjectMapUpdateExtents(I); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Results) " ObjectMap: Map read. Range: %5.3f to %5.3f\n", mind, maxd ENDFB(I->Obj.G); } } else { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Errors) " Error: unable to read GRD file.\n" ENDFB(I->Obj.G); } return (ok); } /*========================================================================*/ static ObjectMap *ObjectMapReadXPLORStr(PyMOLGlobals * G, ObjectMap * I, char *XPLORStr, int state, int quiet) { int ok = true; int isNew = true; if(!I) isNew = true; else isNew = false; if(ok) { if(isNew) { I = (ObjectMap *) ObjectMapNew(G); isNew = true; } else { isNew = false; } ObjectMapXPLORStrToMap(I, XPLORStr, state, quiet); SceneChanged(I->Obj.G); SceneCountFrames(I->Obj.G); } return (I); } /*========================================================================*/ static ObjectMap *ObjectMapReadCCP4Str(PyMOLGlobals * G, ObjectMap * I, char *XPLORStr, int bytes, int state, int quiet) { int ok = true; int isNew = true; if(!I) isNew = true; else isNew = false; if(ok) { if(isNew) { I = (ObjectMap *) ObjectMapNew(G); isNew = true; } else { isNew = false; } ObjectMapCCP4StrToMap(I, XPLORStr, bytes, state, quiet); SceneChanged(G); SceneCountFrames(G); } return (I); } /*========================================================================*/ ObjectMap *ObjectMapLoadCCP4(PyMOLGlobals * G, ObjectMap * obj, const char *fname, int state, int is_string, int bytes, int quiet) { ObjectMap *I = NULL; char *buffer; long size; if(!is_string) { if (!quiet) PRINTFB(G, FB_ObjectMap, FB_Actions) " ObjectMapLoadCCP4File: Loading from '%s'.\n", fname ENDFB(G); buffer = FileGetContents(fname, &size); if(!buffer) ErrMessage(G, "ObjectMapLoadCCP4File", "Unable to open file!"); } else { buffer = (char*) fname; size = (long) bytes; } if (buffer) { I = ObjectMapReadCCP4Str(G, obj, buffer, size, state, quiet); if(!is_string) mfree(buffer); if(!quiet) { if(state < 0) state = I->NState - 1; if(state < I->NState) { ObjectMapState *ms; ms = &I->State[state]; if(ms->Active) { CrystalDump(ms->Symmetry->Crystal); } } } } return (I); } /*========================================================================*/ static ObjectMap *ObjectMapReadFLDStr(PyMOLGlobals * G, ObjectMap * I, char *MapStr, int bytes, int state, int quiet) { int ok = true; int isNew = true; if(!I) isNew = true; else isNew = false; if(ok) { if(isNew) { I = (ObjectMap *) ObjectMapNew(G); isNew = true; } else { isNew = false; } ObjectMapFLDStrToMap(I, MapStr, bytes, state, quiet); SceneChanged(G); SceneCountFrames(G); } return (I); } /*========================================================================*/ static ObjectMap *ObjectMapReadBRIXStr(PyMOLGlobals * G, ObjectMap * I, char *MapStr, int bytes, int state, int quiet) { int ok = true; int isNew = true; if(!I) isNew = true; else isNew = false; if(ok) { if(isNew) { I = (ObjectMap *) ObjectMapNew(G); isNew = true; } else { isNew = false; } ObjectMapBRIXStrToMap(I, MapStr, bytes, state, quiet); SceneChanged(G); SceneCountFrames(G); } return (I); } /*========================================================================*/ static ObjectMap *ObjectMapReadGRDStr(PyMOLGlobals * G, ObjectMap * I, char *MapStr, int bytes, int state, int quiet) { int ok = true; int isNew = true; if(!I) isNew = true; else isNew = false; if(ok) { if(isNew) { I = (ObjectMap *) ObjectMapNew(G); isNew = true; } else { isNew = false; } ObjectMapGRDStrToMap(I, MapStr, bytes, state, quiet); SceneChanged(G); SceneCountFrames(G); } return (I); } /*========================================================================*/ static ObjectMap *ObjectMapReadPHIStr(PyMOLGlobals * G, ObjectMap * I, char *MapStr, int bytes, int state, int quiet) { int ok = true; int isNew = true; if(!I) isNew = true; else isNew = false; if(ok) { if(isNew) { I = (ObjectMap *) ObjectMapNew(G); isNew = true; } else { isNew = false; } ObjectMapPHIStrToMap(I, MapStr, bytes, state, quiet); SceneChanged(G); SceneCountFrames(G); } return (I); } /*========================================================================*/ ObjectMap *ObjectMapLoadPHI(PyMOLGlobals * G, ObjectMap * obj, const char *fname, int state, int is_string, int bytes, int quiet) { ObjectMap *I = NULL; long size; char *buffer; if(!is_string) { if (!quiet) PRINTFB(G, FB_ObjectMap, FB_Actions) " ObjectMapLoadPHIFile: Loading from '%s'.\n", fname ENDFB(G); buffer = FileGetContents(fname, &size); if(!buffer) ErrMessage(G, "ObjectMapLoadPHIFile", "Unable to open file!"); } else { buffer = (char*) fname; size = (long) bytes; } if(buffer) { I = ObjectMapReadPHIStr(G, obj, buffer, size, state, quiet); if(!is_string) mfree(buffer); } return (I); } /*========================================================================*/ static int is_number(char *p) { int result = (*p != 0); char c; if(result) while((c = *(p++))) { if(!((c == '.') || (c == '-') || (c == '+') || (c == 'e') || (c == 'E') || ((c >= '0') && (c <= '9')))) result = false; break; } return result; } static int ObjectMapDXStrToMap(ObjectMap * I, char *DXStr, int bytes, int state, int quiet) { int n_items = 0; char *p, *pp; float dens; int a, b, c, d, e; float v[3], maxd, mind; int ok = true; /* DX named from their docs */ int stage = 0; ObjectMapState *ms; char cc[MAXLINELEN]; if(state < 0) state = I->NState; if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(I->Obj.G, ms); ms->Origin = Alloc(float, 3); ms->Grid = Alloc(float, 3); maxd = -FLT_MAX; mind = FLT_MAX; p = DXStr; /* get the dimensions */ ms->FDim[3] = 3; while(ok && (*p) && (stage == 0)) { pp = p; p = ParseNCopy(cc, p, 35); if((strcmp(cc, "object 1 class gridpositions counts") == 0) || is_number(cc)) { if(is_number(cc)) p = pp; p = ParseWordCopy(cc, p, 10); if(sscanf(cc, "%d", &ms->FDim[0]) == 1) { p = ParseWordCopy(cc, p, 10); if(sscanf(cc, "%d", &ms->FDim[1]) == 1) { p = ParseWordCopy(cc, p, 10); if(sscanf(cc, "%d", &ms->FDim[2]) == 1) { stage = 1; } } } } p = ParseNextLine(p); } if(ok && (stage == 1)) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " DXStrToMap: Dimensions: %d %d %d\n", ms->FDim[0], ms->FDim[1], ms->FDim[2] ENDFB(I->Obj.G); } /* get the origin */ while(ok && (*p) && (stage == 1)) { pp = p; p = ParseNCopy(cc, p, 6); if((strcmp(cc, "origin") == 0) || is_number(cc)) { if(is_number(cc)) p = pp; p = ParseWordCopy(cc, p, 20); if(sscanf(cc, "%f", &ms->Origin[0]) == 1) { p = ParseWordCopy(cc, p, 20); if(sscanf(cc, "%f", &ms->Origin[1]) == 1) { p = ParseWordCopy(cc, p, 20); if(sscanf(cc, "%f", &ms->Origin[2]) == 1) { stage = 2; } } } } p = ParseNextLine(p); } if(ok && (stage == 2)) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " DXStrToMap: Origin %8.3f %8.3f %8.3f\n", ms->Origin[0], ms->Origin[1], ms->Origin[2] ENDFB(I->Obj.G); } float delta[9]; int delta_i = 0; while(ok && (*p) && (stage == 2)) { pp = p; p = ParseNCopy(cc, p, 5); if(strcmp(cc, "delta") != 0) { if(is_number(cc)) { p = pp; } else { p = ParseNextLine(p); continue; } } if(3 != sscanf(p, " %f %f %f", delta + delta_i, delta + delta_i + 1, delta + delta_i + 2)) { // error break; } p = ParseNextLine(p); delta_i += 3; if (delta_i == 9) { stage = 3; if (is_diagonalf(3, delta)) { ms->Grid[0] = delta[0]; ms->Grid[1] = delta[4]; ms->Grid[2] = delta[8]; } else { if(!ms->State.Matrix) ms->State.Matrix = Alloc(double, 16); copy33f44d(delta, ms->State.Matrix); ms->State.Matrix[3] = ms->Origin[0]; ms->State.Matrix[7] = ms->Origin[1]; ms->State.Matrix[11] = ms->Origin[2]; ones3f(ms->Grid); zero3f(ms->Origin); } } } if(ok && (stage == 3)) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " DXStrToMap: Grid %8.3f %8.3f %8.3f\n", ms->Grid[0], ms->Grid[1], ms->Grid[2] ENDFB(I->Obj.G); } while(ok && (*p) && (stage == 3)) { p = ParseNCopy(cc, p, 6); if(strcmp(cc, "object") == 0) { p = ParseWordCopy(cc, p, 20); if (1 == sscanf(p, " class array type %*s rank %*s items %s", cc)) { if(sscanf(cc, "%d", &n_items) == 1) { if(n_items == ms->FDim[0] * ms->FDim[1] * ms->FDim[2]) stage = 4; } } } else if(is_number(cc)) { n_items = ms->FDim[0] * ms->FDim[1] * ms->FDim[2]; stage = 4; break; } p = ParseNextLine(p); } if(stage == 4) { if(ok && (stage == 4)) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " DXStrToMap: %d data points.\n", n_items ENDFB(I->Obj.G); } ms->Field = IsosurfFieldAlloc(I->Obj.G, ms->FDim); ms->MapSource = cMapSourceGeneralPurpose; ms->Field->save_points = false; for(a = 0; a < 3; a++) { ms->Div[a] = ms->FDim[a] - 1; ms->Min[a] = 0; ms->Max[a] = ms->FDim[a] - 1; } for(a = 0; a < ms->FDim[0]; a++) { for(b = 0; b < ms->FDim[1]; b++) { for(c = 0; c < ms->FDim[2]; c++) { p = ParseWordCopy(cc, p, 20); if(!cc[0]) { p = ParseNextLine(p); p = ParseWordCopy(cc, p, 20); } if(sscanf(cc, "%f", &dens) == 1) { if(maxd < dens) maxd = dens; if(mind > dens) mind = dens; F3(ms->Field->data, a, b, c) = dens; } else { ok = false; } } } } for(e = 0; e < 3; e++) { ms->ExtentMin[e] = ms->Origin[e] + ms->Grid[e] * ms->Min[e]; ms->ExtentMax[e] = ms->Origin[e] + ms->Grid[e] * ms->Max[e]; } for(c = 0; c < ms->FDim[2]; c++) { v[2] = ms->Origin[2] + ms->Grid[2] * (c + ms->Min[2]); for(b = 0; b < ms->FDim[1]; b++) { v[1] = ms->Origin[1] + ms->Grid[1] * (b + ms->Min[1]); for(a = 0; a < ms->FDim[0]; a++) { v[0] = ms->Origin[0] + ms->Grid[0] * (a + ms->Min[0]); for(e = 0; e < 3; e++) { F4(ms->Field->points, a, b, c, e) = v[e]; } } } } d = 0; for(c = 0; c < ms->FDim[2]; c += ms->FDim[2] - 1) { v[2] = ms->Origin[2] + ms->Grid[2] * (c + ms->Min[2]); for(b = 0; b < ms->FDim[1]; b += ms->FDim[1] - 1) { v[1] = ms->Origin[1] + ms->Grid[1] * (b + ms->Min[1]); for(a = 0; a < ms->FDim[0]; a += ms->FDim[0] - 1) { v[0] = ms->Origin[0] + ms->Grid[0] * (a + ms->Min[0]); copy3f(v, ms->Corner + 3 * d); d++; } } } if(ok) stage = 5; } if(stage != 5) ok = false; if(!ok) { ErrMessage(I->Obj.G, "ObjectMap", "Error reading map"); } else { ms->Active = true; ObjectMapUpdateExtents(I); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Results) " ObjectMap: Map read. Range: %5.3f to %5.3f\n", mind, maxd ENDFB(I->Obj.G); } } return (ok); } /*========================================================================*/ static ObjectMap *ObjectMapReadDXStr(PyMOLGlobals * G, ObjectMap * I, char *MapStr, int bytes, int state, int quiet) { int ok = true; int isNew = true; if(!I) isNew = true; else isNew = false; if(ok) { if(isNew) { I = (ObjectMap *) ObjectMapNew(G); isNew = true; } else { isNew = false; } ObjectMapDXStrToMap(I, MapStr, bytes, state, quiet); SceneChanged(G); SceneCountFrames(G); } return (I); } /*========================================================================*/ ObjectMap *ObjectMapLoadDXFile(PyMOLGlobals * G, ObjectMap * obj, const char *fname, int state, int quiet) { ObjectMap *I = NULL; long size; char *buffer; float mat[9]; buffer = FileGetContents(fname, &size); if(!buffer) { ErrMessage(G, "ObjectMapLoadDXFile", "Unable to open file!"); PRINTFB(G, FB_ObjectMap, FB_Errors) "ObjectMapLoadDXFile: Does '%s' exist?\n", fname ENDFB(G); } else { if(Feedback(G, FB_ObjectMap, FB_Actions)) { printf(" ObjectMapLoadDXFile: Loading from '%s'.\n", fname); } I = ObjectMapReadDXStr(G, obj, buffer, size, state, quiet); mfree(buffer); if(state < 0) state = I->NState - 1; if(state < I->NState) { ObjectMapState *ms; ms = &I->State[state]; if(ms->Active) { multiply33f33f(ms->Symmetry->Crystal->FracToReal, ms->Symmetry->Crystal->RealToFrac, mat); } } } return (I); } /*========================================================================*/ static int ObjectMapACNTStrToMap(ObjectMap * I, char *ACNTStr, int bytes, int state, int quiet) { int n_items = 0; char *p; float dens; int a, b, c, d, e; float v[3], maxd, mind; int ok = true; int stage = 0; ObjectMapState *ms; char cc[MAXLINELEN]; if(state < 0) state = I->NState; if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(I->Obj.G, ms); ms->Origin = Alloc(float, 3); ms->Grid = Alloc(float, 3); maxd = -FLT_MAX; mind = FLT_MAX; p = ACNTStr; /* skip header */ p = ParseNextLine(p); /* get the origin, spacing, and dimensions */ ms->FDim[3] = 3; /* read the map info */ { int i; for(i = 0; i < 3; i++) { int ii = (4 - i) % 3; /* y, x , z */ p = ParseWordCopy(cc, p, MAXLINELEN); if(sscanf(cc, "%f", &ms->Origin[ii]) == 1) { p = ParseWordCopy(cc, p, MAXLINELEN); if(sscanf(cc, "%f", &ms->Grid[ii]) == 1) { p = ParseWordCopy(cc, p, MAXLINELEN); if(sscanf(cc, "%d", &ms->FDim[ii]) == 1) { p = ParseNextLine(p); stage++; } } } } } /* skip the angles (ignored -- should probably check instead */ p = ParseNextLine(p); /* read the data block */ if(ok && (stage == 3)) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ACNTStrToMap: Dimensions: %d %d %d\n", ms->FDim[0], ms->FDim[1], ms->FDim[2] ENDFB(I->Obj.G); PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ACNTStrToMap: Origin %8.3f %8.3f %8.3f\n", ms->Origin[0], ms->Origin[1], ms->Origin[2] ENDFB(I->Obj.G); PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ACNTStrToMap: Grid %8.3f %8.3f %8.3f\n", ms->Grid[0], ms->Grid[1], ms->Grid[2] ENDFB(I->Obj.G); n_items = ms->FDim[0] * ms->FDim[1] * ms->FDim[2]; if(ok && (stage == 1)) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Details) " ACNTStrToMap: %d data points.\n", n_items ENDFB(I->Obj.G); } ms->Field = IsosurfFieldAlloc(I->Obj.G, ms->FDim); ms->MapSource = cMapSourceGeneralPurpose; ms->Field->save_points = false; for(a = 0; a < 3; a++) { ms->Div[a] = ms->FDim[a] - 1; ms->Min[a] = 0; ms->Max[a] = ms->FDim[a] - 1; } for(c = 0; c < ms->FDim[2]; c++) { for(a = 0; a < ms->FDim[0]; a++) { for(b = 0; b < ms->FDim[1]; b++) { p = ParseWordCopy(cc, p, MAXLINELEN); p = ParseNextLine(p); if(sscanf(cc, "%f", &dens) == 1) { if(maxd < dens) maxd = dens; if(mind > dens) mind = dens; F3(ms->Field->data, a, b, c) = dens; } else { ok = false; } } } } for(e = 0; e < 3; e++) { ms->ExtentMin[e] = ms->Origin[e] + ms->Grid[e] * ms->Min[e]; ms->ExtentMax[e] = ms->Origin[e] + ms->Grid[e] * ms->Max[e]; } for(c = 0; c < ms->FDim[2]; c++) { v[2] = ms->Origin[2] + ms->Grid[2] * (c + ms->Min[2]); for(b = 0; b < ms->FDim[1]; b++) { v[1] = ms->Origin[1] + ms->Grid[1] * (b + ms->Min[1]); for(a = 0; a < ms->FDim[0]; a++) { v[0] = ms->Origin[0] + ms->Grid[0] * (a + ms->Min[0]); for(e = 0; e < 3; e++) { F4(ms->Field->points, a, b, c, e) = v[e]; } } } } d = 0; for(c = 0; c < ms->FDim[2]; c += ms->FDim[2] - 1) { v[2] = ms->Origin[2] + ms->Grid[2] * (c + ms->Min[2]); for(b = 0; b < ms->FDim[1]; b += ms->FDim[1] - 1) { v[1] = ms->Origin[1] + ms->Grid[1] * (b + ms->Min[1]); for(a = 0; a < ms->FDim[0]; a += ms->FDim[0] - 1) { v[0] = ms->Origin[0] + ms->Grid[0] * (a + ms->Min[0]); copy3f(v, ms->Corner + 3 * d); d++; } } } if(ok) stage = 4; } if(stage != 4) ok = false; if(!ok) { ErrMessage(I->Obj.G, "ObjectMap", "Error reading map"); } else { ms->Active = true; ObjectMapUpdateExtents(I); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Results) " ObjectMap: Map read. Range: %5.3f to %5.3f\n", mind, maxd ENDFB(I->Obj.G); } } return (ok); } static ObjectMap *ObjectMapReadACNTStr(PyMOLGlobals * G, ObjectMap * I, char *MapStr, int bytes, int state, int quiet) { int ok = true; int isNew = true; if(!I) isNew = true; else isNew = false; if(ok) { if(isNew) { I = (ObjectMap *) ObjectMapNew(G); isNew = true; } else { isNew = false; } ObjectMapACNTStrToMap(I, MapStr, bytes, state, quiet); SceneChanged(G); SceneCountFrames(G); } return (I); } ObjectMap *ObjectMapLoadACNTFile(PyMOLGlobals * G, ObjectMap * obj, const char *fname, int state, int quiet) { ObjectMap *I = NULL; long size; char *buffer; float mat[9]; buffer = FileGetContents(fname, &size); if(!buffer) { ErrMessage(G, "ObjectMapLoadACNTFile", "Unable to open file!"); PRINTFB(G, FB_ObjectMap, FB_Errors) "ObjectMapLoadACNTFile: Does '%s' exist?\n", fname ENDFB(G); } else { if(Feedback(G, FB_ObjectMap, FB_Actions)) { printf(" ObjectMapLoadACNTFile: Loading from '%s'.\n", fname); } I = ObjectMapReadACNTStr(G, obj, buffer, size, state, quiet); mfree(buffer); if(state < 0) state = I->NState - 1; if(state < I->NState) { ObjectMapState *ms; ms = &I->State[state]; if(ms->Active) { multiply33f33f(ms->Symmetry->Crystal->FracToReal, ms->Symmetry->Crystal->RealToFrac, mat); } } } return (I); } /*========================================================================*/ ObjectMap *ObjectMapLoadFLDFile(PyMOLGlobals * G, ObjectMap * obj, const char *fname, int state, int quiet) { ObjectMap *I = NULL; long size; char *buffer; float mat[9]; buffer = FileGetContents(fname, &size); if(!buffer) { ErrMessage(G, "ObjectMapLoadFLDFile", "Unable to open file!"); } else { if(Feedback(G, FB_ObjectMap, FB_Actions)) { printf(" ObjectMapLoadFLDFile: Loading from '%s'.\n", fname); } I = ObjectMapReadFLDStr(G, obj, buffer, size, state, quiet); mfree(buffer); if(state < 0) state = I->NState - 1; if(state < I->NState) { ObjectMapState *ms; ms = &I->State[state]; if(ms->Active) { multiply33f33f(ms->Symmetry->Crystal->FracToReal, ms->Symmetry->Crystal->RealToFrac, mat); } } } return (I); } /*========================================================================*/ ObjectMap *ObjectMapLoadBRIXFile(PyMOLGlobals * G, ObjectMap * obj, const char *fname, int state, int quiet) { ObjectMap *I = NULL; long size; char *buffer; float mat[9]; buffer = FileGetContents(fname, &size); if(!buffer) { ErrMessage(G, "ObjectMapLoadBRIXFile", "Unable to open file!"); } else { if(Feedback(G, FB_ObjectMap, FB_Actions)) { printf(" ObjectMapLoadBRIXFile: Loading from '%s'.\n", fname); } I = ObjectMapReadBRIXStr(G, obj, buffer, size, state, quiet); mfree(buffer); if(state < 0) state = I->NState - 1; if(state < I->NState) { ObjectMapState *ms; ms = &I->State[state]; if(ms->Active) { CrystalDump(ms->Symmetry->Crystal); multiply33f33f(ms->Symmetry->Crystal->FracToReal, ms->Symmetry->Crystal->RealToFrac, mat); } } } return (I); } /*========================================================================*/ ObjectMap *ObjectMapLoadGRDFile(PyMOLGlobals * G, ObjectMap * obj, const char *fname, int state, int quiet) { ObjectMap *I = NULL; long size; char *buffer; float mat[9]; buffer = FileGetContents(fname, &size); if(!buffer) { ErrMessage(G, "ObjectMapLoadGRDFile", "Unable to open file!"); } else { if(Feedback(G, FB_ObjectMap, FB_Actions)) { printf(" ObjectMapLoadGRDFile: Loading from '%s'.\n", fname); } I = ObjectMapReadGRDStr(G, obj, buffer, size, state, quiet); mfree(buffer); if(state < 0) state = I->NState - 1; if(state < I->NState) { ObjectMapState *ms; ms = &I->State[state]; if(ms->Active) { CrystalDump(ms->Symmetry->Crystal); multiply33f33f(ms->Symmetry->Crystal->FracToReal, ms->Symmetry->Crystal->RealToFrac, mat); } } } return (I); } /*========================================================================*/ ObjectMap *ObjectMapLoadXPLOR(PyMOLGlobals * G, ObjectMap * obj, const char *fname, int state, int is_file, int quiet) { ObjectMap *I = NULL; long size; char *buffer; if(is_file) { buffer = FileGetContents(fname, &size); if(!buffer) ErrMessage(G, "ObjectMapLoadXPLOR", "Unable to open file!"); } else { buffer = (char*) fname; } if (buffer) { if((!quiet) && (Feedback(G, FB_ObjectMap, FB_Actions))) { if(is_file) { printf(" ObjectMapLoadXPLOR: Loading from '%s'.\n", fname); } else { printf(" ObjectMapLoadXPLOR: Loading...\n"); } } I = ObjectMapReadXPLORStr(G, obj, buffer, state, quiet); if(is_file) mfree(buffer); if(!quiet) { if(Feedback(G, FB_ObjectMap, FB_Details)) { if(state < 0) state = I->NState - 1; if(state < I->NState) { ObjectMapState *ms; ms = &I->State[state]; if(ms->Active) { CrystalDump(ms->Symmetry->Crystal); } } } } } return (I); } /*========================================================================*/ int ObjectMapSetBorder(ObjectMap * I, float level, int state) { int a; int result = true; if(state == -2) state = ObjectGetCurrentState(&I->Obj, false); for(a = 0; a < I->NState; a++) { if((state < 0) || (state == a)) { if(I->State[a].Active) result = result && ObjectMapStateSetBorder(&I->State[a], level); } } return (result); } /*========================================================================*/ #ifndef _PYMOL_NOPY static int ObjectMapNumPyArrayToMapState(PyMOLGlobals * G, ObjectMapState * ms, PyObject * ary, int quiet) { int a, b, c, d, e; float v[3], dens, maxd, mind; int ok = true; void * ptr; #ifdef _PYMOL_NUMPY PyArrayObject * pao = (PyArrayObject *) ary; const int itemsize = PyArray_ITEMSIZE(pao); #endif maxd = -FLT_MAX; mind = FLT_MAX; if(ok) { ms->FDim[0] = ms->Dim[0]; ms->FDim[1] = ms->Dim[1]; ms->FDim[2] = ms->Dim[2]; ms->FDim[3] = 3; if(!(ms->FDim[0] && ms->FDim[1] && ms->FDim[2])) ok = false; else { ms->Field = IsosurfFieldAlloc(G, ms->FDim); for(c = 0; c < ms->FDim[2]; c++) { v[2] = ms->Origin[2] + ms->Grid[2] * c; for(b = 0; b < ms->FDim[1]; b++) { v[1] = ms->Origin[1] + ms->Grid[1] * b; for(a = 0; a < ms->FDim[0]; a++) { v[0] = ms->Origin[0] + ms->Grid[0] * a; #ifdef _PYMOL_NUMPY ptr = PyArray_GETPTR3(pao, a, b, c); switch(itemsize) { case sizeof(double): dens = (float) *((double*)ptr); break; case sizeof(float): dens = *((float*)ptr); break; default: dens = 0.0; printf("no itemsize match\n"); } #else dens = 0.0; #endif F3(ms->Field->data, a, b, c) = dens; if(maxd < dens) maxd = dens; if(mind > dens) mind = dens; for(e = 0; e < 3; e++) F4(ms->Field->points, a, b, c, e) = v[e]; } } } d = 0; for(c = 0; c < ms->FDim[2]; c += (ms->FDim[2] - 1)) { v[2] = ms->Origin[2] + ms->Grid[2] * c; for(b = 0; b < ms->FDim[1]; b += (ms->FDim[1] - 1)) { v[1] = ms->Origin[1] + ms->Grid[1] * b; for(a = 0; a < ms->FDim[0]; a += (ms->FDim[0] - 1)) { v[0] = ms->Origin[0] + ms->Grid[0] * a; copy3f(v, ms->Corner + 3 * d); d++; } } } } } if(ok) { copy3f(ms->Origin, ms->ExtentMin); copy3f(ms->Origin, ms->ExtentMax); add3f(ms->Range, ms->ExtentMax, ms->ExtentMax); } if(!ok) { ErrMessage(G, "ObjectMap", "Error reading map"); } else { ms->Active = true; if(!quiet) { PRINTFB(G, FB_ObjectMap, FB_Results) " ObjectMap: Map read. Range: %5.3f to %5.3f\n", mind, maxd ENDFB(G); } } return (ok); } #endif /*========================================================================*/ ObjectMap *ObjectMapLoadChemPyBrick(PyMOLGlobals * G, ObjectMap * I, PyObject * Map, int state, int discrete, int quiet) { #ifndef _PYMOL_NUMPY ErrMessage(G, "ObjectMap", "missing numpy support, required for chempy.brick"); return NULL; #endif #ifdef _PYMOL_NOPY return NULL; #else int ok = true; int isNew = true; PyObject *tmp; ObjectMapState *ms; if(!I) isNew = true; else isNew = false; if(ok) { if(isNew) { I = (ObjectMap *) ObjectMapNew(G); isNew = true; } else { isNew = false; } if(state < 0) state = I->NState; if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(G, ms); if(PyObject_HasAttrString(Map, "origin") && PyObject_HasAttrString(Map, "dim") && PyObject_HasAttrString(Map, "range") && PyObject_HasAttrString(Map, "grid") && PyObject_HasAttrString(Map, "lvl")) { tmp = PyObject_GetAttrString(Map, "origin"); if(tmp) { PConvPyListToFloatArray(tmp, &ms->Origin); Py_DECREF(tmp); } else ok = ErrMessage(G, "ObjectMap", "missing brick origin."); tmp = PyObject_GetAttrString(Map, "dim"); if(tmp) { PConvPyListToIntArray(tmp, &ms->Dim); Py_DECREF(tmp); } else ok = ErrMessage(G, "ObjectMap", "missing brick dimension."); tmp = PyObject_GetAttrString(Map, "range"); if(tmp) { PConvPyListToFloatArray(tmp, &ms->Range); Py_DECREF(tmp); } else ok = ErrMessage(G, "ObjectMap", "missing brick range."); tmp = PyObject_GetAttrString(Map, "grid"); if(tmp) { PConvPyListToFloatArray(tmp, &ms->Grid); Py_DECREF(tmp); } else ok = ErrMessage(G, "ObjectMap", "missing brick grid."); tmp = PyObject_GetAttrString(Map, "lvl"); if(tmp) { ObjectMapNumPyArrayToMapState(G, ms, tmp, quiet); Py_DECREF(tmp); } else ok = ErrMessage(G, "ObjectMap", "missing brick density."); } else ok = ErrMessage(G, "ObjectMap", "missing any brick attribute."); SceneChanged(G); SceneCountFrames(G); if(ok) { int a; for(a = 0; a < 3; a++) { ms->Min[a] = 0; ms->Max[a] = ms->Dim[a] - 1; } ms->Active = true; ms->MapSource = cMapSourceChempyBrick; ObjectMapUpdateExtents(I); } } return (I); #endif } /*========================================================================*/ ObjectMap *ObjectMapLoadChemPyMap(PyMOLGlobals * G, ObjectMap * I, PyObject * Map, int state, int discrete, int quiet) { #ifdef _PYMOL_NOPY return NULL; #else int ok = true; int isNew = true; float *cobj; WordType format; float v[3], vr[3], dens, maxd, mind; int a, b, c, d, e; ObjectMapState *ms; maxd = -FLT_MAX; mind = FLT_MAX; if(!I) isNew = true; else isNew = false; if(ok) { if(isNew) { I = (ObjectMap *) ObjectMapNew(G); isNew = true; } else { isNew = false; } if(state < 0) state = I->NState; if(I->NState <= state) { VLACheck(I->State, ObjectMapState, state); I->NState = state + 1; } ms = &I->State[state]; ObjectMapStateInit(G, ms); if(!PConvAttrToStrMaxLen(Map, "format", format, sizeof(WordType) - 1)) ok = ErrMessage(G, "LoadChemPyMap", "bad 'format' parameter."); else if(!PConvAttrToFloatArrayInPlace(Map, "cell_dim", ms->Symmetry->Crystal->Dim, 3)) ok = ErrMessage(G, "LoadChemPyMap", "bad 'cell_dim' parameter."); else if(!PConvAttrToFloatArrayInPlace(Map, "cell_ang", ms->Symmetry->Crystal->Angle, 3)) ok = ErrMessage(G, "LoadChemPyMap", "bad 'cell_ang' parameter."); else if(!PConvAttrToIntArrayInPlace(Map, "cell_div", ms->Div, 3)) ok = ErrMessage(G, "LoadChemPyMap", "bad 'cell_div' parameter."); else if(!PConvAttrToIntArrayInPlace(Map, "first", ms->Min, 3)) ok = ErrMessage(G, "LoadChemPyMap", "bad 'first' parameter."); else if(!PConvAttrToIntArrayInPlace(Map, "last", ms->Max, 3)) ok = ErrMessage(G, "LoadChemPyMap", "bad 'last' parameter."); if(ok) { if(strcmp(format, "CObjectZYXfloat") == 0) { ok = PConvAttrToPtr(Map, "c_object", (void **) (void *) &cobj); if(!ok) ErrMessage(G, "LoadChemPyMap", "CObject unreadable."); } else { ok = ErrMessage(G, "LoadChemPyMap", "unsupported format."); } } /* good to go */ if(ok) { if(strcmp(format, "CObjectZYXfloat") == 0) { ms->FDim[0] = ms->Max[0] - ms->Min[0] + 1; ms->FDim[1] = ms->Max[1] - ms->Min[1] + 1; ms->FDim[2] = ms->Max[2] - ms->Min[2] + 1; if(Feedback(G, FB_ObjectMap, FB_Actions)) { printf(" LoadChemPyMap: CObjectZYXdouble %dx%dx%d\n", ms->FDim[0], ms->FDim[1], ms->FDim[2]); } ms->FDim[3] = 3; if(!(ms->FDim[0] && ms->FDim[1] && ms->FDim[2])) ok = false; else { SymmetryUpdate(ms->Symmetry); ms->Field = IsosurfFieldAlloc(G, ms->FDim); for(c = 0; c < ms->FDim[2]; c++) { v[2] = (c + ms->Min[2]) / ((float) ms->Div[2]); for(b = 0; b < ms->FDim[1]; b++) { v[1] = (b + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < ms->FDim[0]; a++) { v[0] = (a + ms->Min[0]) / ((float) ms->Div[0]); dens = *(cobj++); F3(ms->Field->data, a, b, c) = dens; if(maxd < dens) maxd = dens; if(mind > dens) mind = dens; transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); for(e = 0; e < 3; e++) F4(ms->Field->points, a, b, c, e) = vr[e]; } } } if(ok) { d = 0; for(c = 0; c < ms->FDim[2]; c += (ms->FDim[2] - 1)) { v[2] = (c + ms->Min[2]) / ((float) ms->Div[2]); for(b = 0; b < ms->FDim[1]; b += (ms->FDim[1] - 1)) { v[1] = (b + ms->Min[1]) / ((float) ms->Div[1]); for(a = 0; a < ms->FDim[0]; a += (ms->FDim[0] - 1)) { v[0] = (a + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, vr); copy3f(vr, ms->Corner + 3 * d); d++; } } } } } } } if(ok) { CrystalDump(ms->Symmetry->Crystal); v[2] = (ms->Min[2]) / ((float) ms->Div[2]); v[1] = (ms->Min[1]) / ((float) ms->Div[1]); v[0] = (ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMin); v[2] = ((ms->FDim[2] - 1) + ms->Min[2]) / ((float) ms->Div[2]); v[1] = ((ms->FDim[1] - 1) + ms->Min[1]) / ((float) ms->Div[1]); v[0] = ((ms->FDim[0] - 1) + ms->Min[0]) / ((float) ms->Div[0]); transform33f3f(ms->Symmetry->Crystal->FracToReal, v, ms->ExtentMax); } if(!ok) { ErrMessage(G, "ObjectMap", "Error reading map"); } else { ms->Active = true; ObjectMapUpdateExtents(I); if(!quiet) { PRINTFB(I->Obj.G, FB_ObjectMap, FB_Results) " ObjectMap: Map read. Range: %5.3f to %5.3f\n", mind, maxd ENDFB(I->Obj.G); } } if(ok) { SceneChanged(G); SceneCountFrames(G); } } return (I); #endif }