CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/CommonTools/Utils/src/TMVAZipReader.cc

Go to the documentation of this file.
00001 #include "CommonTools/Utils/interface/TMVAZipReader.h"
00002 #include "FWCore/Utilities/interface/Exception.h"
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <cstdio>
00006 #include <cstdlib>
00007 #include "zlib.h"
00008 
00009 using namespace std;
00010 
00011 // From http://stackoverflow.com/questions/874134/find-if-string-endswith-another-string-in-c
00012 bool reco::details::hasEnding(std::string const &fullString, std::string const &ending) {
00013   if (fullString.length() >= ending.length()) {
00014     return (0 == fullString.compare(
00015           fullString.length() - ending.length(), ending.length(), ending));
00016   } else {
00017     return false;
00018   }
00019 }
00020 
00021 char* reco::details::readGzipFile(const std::string& weightFile)
00022 {
00023   FILE *f = fopen(weightFile.c_str(), "r");
00024   if (f==NULL) {
00025     throw cms::Exception("InvalidFileState")
00026       << "Failed to open MVA file = " << weightFile << " !!\n";
00027   }
00028   int magic;
00029   int size;
00030   fread(&magic, 4, 1, f);
00031   fseek(f, -4, SEEK_END);
00032   fread(&size, 4, 1, f);
00033   fclose(f);
00034   //printf("%x, %i\n", magic, size);
00035 
00036   gzFile  file = gzopen (weightFile.c_str(), "r");
00037 
00038   int bytes_read;
00039   char *buffer = (char*)malloc(size);
00040   bytes_read = gzread (file, buffer, size - 1);
00041   buffer[bytes_read] = '\0';
00042   if (!gzeof (file)) {
00043     int err;
00044     const char * error_string;
00045     error_string = gzerror (file, & err);
00046     if (err) {
00047       free(buffer);
00048       throw cms::Exception("InvalidFileState")
00049         << "Error while reading gzipped file = " << weightFile << " !!\n"
00050         << error_string;
00051     }
00052   }
00053   gzclose (file);
00054   return buffer;
00055 }
00056 
00057 void reco::details::loadTMVAWeights(TMVA::Reader* reader, const std::string& method,
00058     const std::string& weightFile, bool verbose) {
00059   verbose = false;
00060   if (verbose)
00061     std::cout << "Booking TMVA Reader with " << method << " and weight file: " << weightFile
00062       << std::endl;
00063 
00064   if (reco::details::hasEnding(weightFile, ".xml")) {
00065     if (verbose)
00066       std::cout << "Weight file is pure xml." << std::endl;
00067     // Let TMVA read the file
00068     reader->BookMVA(method, weightFile);
00069   } else if (reco::details::hasEnding(weightFile, ".gz") || reco::details::hasEnding(weightFile, ".gzip")) {
00070     if (verbose)
00071       std::cout << "Unzipping file." << std::endl;
00072     char* c = readGzipFile(weightFile);
00073 
00074     // We can't use tmpnam, gcc emits a warning about security.
00075     // This is also technically insecure in the same way, since we append
00076     // a suffix and then open another file.
00077     char tmpFilename[] = "/tmp/tmva.XXXXXX";
00078     int fdToUselessFile = mkstemp(tmpFilename);
00079     std::string weight_file_name(tmpFilename);
00080     weight_file_name += ".xml";
00081     FILE *theActualFile = fopen(weight_file_name.c_str(), "w");
00082     // write xml
00083     fputs(c, theActualFile);
00084     fputs("\n", theActualFile);
00085     fclose(theActualFile);
00086     close(fdToUselessFile);
00087     if (verbose)
00088       std::cout << "Booking MvA" << std::endl;
00089     reader->BookMVA(method, weight_file_name);
00090     if (verbose)
00091       std::cout << "Cleaning up" << std::endl;
00092     remove(weight_file_name.c_str());
00093     remove(tmpFilename);
00094 
00095     // Someday this will work.
00096     //reader->BookMVA(TMVA::Types::Instance().GetMethodType(TString(method)), c);
00097     if (verbose) {
00098       std::cout << "Reader booked" << std::endl;
00099     }
00100     free(c);
00101   } else {
00102     throw cms::Exception("BadTMVAWeightFilename")
00103       << "I don't understand the extension on the filename: "
00104       << weightFile << ", it should be .xml, .gz, or .gzip" << std::endl;
00105   }
00106 }