Skip to content

Commit a1f1aa5

Browse files
author
miranov25
committed
Adding getStat
1 parent d0411c8 commit a1f1aa5

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

UTILS/Parsers/treeFastCache.C

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,134 @@ void example1D() {
125125
tree0->SetAlias("mDCAr_A_NTracks_median_All" ,("getNearest1D(time, " + std::to_string(mapID) + ")").data());
126126
tree0->Draw("mTSITSTPC.mDCAr_A_NTracks_median:mDCAr_A_NTracks_median_All","indexType==1","",10000);
127127
}
128+
/* ------------------------------------------------------------------
129+
Statistics extension (non‑breaking) -------------------------------
130+
Added without changing previous API.
131+
132+
New options:
133+
• Enum‑based interface for better ROOT compatibility
134+
enum StatKind { kMean=0, kMedian=1, kStd=2 };
135+
float getStat(double x,int mapID,StatKind kind,double dx);
136+
137+
• Convenience thin wrappers for ROOT aliases
138+
getMean1D , getMedian1D , getStd1D
139+
140+
• cacheStat unchanged (uses strings internally)
141+
142+
------------------------------------------------------------------*/
143+
144+
#include <vector>
145+
#include <algorithm>
146+
#include <numeric>
147+
148+
// --- enum for faster numeric calls --------------------------------
149+
enum StatKind { kMean=0, kMedian=1, kStd=2 };
150+
151+
// Cache: stat → mapID → dx → (x → value)
152+
static std::map<int, std::map<double, std::map<double,float>>> cacheMean;
153+
static std::map<int, std::map<double, std::map<double,float>>> cacheMedian;
154+
static std::map<int, std::map<double, std::map<double,float>>> cacheStd;
155+
156+
static float _mean(const std::vector<float>& v){ return v.empty()?NAN:std::accumulate(v.begin(),v.end(),0.0f)/v.size(); }
157+
static float _median(std::vector<float> v){ if(v.empty()) return NAN; size_t n=v.size()/2; std::nth_element(v.begin(),v.begin()+n,v.end()); return v[n]; }
158+
static float _std(const std::vector<float>& v){ if(v.size()<2) return NAN; float m=_mean(v); double s2=0; for(float e:v){ double d=e-m; s2+=d*d;} return std::sqrt(s2/(v.size()-1)); }
159+
160+
//--------------------------------------------------------------------
161+
static float _computeStat(double x,int mapID,double dx,StatKind k){
162+
const auto itM=registeredMaps.find(mapID);
163+
if(itM==registeredMaps.end()||itM->second.empty()) return NAN;
164+
const auto &mp=itM->second;
165+
std::vector<float> buf;
166+
for(auto it=mp.lower_bound(x-dx); it!=mp.end()&&it->first<=x+dx; ++it) buf.push_back(it->second);
167+
if(buf.empty()) return NAN;
168+
switch(k){
169+
case kMean: return _mean(buf);
170+
case kMedian: return _median(buf);
171+
case kStd: return _std(buf);
172+
}
173+
return NAN;
174+
}
175+
176+
//--------------------------------------------------------------------
177+
/**
178+
* @brief Return a local statistic (mean / median / std) around a query point.
179+
*
180+
* This version is preferred inside **TTree::Draw** because it uses an enum
181+
* instead of a string literal.
182+
*
183+
* @param x Center of the window (same coordinate used in the cache)
184+
* @param mapID ID returned by registerMap1D / registerMap1DByName
185+
* @param kind kMean (0), kMedian (1) or kStd (2)
186+
* @param dx Half‑window size: the statistic is computed from all points
187+
* with X in [x − dx, x + dx]
188+
*
189+
* Internally the first request builds (and caches) a map x → stat(x)
190+
* for the given (mapID, dx, kind). Subsequent calls are O(log N).
191+
*/
192+
// Fast numeric interface (enum) ------------------------------------
193+
float getStat(double x,int mapID,StatKind kind,double dx){
194+
auto *pcache = (kind==kMean? &cacheMean : (kind==kMedian? &cacheMedian : &cacheStd));
195+
auto &byMap = (*pcache)[mapID];
196+
auto &byDx = byMap[dx];
197+
if(byDx.empty()){
198+
// build lazily for this dx
199+
const auto itM=registeredMaps.find(mapID);
200+
if(itM==registeredMaps.end()) return NAN;
201+
for(const auto &kv: itM->second){ double cx=kv.first; byDx[cx]=_computeStat(cx,mapID,dx,kind);} }
202+
const auto &statMap = byDx;
203+
auto it=statMap.lower_bound(x);
204+
if(it==statMap.begin()) return it->second;
205+
if(it==statMap.end()) return std::prev(it)->second;
206+
auto prev=std::prev(it);
207+
return (fabs(prev->first-x)<fabs(it->first-x)?prev->second:it->second);
208+
}
209+
210+
// String interface kept for backward compat.
211+
float getStat(double x,int mapID,const char* st,double dx){
212+
std::string s(st);
213+
if(s=="mean") return getStat(x,mapID,kMean ,dx);
214+
if(s=="median") return getStat(x,mapID,kMedian,dx);
215+
if(s=="std"||s=="sigma") return getStat(x,mapID,kStd,dx);
216+
std::cerr<<"[getStat] Unknown statType="<<s<<std::endl; return NAN;
217+
}
218+
219+
//--------------------------------------------------------------------
220+
// Convenience wrappers for ROOT Draw / numeric helpers -----------------
221+
inline float getMean1D (double x,int id,double dx){ return getStat(x,id,kMean ,dx);} // mean
222+
inline float getMedian1D(double x,int id,double dx){ return getStat(x,id,kMedian,dx);} // median
223+
inline float getStd1D (double x,int id,double dx){ return getStat(x,id,kStd ,dx);} // stddev
224+
225+
// Integer overload for ROOT (fix #2) --------------------------------
226+
inline float getStat(double x,int id,int kind,double dx){
227+
return getStat(x,id,static_cast<StatKind>(kind),dx);
228+
}
229+
230+
//--------------------------------------------------------------------
231+
// Pre‑cache requested stats (by enum) ------------------------------- (by enum) -------------------------------
232+
bool cacheStat(int mapID,const std::vector<std::string>& stats,double dx){
233+
for(const std::string &s:stats){
234+
if(s=="mean") getStat(0,mapID,kMean ,dx); // lazy build
235+
else if(s=="median") getStat(0,mapID,kMedian,dx);
236+
else if(s=="std"||s=="sigma") getStat(0,mapID,kStd,dx);
237+
}
238+
return true;
239+
}
240+
241+
//--------------------------------------------------------------------
242+
/// Example: statistics with enum wrappers
243+
void exampleStat1D(){
244+
TFile *f=TFile::Open("timeSeries10000_apass5.root");
245+
TTree *t=(TTree*)f->Get("timeSeries");
246+
int id = registerMap1DByName("dcar_time_stat","time","mTSITSTPC.mDCAr_A_NTracks_median",t,"subentry==127");
247+
248+
// Pre‑cache mean & std for ±200 window
249+
cacheStat(id,{"mean","std"},200);
250+
251+
// Use integer selector (0 = mean, 2 = std). This avoids any ROOT
252+
// overload ambiguity and works in TTree::Draw directly.
253+
t->SetAlias("dcar_mean", Form("getStat(time,%d,0,200)", id)); // 0 → kMean
254+
t->SetAlias("dcar_sigma", Form("getStat(time,%d,2,200)", id)); // 2 → kStd
255+
256+
t->Draw("mTSITSTPC.mDCAr_A_NTracks_median:dcar_mean","indexType==1","colz",10000);
257+
t->Draw("getStat(time,591487517, 0 ,10000+0):getStat(time,591487517, 1 ,10000+0)","indexType==1","colz",100000);
258+
}

0 commit comments

Comments
 (0)