/* Copyright (C) 2000-2004 Code contributed by Greg Collecutt, Joseph Hope and Paul Cochrane This file is part of xmds. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* $Id: xsilfield.cc,v 1.22 2005/05/19 03:42:00 joehope Exp $ */ /*! @file xsilfield.cc @brief XSIL format parsing classes and methods More detailed explanation... */ #include #include #include #include #include #include #define DEBUG 0 // ****************************************************************************** // ****************************************************************************** // xsilField public // ****************************************************************************** // ****************************************************************************** long nxsilFields=0; //!< The number of xsil fields // ****************************************************************************** xsilField::xsilField() { if(DEBUG) { nxsilFields++; printf("xsilField::xsilField\n"); printf("nxsilFields=%li\n",nxsilFields); } }; // ****************************************************************************** xsilField::~xsilField() { if(DEBUG) { nxsilFields--; printf("xsilField::~xsilField\n"); printf("nxsilFields=%li\n",nxsilFields); } }; // ****************************************************************************** void xsilField::processElement( const Element *const yourElement) { if(DEBUG) { printf("xsilField::processElement\n"); } fieldName=""; nIndependentVariables=0; variableNamesList.clear(); latticeList.clear(); const NodeList* candidateElements; const NamedNodeMap* elementAttributes; const Node* attributeNode; list anXMLStringList; // ************************************ // find name elementAttributes = yourElement->attributes(); attributeNode = elementAttributes->getNamedItem("Name"); if(attributeNode != 0) { fieldName = *attributeNode->nodeValue(); } else { throw xmdsException(yourElement,"Where is my Name='...' attribute?"); } // ************************************ // find n_independent Param assignment candidateElements = yourElement->getElementsByTagName("Param",0); if(candidateElements->length()>1) { throw xmdsException(yourElement,"Only one element expected "); } elementAttributes = candidateElements->item(0)->attributes(); attributeNode = elementAttributes->getNamedItem("Name"); if(attributeNode != 0) { if(*attributeNode->nodeValue() == "n_independent") { if(!candidateElements->item(0)->textContent(0)->asULong(nIndependentVariables)) { throw xmdsException(candidateElements->item(0),"Invalid positive integer format"); } } else { throw xmdsException(candidateElements->item(0),"Unknown element"); } } else { throw xmdsException(candidateElements->item(0),"Where is my Name='...' attribute?"); } // ************************************ // find Arrays candidateElements = yourElement->getElementsByTagName("Array",0); if(candidateElements->length() != 2) { throw xmdsException(yourElement,"Exactly two elements expected "); } // ************************************ // find variables Array elementAttributes = candidateElements->item(0)->attributes(); attributeNode = elementAttributes->getNamedItem("Name"); if(attributeNode != 0) { if(*attributeNode->nodeValue() != "variables") { sprintf(errorMessage(),"Unknown element '%s'",attributeNode->nodeValue()->c_str()); throw xmdsException(yourElement,errorMessage()); } } else throw xmdsException(candidateElements->item(0),"Where is my Name='...' attribute?"); const Element* myVariablesArrayElement = dynamic_cast(candidateElements->item(0)); // ************************************ // find data Array elementAttributes = candidateElements->item(1)->attributes(); attributeNode = elementAttributes->getNamedItem("Name"); if(attributeNode != 0) { if(*attributeNode->nodeValue() != "data") { sprintf(errorMessage(),"Unknown element '%s'",attributeNode->nodeValue()->c_str()); throw xmdsException(yourElement,errorMessage()); } } else { throw xmdsException(candidateElements->item(1),"Where is my Name='...' attribute?"); } const Element* myDataArrayElement = dynamic_cast(candidateElements->item(1)); // ************************************ // process variables Array unsigned long nVariables; candidateElements = myVariablesArrayElement->getElementsByTagName("Dim",0); if(candidateElements->length()>1) { throw xmdsException(myVariablesArrayElement,"Only one element expected "); } if(!candidateElements->item(0)->textContent(0)->asULong(nVariables)) { throw xmdsException(candidateElements->item(0),"Invalid positive integer format"); } getAssignmentStrings(myVariablesArrayElement,"Stream",1,nVariables,variableNamesList); // ************************************ // process data Array candidateElements = myDataArrayElement->getElementsByTagName("Dim",0); if(candidateElements->length() != nIndependentVariables + 1) { sprintf(errorMessage(),"Exactly %li elements expected",nIndependentVariables + 1); throw xmdsException(myDataArrayElement,errorMessage()); } for(unsigned long i=0 ; ilength(); i++) { unsigned long nextDim; if(!candidateElements->item(i)->textContent(0)->asULong(nextDim)) { throw xmdsException(candidateElements->item(i),"Invalid positive integer format"); } latticeList.push_back(nextDim); } candidateElements = myDataArrayElement->getElementsByTagName("Stream",0); if(candidateElements->length() != 1) { throw xmdsException(myDataArrayElement,"A element expected"); } const Element* myStreamElement = dynamic_cast(candidateElements->item(0)); // get the Metalink tags candidateElements = myDataArrayElement->getElementsByTagName("Metalink",1); if (candidateElements->length() != 1) { throw xmdsException(myDataArrayElement," element expected"); } // get the Format attribute elementAttributes = candidateElements->item(0)->attributes(); attributeNode = elementAttributes->getNamedItem("Format"); if(attributeNode != 0) { if(*attributeNode->nodeValue() != "Text" && *attributeNode->nodeValue() != "Binary") { sprintf(errorMessage(),"Unknown attribute '%s'",attributeNode->nodeValue()->c_str()); throw xmdsException(yourElement,errorMessage()); } } else { throw xmdsException(candidateElements->item(0),"Where is my Format='...' attribute?"); } // determine the stream format and work out where the data is streamFormat = *attributeNode->nodeValue(); if(streamFormat == "Text") { // ok then, the data is ascii, go get it tiger! data = *myStreamElement->textContent(0); } else if (streamFormat == "Binary") { // data is binary, the textContent of the Stream element is the datafile filename binDatFname = *myStreamElement->textContent(0); // try to remove whitespace chars std::string tmp = binDatFname.c_str(); std::string tmp2; for (unsigned long int i=0; igetNamedItem("Encoding"); if (attributeNode != 0) { if (*attributeNode->nodeValue() != "LittleEndian" && *attributeNode->nodeValue() != "BigEndian") { sprintf(errorMessage(),"Unknown attribute '%s'", attributeNode->nodeValue()->c_str()); throw xmdsException(yourElement,errorMessage()); } } else { throw xmdsException(candidateElements->item(0),"Where is my Encoding='...' attribute?"); } // the binary encoding of the data file binEncoding = *attributeNode->nodeValue(); // get the precision attribute elementAttributes = candidateElements->item(0)->attributes(); attributeNode = elementAttributes->getNamedItem("precision"); if(attributeNode != 0) { if(*attributeNode->nodeValue() != "single" && *attributeNode->nodeValue() != "double") { sprintf(errorMessage(),"Unknown attribute '%s'",attributeNode->nodeValue()->c_str()); throw xmdsException(yourElement,errorMessage()); } } else { throw xmdsException(candidateElements->item(0),"Where is my precison='...' attribute?"); } // the precison of the binary data binPrecision = *attributeNode->nodeValue(); // get the UnsignedLong attribute elementAttributes = candidateElements->item(0)->attributes(); attributeNode = elementAttributes->getNamedItem("UnsignedLong"); if(attributeNode != 0) { if(*attributeNode->nodeValue() != "ulong" && *attributeNode->nodeValue() != "uint32" && *attributeNode->nodeValue() != "uint64") { sprintf(errorMessage(),"Unknown attribute '%s'",attributeNode->nodeValue()->c_str()); throw xmdsException(yourElement,errorMessage()); } ulongType = *attributeNode->nodeValue(); } else { ulongType = "ulong"; printf("Defaulting to ulong\n"); } } }; // ****************************************************************************** void xsilField::writeAsFormat( FILE *const outfile, const outputFormatEnum& format, const long& iD, const char *datFileNameBase) { if(DEBUG) { printf("xsilField::writeAsFormat\n"); } if (streamFormat == "Text") { // dump data as ascii file char datFileName[64]; sprintf(datFileName,"%s%li.dat",datFileNameBase,iD); FILE *tempfile=fopen(datFileName,"w"); // write header row (this doesn't work for matlab!) if(format != FORMAT_MATLAB) { for(list::const_iterator pXMLString = variableNamesList.begin(); pXMLString != variableNamesList.end(); pXMLString++) { fprintf(tempfile," %s ",pXMLString->c_str()); } } // write data fprintf(tempfile,"%s",data.c_str()); fclose(tempfile); // initialise variables list::iterator pXMLString = variableNamesList.begin(); for(unsigned long i=0;igoLatinAlphaNumeric(); char tempString[64]; sprintf(tempString,"_%li",iD); *pXMLString += tempString; if(nIndependentVariables==0) { fprintf(outfile,"%s = zeros(1,1);\n",pXMLString->c_str()); } else if(nIndependentVariables==1) { if(i==0) { fprintf(outfile,"temp_d1 = zeros(1,%li);\n",lattice(0)); } else { fprintf(outfile,"%s = zeros(1,%li);\n",pXMLString->c_str(),lattice(0)); } } else { if(ic_str(),lattice(nIndependentVariables-1)); } for(unsigned long j=nIndependentVariables-1;j>0;j--) { fprintf(outfile,",%li",lattice(j-1)); } fprintf(outfile,");\n"); } if(ic_str(),lattice(i)); } pXMLString++; } fprintf(outfile,"\n"); // load in temp file if(format==FORMAT_SCILAB) { fprintf(outfile,"%s%li = fscanfMat('%s');\n",datFileNameBase,iD,datFileName); } else { fprintf(outfile,"load %s -ascii\n",datFileName); } for(unsigned long i=0;ic_str(),datFileNameBase,iD,i+1); } // work out coordinates for(unsigned long i=0;ic_str(),i+1); if(i==(nIndependentVariables-1)) { fprintf(outfile,":"); } else { fprintf(outfile,"1"); } for(unsigned long j=nIndependentVariables-1;j>0;j--) { if((j-1)==i) { fprintf(outfile,",:"); } else { fprintf(outfile,",1"); } } fprintf(outfile,");\n"); } fprintf(outfile,"\n"); // clear excess variables fprintf(outfile,"clear %s%li",datFileNameBase,iD); for(unsigned long i=0;i::iterator pXMLString = variableNamesList.begin(); pXMLString != variableNamesList.end(); pXMLString++) { char tempString[64]; sprintf(tempString,"_%li",iD); *pXMLString += tempString; if (k < nIndependentVariables) { fprintf(outfile,"%sLen = fread(fpDat,1,'%s');\n",pXMLString->c_str(),ulongType.c_str()); fprintf(outfile,"%s = zeros(1,%sLen);\n",pXMLString->c_str(),pXMLString->c_str()); fprintf(outfile,"%s(:) = fread(fpDat,%sLen,'%s');\n",pXMLString->c_str(),pXMLString->c_str(),binPrecision.c_str()); } else if (k >= nIndependentVariables) { fprintf(outfile,"%sLen = fread(fpDat,1,'%s');\n",pXMLString->c_str(),ulongType.c_str()); if (nIndependentVariables == 1) { fprintf(outfile,"%s = fread(fpDat,%sLen,'%s');\n",pXMLString->c_str(), variableNamesList.begin()->c_str(),binPrecision.c_str()); } else if (nIndependentVariables == 2) { fprintf(outfile,"%s = fread(fpDat,[%sLen,%sLen],'%s');\n",pXMLString->c_str(), (++variableNamesList.begin())->c_str(),variableNamesList.begin()->c_str(),binPrecision.c_str()); } else if (nIndependentVariables > 2) { // now we need to create a multi-dimensional matrix, // and this is harder to do... // we need to read in a matrix-sized (ie 2D) block at a time, // and append this to the other dimensions the number of // independent variables determines the dimensions of the // N-D matrix to produce // construct the for loop to loop over the third and subsequent dimensions list::iterator pIndepVars = variableNamesList.begin(); for (unsigned long int inumIndepVars=2; inumIndepVarsc_str()); pIndepVars++; } // generate the first part of the string, which is the array to be assigned into fprintf(outfile, "%s(:,:,",pXMLString->c_str()); pIndepVars = variableNamesList.begin(); for (unsigned long int inumIndepVars=nIndependentVariables-1; inumIndepVars>=2; inumIndepVars--) { fprintf(outfile, "index%li",inumIndepVars-2); // need to append a comma if not the last index to append if (inumIndepVars != 2) { fprintf(outfile,","); } } // generate the fread statement // to do this, I have to work out what the last and second-to-last // independent variable names are this is because, for some reason, // one can't inspect a given element of a list // first, the last one pIndepVars = variableNamesList.begin(); XMLString lastIndepVar; for (unsigned long int inumIndepVars=0; inumIndepVars::iterator pXMLString = variableNamesList.begin(); pXMLString != variableNamesList.end(); pXMLString++) { fprintf(outfile, "%sLen ",pXMLString->c_str()); } for (unsigned long int inumIndepVars=2; inumIndepVars tag).\n" "Exiting...\n"); exit(254); } else { throw(xmdsException("Unknown format. I only accept Matlab or Scilab at present\n")); } } else { throw(xmdsException("Stream format is neither Text or Binary, something has seriously gone wrong!\n")); } }; // ****************************************************************************** // ****************************************************************************** // xsilField private // ****************************************************************************** // ****************************************************************************** // ****************************************************************************** unsigned long xsilField::lattice( const unsigned long& index) const { if(DEBUG) { printf("xsilField::lattice\n"); } if(index>=latticeList.size()) { throw xmdsException("Internal range error in xsilField::lattice"); } list::const_iterator pULong = latticeList.begin(); for(unsigned long i=0; i=variableNamesList.size()) { throw xmdsException("Internal range error in xsilField::variableName"); } list::const_iterator pXMLString = variableNamesList.begin(); for(unsigned long i=0; i