//------------------------------------------------------------------------------ bool OBOpenDXCubeFormat::ReadMolecule( OBBase* pOb, OBConversion* pConv ) { OBMol* pmol = pOb->CastAndClear<OBMol>(); if(pmol == 0) return false; istream& ifs = *pConv->GetInStream(); const char* title = pConv->GetTitle(); char buffer[BUFF_SIZE]; stringstream errorMsg; if (!ifs) return false; // We are attempting to read past the end of the file pmol->SetTitle(title); while (ifs.good() && ifs.getline(buffer,BUFF_SIZE)) { if (buffer[0] == '#') continue; // comment line if (EQn(buffer, "object", 6)) break; } if (!ifs) return false; // ran out of lines vector<string> vs; tokenize(vs, buffer); // Number of grid points (voxels) vector<int> voxels(3); if (!EQn(buffer, "object", 6) || vs.size() != 8) return false; else { voxels[0] = atoi(vs[5].c_str()); voxels[1] = atoi(vs[6].c_str()); voxels[2] = atoi(vs[7].c_str()); } double x, y, z; if (!ifs.getline(buffer, BUFF_SIZE) || !EQn(buffer, "origin", 6)) return false; else { tokenize(vs, buffer); if (vs.size() != 4) return false; x = atof(vs[1].c_str()); y = atof(vs[2].c_str()); z = atof(vs[3].c_str()); } vector3 origin(x, y, z); // now three lines with the x, y, and z axes vector<vector3> axes; for (unsigned int i = 0; i < 3; ++i) { if (!ifs.getline(buffer, BUFF_SIZE) || !EQn(buffer, "delta", 5)) return false; else { tokenize(vs, buffer); if (vs.size() != 4) return false; x = atof(vs[1].c_str()); y = atof(vs[2].c_str()); z = atof(vs[3].c_str()); axes.push_back(vector3(x, y, z)); } } // Two remaining header lines before the data: /* object 2 class gridconnections counts nx ny nz object 3 class array type double rank 0 times n data follows */ if (!ifs.getline(buffer, BUFF_SIZE) || !EQn(buffer, "object", 6)) return false; if (!ifs.getline(buffer, BUFF_SIZE) || !EQn(buffer, "object", 6)) return false; pmol->BeginModify(); pmol->SetDimension(3); OBGridData *gd = new OBGridData; gd->SetAttribute("OpenDX"); // get all values as one vector<double> char *endptr; vector<double> values; int n = voxels[0]*voxels[1]*voxels[2]; int line = 0; values.reserve(n); while (ifs.getline(buffer, BUFF_SIZE)) { ++line; if (EQn(buffer, "attribute", 9)) break; // we're finished with reading data -- although we should probably have a voxel check in here too tokenize(vs, buffer); if (vs.size() == 0) { errorMsg << "Problem reading the OpenDX grid file: cannot" << " read line " << line << ", there does not appear to be any data in it.\n" << buffer << "\n"; obErrorLog.ThrowError(__FUNCTION__, errorMsg.str(), obError); return false; } for (unsigned int l = 0; l < vs.size(); ++l) { values.push_back(strtod(static_cast<const char*>(vs[l].c_str()), &endptr)); } } gd->SetNumberOfPoints(voxels[0], voxels[1], voxels[2]); gd->SetLimits(origin, axes[0], axes[1], axes[2]); gd->SetUnit(OBGridData::ANGSTROM); gd->SetOrigin(fileformatInput); // i.e., is this data from a file or determined by Open Babel gd->SetValues(values); // set the values pmol->SetData(gd); // store the grids in the OBMol pmol->EndModify(); // Trailing control lines /* attribute "dep" string "positions" object "regular positions regular connections" class field component "positions" value 1 component "connections" value 2 component "data" value 3 */ if (!ifs.getline(buffer, BUFF_SIZE) || !EQn(buffer, "object", 6)) return false; if (!ifs.getline(buffer, BUFF_SIZE) || !EQn(buffer, "component", 9)) return false; if (!ifs.getline(buffer, BUFF_SIZE) || !EQn(buffer, "component", 9)) return false; if (!ifs.getline(buffer, BUFF_SIZE) || !EQn(buffer, "component", 9)) return false; // clean out any remaining blank lines std::streampos ipos; do { ipos = ifs.tellg(); ifs.getline(buffer,BUFF_SIZE); } while(strlen(buffer) == 0 && !ifs.eof() ); ifs.seekg(ipos); return true; }