// Expand l-system into production string. // object_string is read with the k counter and // the next generation is built up in otemp void L_system() { // Map rule names typedef std::map<char, unsigned long> map_t; map_t S; // Each char gets a rule number for(unsigned long i = rules.size(); i > 0; i--) if(rules[i - 1].size()) S[(rules[i - 1][0])] = i - 1; // For each recursion unsigned long max = max_string - 10L; bool incomplete = false; for(unsigned long l = 0; l < lev; l++) { // Need markers ? bool marker = (l == (lev - 1)) && (fraction != 0.0); std::string otemp(""); unsigned long ss = 0; // For each char in the string for(unsigned long k = 0; k < object_string.size(); k++) { // Default rule which does nothing unsigned long i = rules.size() - 1; // i = rule number attached to current char map_t::const_iterator find_rule = S.find(object_string[k]); if(find_rule != S.end()) i = find_rule->second; // s = size of current rule unsigned long s = rules[i].size() - 2; ss += s; // Overflow if(ss >= max) { l = lev; incomplete = true; break; } // Add mark char if(marker && marks[i]) { otemp += '@'; otemp += std::string(rules[i], 2, s); otemp += '@'; } else { // Copy otemp += std::string(rules[i], 2, s); } } // Copy the temp string to object_string and repeat cycle object_string = otemp; } }
int NanoShaperInterface::compute_from_file(int surftype, float gspacing, float probe_radius, float skin_parm, float blob_parm, int n, int *ids, float *xyzr, int *flgs) { const char *nsbin = "NanoShaper"; // generate output file name and try to create char *dirname = vmd_tempfile(""); int uid = vmd_getuid(); int rnd = vmd_random() % 999; char *filebase = new char[strlen(dirname) + 100]; sprintf(filebase, "%svmdns.u%d.%d.", dirname, uid, rnd); delete [] dirname; char *pfilename = new char[strlen(filebase) + 100]; char *ofilename = new char[strlen(filebase) + 100]; sprintf(pfilename, "%sprm", filebase); sprintf(ofilename, "%sxyzr", filebase); FILE *pfile = fopen(pfilename, "wt"); if (!pfile) { delete [] filebase; delete [] pfilename; delete [] ofilename; msgErr << "Failed to create NanoShaper parameter input file" << sendmsg; return 0; // failure } const char *surfstr = "ses"; const char *modestr = "normal"; switch(surftype) { case NS_SURF_SES: surfstr = "ses"; modestr = "normal"; break; case NS_SURF_SKIN: surfstr = "skin"; modestr = "normal"; break; case NS_SURF_BLOBBY: surfstr = "blobby"; modestr = "normal"; break; case NS_SURF_POCKETS: surfstr = "pockets"; modestr = "pockets"; break; } // // Emit surface calculation configuration into NS input file // fprintf(pfile, "Operative_Mode = %s\n", modestr); fprintf(pfile, "Pocket_Radius_Small = %.1f\n", 1.4); fprintf(pfile, "Pocket_Radius_Big = %.1f\n", 3.0); fprintf(pfile, "Surface = %s\n", surfstr); if (gspacing < 0.05f) gspacing = 0.05f; fprintf(pfile, "Grid_scale = %.1f\n", 1.0f/gspacing); fprintf(pfile, "XYZR_FileName = %s\n", ofilename); fprintf(pfile, "Probe_Radius = %.1f\n", probe_radius); fprintf(pfile, "Skin_Surface_Parameter = %.2f\n", skin_parm); fprintf(pfile, "Blobbyness = %.1f\n", blob_parm); // enable all to emulate MSMS fprintf(pfile, "Compute_Vertex_Normals = true\n"); fprintf(pfile, "Save_Mesh_MSMS_Format = true\n"); fprintf(pfile, "Vertex_Atom_Info = true\n"); // various parameters copied from example input file fprintf(pfile, "Grid_perfil = %.1f\n", 70.0); fprintf(pfile, "Build_epsilon_maps = false\n"); fprintf(pfile, "Build_status_map = true\n"); fprintf(pfile, "Smooth_Mesh = true\n"); fprintf(pfile, "Triangulation = true\n"); // SD: optimized value for big structures fprintf(pfile, "Max_Probes_Self_Intersections = 5000\n"); fprintf(pfile, "Self_Intersections_Grid_Coefficient = 5.0\n"); fprintf(pfile, "Accurate_Triangulation = true\n"); // Tell NS to store all files by appending to a base filename provided // by the caller, so we don't end up with problems on multi-user systems // or when multiple VMD sessions are running concurrently on the same // machine. VMD chooses the base filename via OS temp file APIs. fprintf(pfile, "Root_FileName = %s\n", filebase); // SD: optimized value for big structures fprintf(pfile, "Max_skin_patches_per_auxiliary_grid_2d_cell = 2000\n"); fclose(pfile); FILE *ofile = fopen(ofilename, "wt"); if (!ofile) { delete [] ofilename; msgErr << "Failed to create NanoShaper atom xyzr input file" << sendmsg; return 0; // failure } char *facetfilename = new char[strlen(filebase) + 100]; char *vertfilename = new char[strlen(filebase) + 100]; char *errfilename = new char[strlen(filebase) + 100]; char *expfilename = new char[strlen(filebase) + 100]; char *expindfilename = new char[strlen(filebase) + 100]; char *areafilename = new char[strlen(filebase) + 100]; sprintf(facetfilename, "%striangulatedSurf.face", filebase); sprintf(vertfilename, "%striangulatedSurf.vert", filebase); sprintf(errfilename, "%sstderror.txt", filebase); sprintf(expfilename, "%sexposed.xyz", filebase); sprintf(expindfilename, "%sexposedIndices.txt", filebase); sprintf(areafilename, "%striangleAreas.txt", filebase); // temporary files we want to make sure to clean up VMDTempFile ptemp(pfilename); VMDTempFile otemp(ofilename); VMDTempFile ftemp(facetfilename); VMDTempFile vtemp(vertfilename); VMDTempFile errtemp(errfilename); VMDTempFile exptemp(expfilename); VMDTempFile expindtemp(expindfilename); VMDTempFile areatemp(areafilename); // // write atom coordinates and radii to the file we send to NanoShaper // for (int i=0; i<n; i++) { fprintf(ofile, "%f %f %f %f\n", xyzr[4L*i], xyzr[4L*i+1], xyzr[4L*i+2], xyzr[4L*i+3]); } fclose(ofile); // // call NanoShaper to calculate the surface for the given atoms // char *nscmd = new char[2*strlen(ofilename) + strlen(nsbin) + 100]; sprintf(nscmd, "\"%s\" %s", nsbin, pfilename); vmd_system(nscmd); delete [] nscmd; delete [] pfilename; // // read NanoShaper output files // if (surftype == NS_SURF_POCKETS) { // XXX pockets feature not complete yet msgErr << "NanoShaper pockets mode currently unimplemented" << sendmsg; return 0; } else { // Read output files for one of the normal surface modes // read facets FILE *facetfile = fopen(facetfilename, "r"); if (!facetfile) { msgErr << "Cannot read NanoShaper facet file: " << facetfilename << sendmsg; return 0; // failed } NanoShaperFace face; char trash[256]; fgets(trash, sizeof(trash), facetfile); // eat text comments and counts fgets(trash, sizeof(trash), facetfile); fgets(trash, sizeof(trash), facetfile); while (fscanf(facetfile, "%d %d %d %d %d", face.vertex+0, face.vertex+1, face.vertex+2, &face.surface_type, &face.anaface) == 5) { face.component = 0; // XXX Unused by VMD, so why store? face.vertex[0]--; face.vertex[1]--; face.vertex[2]--; faces.append(face); } fclose(facetfile); msgInfo << "NanoShaper face count: " << faces.num() << sendmsg; // read verts FILE *vertfile = fopen(vertfilename, "r"); if (!vertfile) { msgErr << "Cannot read NanoShaper vertex file: " << vertfilename << sendmsg; return 0; // failed } NanoShaperCoord norm, coord; int atomid; // 1-based atom index int l0fa; // number of of the level 0 SES face int l; // SES face level? (1/2/3) fgets(trash, sizeof(trash), vertfile); fgets(trash, sizeof(trash), vertfile); fgets(trash, sizeof(trash), vertfile); while (fscanf(vertfile, "%f %f %f %f %f %f %d %d %d", coord.x+0, coord.x+1, coord.x+2, norm.x+0, norm.x+1, norm.x+2, &l0fa, &atomid, &l) == 9) { norms.append(norm); coords.append(coord); atomids.append(atomid-1); } fclose(vertfile); msgInfo << "NanoShaper vert count: " << norms.num() << sendmsg; if (ids) { for (int i=0; i<atomids.num(); i++) { atomids[i] = ids[atomids[i]]; } } } return 1; // success }