00001 #include "NCUtility.h"
00002
00003 #include "TH1.h"
00004 #include "TH2.h"
00005 #include "TH3.h"
00006
00007 #include "TStopwatch.h"
00008
00009 #include "MessageService/MsgService.h"
00010
00011 #include <cassert>
00012
00013 #include "sys/stat.h"
00014
00015 CVSID("$Id: NCUtility.cxx,v 1.7 2010/01/20 15:41:32 rodriges Exp $");
00016
00017 TH1* NC::Utility::CloneFast(const TH1* h)
00018 {
00019 const TString className = h->ClassName();
00020
00021 if(className == "TH1F") return new TH1F(*((TH1F*)h));
00022 if(className == "TH1D") return new TH1D(*((TH1D*)h));
00023 if(className == "TH2F") return new TH2F(*((TH2F*)h));
00024 if(className == "TH2D") return new TH2D(*((TH2D*)h));
00025 if(className == "TH3F") return new TH3F(*((TH3F*)h));
00026 if(className == "TH3D") return new TH3D(*((TH3D*)h));
00027
00028 MSG("NCUtility", Msg::kWarning) << "Histogram type "
00029 << className
00030 << " is not handled."
00031 << " Falling back to Clone()"
00032 << " which is slow." << endl;
00033 return (TH1*)h->Clone();
00034 }
00035
00036
00038 inline void GetArray(const TH1* h, float*& fArray, double*& dArray)
00039 {
00040 fArray = 0; dArray = 0;
00041
00042 const TString className = h->ClassName();
00043
00044 if(className == "TH1F") fArray = ((TH1F*)h)->fArray;
00045 if(className == "TH2F") fArray = ((TH2F*)h)->fArray;
00046 if(className == "TH3F") fArray = ((TH3F*)h)->fArray;
00047 if(className == "TH1D") dArray = ((TH1D*)h)->fArray;
00048 if(className == "TH2D") dArray = ((TH2D*)h)->fArray;
00049 if(className == "TH3D") dArray = ((TH3D*)h)->fArray;
00050 }
00051
00052
00053 int NC::Utility::GetArraySize(const TH1* h)
00054 {
00055
00056
00057 struct CellsGetter: public TH1
00058 {
00059 int NCells()
00060 {
00061 return fNcells;
00062 }
00063 };
00064
00065 return ((CellsGetter*)h)->NCells();
00066 }
00067
00068
00069 void NC::Utility::AddFast(TH1* a, const TH1* b, double c)
00070 {
00071 if(c == 0) return;
00072
00073 assert(a->ClassName() == b->ClassName());
00074
00075 const int N = GetArraySize(a);
00076 assert(GetArraySize(b) == N);
00077
00078 float* fArrayA = 0;
00079 float* fArrayB = 0;
00080 double* dArrayA = 0;
00081 double* dArrayB = 0;
00082
00083 GetArray(a, fArrayA, dArrayA);
00084 GetArray(b, fArrayB, dArrayB);
00085
00086 if(!(fArrayA && fArrayB) && !(dArrayA && dArrayB)){
00087 MSG("NCUtility", Msg::kWarning) << "Histogram type "
00088 << a->ClassName()
00089 << " is not handled."
00090 << " Falling back to Add()"
00091 << " which is slow." << endl;
00092 a->Add(b, c);
00093 return;
00094 }
00095
00096 if(fArrayA && fArrayB) for(int n = 0; n < N; ++n) fArrayA[n] += fArrayB[n]*c;
00097 if(dArrayA && dArrayB) for(int n = 0; n < N; ++n) dArrayA[n] += dArrayB[n]*c;
00098 }
00099
00100
00101 void NC::Utility::MultiplyFast(TH1* a, const TH1* b, double c)
00102 {
00103 assert(a->ClassName() == b->ClassName());
00104
00105 const int N = GetArraySize(a);
00106 assert(GetArraySize(b) == N);
00107
00108 float* fArrayA = 0;
00109 float* fArrayB = 0;
00110 double* dArrayA = 0;
00111 double* dArrayB = 0;
00112
00113 GetArray(a, fArrayA, dArrayA);
00114 GetArray(b, fArrayB, dArrayB);
00115
00116 if(!(fArrayA && fArrayB) && !(dArrayA && dArrayB)){
00117 MSG("NCUtility", Msg::kWarning) << "Histogram type "
00118 << a->ClassName()
00119 << " is not handled."
00120 << " Falling back to Multiply()"
00121 << " which is slow." << endl;
00122 a->Multiply(b);
00123 a->Scale(c);
00124 return;
00125 }
00126
00127 if(fArrayA && fArrayB) for(int n = 0; n < N; ++n) fArrayA[n] *= fArrayB[n]*c;
00128 if(dArrayA && dArrayB) for(int n = 0; n < N; ++n) dArrayA[n] *= dArrayB[n]*c;
00129 }
00130
00131
00132 void NC::Utility::DivideFast(TH1* a, const TH1* b, double c)
00133 {
00134 assert(a->ClassName() == b->ClassName());
00135
00136 const int N = GetArraySize(a);
00137 assert(GetArraySize(b) == N);
00138
00139 float* fArrayA = 0;
00140 float* fArrayB = 0;
00141 double* dArrayA = 0;
00142 double* dArrayB = 0;
00143
00144 GetArray(a, fArrayA, dArrayA);
00145 GetArray(b, fArrayB, dArrayB);
00146
00147 if(!(fArrayA && fArrayB) && !(dArrayA && dArrayB)){
00148 MSG("NCUtility", Msg::kWarning) << "Histogram type "
00149 << a->ClassName()
00150 << " is not handled."
00151 << " Falling back to Divide()"
00152 << " which is slow." << endl;
00153 a->Divide(b);
00154 a->Scale(1/c);
00155 return;
00156 }
00157
00158 if(fArrayA && fArrayB){
00159 for(int n = 0; n < N; ++n){
00160 const double denom = fArrayB[n]*c;
00161 if(denom) fArrayA[n] /= denom; else fArrayA[n] = 0;
00162 }
00163 }
00164
00165 if(dArrayA && dArrayB){
00166 for(int n = 0; n < N; ++n){
00167 const double denom = dArrayB[n]*c;
00168 if(denom) dArrayA[n] /= denom; else dArrayA[n] = 0;
00169 }
00170 }
00171 }
00172
00173
00174 vector<TString> NC::Utility::ParseStringList(const char* sl)
00175 {
00176 TString strList = sl;
00177
00178 vector<TString> ret;
00179
00180 strList.Remove(TString::kBoth, ' ');
00181
00182 if(strList == "") return ret;
00183
00184 int space = strList.First(' ');
00185
00186
00187 if(space < 0) space = strList.Length();
00188
00189
00190 const TString head = strList(0, space);
00191 const TString tail = strList(space+1, strList.Length()-space);
00192
00193 ret.push_back(head);
00194
00195
00196 const vector<TString> rest = ParseStringList(tail);
00197 ret.insert(ret.end(), rest.begin(), rest.end());
00198
00199 return ret;
00200 }
00201
00202
00203 vector<int> NC::Utility::ParseNumberList(const char* nl)
00204 {
00205 const vector<TString> sl = ParseStringList(nl);
00206
00207 vector<int> ret;
00208
00209 for(unsigned int n = 0; n < sl.size(); ++n){
00210 assert(sl[n].IsDigit());
00211 ret.push_back(sl[n].Atoi());
00212 }
00213
00214 return ret;
00215 }
00216
00217
00218 void NC::Utility::ReportProgress(double est_frac, TStopwatch& sw)
00219 {
00220
00221
00222 struct stat buf;
00223 fstat(fileno(stdout), &buf);
00224 const bool isFile = (buf.st_mode & S_IFREG) || (buf.st_mode & S_IFIFO);
00225
00226 const double elapsed = sw.RealTime();
00227 sw.Start(kFALSE);
00228
00229 if(est_frac < 0) est_frac = 0;
00230 if(est_frac > 1) est_frac = 1;
00231
00232 const int remain = est_frac ? int(elapsed*(1/est_frac-1)) : 0;
00233
00234 const TString txt = TString::
00235 Format("%d%% complete, approx %dh%dm%ds remain",
00236 int(100*est_frac), remain/3600, (remain/60)%60, remain%60);
00237
00238 if(isFile){
00239 MSG("NCUtility", Msg::kInfo) << txt << std::endl;
00240 }
00241 else{
00242 TString bar;
00243 const int extra = 50-txt.Length();
00244 const int before = extra/2;
00245 const int after = extra-before;
00246
00247 string plain_bar;
00248 for(int n = 0; n < before; ++n) plain_bar += " ";
00249 plain_bar += txt;
00250 for(int n = 0; n < after; ++n) plain_bar += " ";
00251
00252 const char kColor_Reset[] = { 0x1B, '[', '0', 'm', 0 };
00253 const char kColor_BgRed[] = { 0x1B, '[', '4', '1', 'm', 0 };
00254 const char kColor_BgGreen[] = { 0x1B, '[', '4', '2', 'm', 0 };
00255
00256 int fracInt = int(est_frac*50);
00257 if(fracInt < 0) fracInt = 0;
00258 if(fracInt > 50) fracInt = 50;
00259 bar += kColor_BgGreen;
00260 for(int n = 0; n < 50; ++n){
00261 if(n >= fracInt) bar += kColor_BgRed;
00262 bar += plain_bar[n];
00263 }
00264 bar += kColor_Reset;
00265
00266 MSG("NCUtility", Msg::kInfo) << bar << "\r" << std::flush;
00267 }
00268 }