FEDRA emulsion software from the OPERA Collaboration
mc2raw.cxx File Reference
#include <TROOT.h>
#include <TObjArray.h>
#include <TFile.h>
#include <TTree.h>
#include <TEnv.h>
#include <TF1.h>
#include <TRandom3.h>
#include <EdbVertex.h>
#include <EdbDataStore.h>
#include <EdbPattern.h>
#include <EdbLog.h>
Include dependency graph for mc2raw.cxx:

Functions

void GenerateBG (EdbDataStore *DS, bool correl=false)
 
void Help ()
 
void InitBGHist (TEnv &cenv)
 
TF1 * InitEfficiency (TEnv &cenv)
 
EdbScanCondInitSmearing (TEnv &cenv)
 
int main (int argc, char **argv)
 
void read_args (int argc, char **argv)
 
int readNum (char *st)
 
void set_default (TEnv &cenv)
 if true - generate BG basetracks (i.e. corellated microtracks). Ottherwise - ucorellated. More...
 
void WriteLog (const char *logfnm, TF1 *efff, EdbScanCond *smr, EdbDataStore *DS)
 

Variables

TH2F * bg_Ang =0
 
bool bg_BaseTrk =false
 
const char * bg_fnm =0
 
char * bg_hnm1 ="bg_TXTY"
 
char * bg_hnm2 ="bg_WT"
 
TH2F * bg_Puls =0
 
long dNEV =0
 
const char * envfname ="mceff.rootrc"
 
const char * fname =0
 
EdbID idset
 
long NBG =0
 
long NEV0 =0
 ==================================================================== More...
 
long NEV1 =0
 
bool noaff =false
 
const char * opt ="RECREATE"
 

Function Documentation

◆ GenerateBG()

void GenerateBG ( EdbDataStore DS,
bool  correl = false 
)
300 {
301 long Ntot=0;
302 for(int Npl=0; Npl< DS->Nplt(); ++Npl){
303 if(bg_BaseTrk) Ntot+=DS->Gen_mtk_BG(NBG,Npl,0,bg_Ang,bg_Puls);
304 else{
305 Ntot+=DS->Gen_mtk_BG(NBG,Npl,1,bg_Ang,bg_Puls);
306 Ntot+=DS->Gen_mtk_BG(NBG,Npl,2,bg_Ang,bg_Puls);
307 }
308 }
309 printf("Generated total of %ld bg segments\n",Ntot);
310}
int Nplt()
Definition: EdbDataStore.h:39
long Gen_mtk_BG(long NBG, int Plate, int Side, TH2 *pdf_Ang, TH2 *pdf_WT=0)
Definition: EdbDataStore.cxx:420
TH2F * bg_Ang
Definition: mc2raw.cxx:49
TH2F * bg_Puls
Definition: mc2raw.cxx:49
bool bg_BaseTrk
Definition: mc2raw.cxx:50
long NBG
Definition: mc2raw.cxx:39

◆ Help()

void Help ( )

==================================================================

mc2raw: convert data to raw.root format read data from EdbDataStore file (root file with array of vertices)


20 {
21 printf(" -------------------------------------------------\n");
22 printf(" usage:\n\t mc2raw [options] -set=ID input.root\n");
23 printf(" Convert simulation data from file [input.root] to FEDRA brick structure b0[BrickID].\n");
24 printf(" Options: \n") ;
25 printf(" \t-h \t - display this help message");
26 printf(" \t-n0=NEV_START\t - starting event number. Default=0\n");
27 printf(" \t-n=NEV_TODO \t - number of events to process. Default=0\n");
28 printf(" \t-v=VLEVEL \t - set Fedra verbosity level. Default=0\n");
29 printf(" \t-a \t - Add to existing brick. I.e. set file access mode to \'APPEND\'. Default=\'RECREATE\'\n");
30 printf(" \t-env=ENV_FILE\t - set ENV file to read. Default=\'mceff.rootrc\'\n");
31 printf(" \t-noaff \t - Do not modify AFF files\n");
32 printf(" Note: you can use modifiers like \'k\' and \'m\', they will be substituted with \'000\' and \'000000\' correspondingly\n");
33 printf("---------------------------------------------------\n");
34 printf(" Usage example:\n mc2raw -a -n0=2m -n=200k -set=90001.0.10.100 /data/sim5m.root\n");
35 printf(" will read file \"/data/sim5m.root\", take events [2000000,2200000] and and APPEND them to brick directory \"b090001\"\n");
36 printf("---------------------------------------------------\n");
37}

◆ InitBGHist()

void InitBGHist ( TEnv &  cenv)

normalize histograms for simulation angular histogram is used for generation of TX:TY, so we need just to make its maximum=1

194 {
195 bg_fnm=cenv.GetValue("addbg.FileName",(const char*)0);
196 if(bg_fnm==0 || NBG==0)return;
197 const char* line=cenv.GetValue("addbg.HistName","bg_TXTY bg_WT");
198 printf("line=%s\n",line);
199 char* h1=new char[10];
200 char* h2=new char[10];
201 sscanf(line,"%s %s",h1,h2);
203 printf("hstnms=%s %s\n",bg_hnm1,bg_hnm2);
204 TFile f(bg_fnm,"READ");
205 TH2F *h1p, *h2p;
206 f.GetObject(bg_hnm1,h1p);
207 f.GetObject(bg_hnm2,h2p);
208 bg_BaseTrk=cenv.GetValue("addbg.BaseTrk",0);
209 gROOT->cd();
210 bg_Ang =(TH2F*)gROOT->CloneObject(h1p);
211 bg_Puls=(TH2F*)gROOT->CloneObject(h2p);
212 f.Close();
213
216 float maxval=0,val;
217 maxval=bg_Ang->GetBinContent(bg_Ang->GetMaximumBin());
218 //printf("max_val Ang=%2.4f\n",maxval);
219 bg_Ang->Scale(1./maxval);
220
221 for(int nbx=0; nbx< bg_Puls->GetNbinsX();++nbx){
222 maxval=0;
223 for(int nby=0; nby< bg_Puls->GetNbinsY();++nby){
224 val=bg_Puls->GetBinContent(nbx,nby);
225 if(val>maxval)maxval=val;
226 }
227 //printf("Xbin#%d(%2.4f) maxval = %2.5f\n",nbx,bg_Puls->GetXaxis()->GetBinCenter(nbx),maxval);
228 if(maxval==0)continue;
229 for(int nby=0; nby< bg_Puls->GetNbinsY();++nby){
230 val=bg_Puls->GetBinContent(nbx,nby);
231 bg_Puls->SetBinContent(nbx,nby,val/maxval);
232 }
233 }
234 }
FILE * f
Definition: RecDispMC.C:150
TEnv cenv("emrec")
TH1F * h2
Definition: energy.C:19
TH1F * h1
Definition: energy.C:16
char * bg_hnm2
Definition: mc2raw.cxx:48
char * bg_hnm1
Definition: mc2raw.cxx:47
const char * bg_fnm
Definition: mc2raw.cxx:46

◆ InitEfficiency()

TF1 * InitEfficiency ( TEnv &  cenv)

--------—plot probability----------—

137 {
138 cenv.Print();
139 int ApplyEff=cenv.GetValue("mceff.ApplyEff",1);
140 if(!ApplyEff)return 0;
141 const char* EffAlg=cenv.GetValue("mceff.EffAlg","pol0");
142 const char* EffPar=cenv.GetValue("mceff.EffPar","1.00");
143 float tanmax=cenv.GetValue("mceff.TanMax",1.0);
144 printf("--- initializing efficiency algorithm \'%s\'\n ---",EffAlg);
145
146 TF1* eff=new TF1("mc_eff",Form("%s(0)",EffAlg),0,tanmax);
147 eff->SetTitle("Microtrack efficiency; tan#theta; survival probability");
148 int n=0;
149 const char* nxt=EffPar;
150 float par=0;
151 do{
152 //printf("next line(%d)=\'%s\'\n",n,nxt);
153 par=atof(nxt);
154 nxt=strchr(nxt+1,' ');
155 eff->SetParameter(n,par);
156 printf("Par#%d = %2.4f\n",n,par);
157 n++;
158 }while(nxt);
159 printf(" -------------done--------------\n");
161 TCanvas c;
162 eff->Draw("l");
163 eff->SetMaximum(1.);
164 eff->SetMinimum(0.);
165 c.SetGrid();
166 c.Print("eff.png");
167 return eff;
168}
new TCanvas()

◆ InitSmearing()

EdbScanCond * InitSmearing ( TEnv &  cenv)
171 {
172 int ApplySmear=cenv.GetValue("mceff.ApplySmearing",1);
173 if(ApplySmear==0)return 0;
175 float s0[4];
176 float p0[2], p04[2];
177 float degrad;
178 const char* line=cenv.GetValue("fedra.smear.Sigma0","1 1 0.13 0.13");
179 sscanf(line,"%f %f %f %f",s0,s0+1,s0+2,s0+3);
180 line=cenv.GetValue("fedra.smear.PulsRamp0","6 6");
181 sscanf(line,"%f %f",p0,p0+1);
182 line=cenv.GetValue("fedra.smear.PulsRamp04","6 6");
183 sscanf(line,"%f %f",p04,p04+1);
184 degrad=cenv.GetValue("fedra.smear.Degrad",5.0);
185
186 smear->SetSigma0(s0[0],s0[1],s0[2],s0[3]);
187 smear->SetPulsRamp0 (p0[0], p0[1]);
188 smear->SetPulsRamp04(p04[0],p04[1]);
189 smear->SetDegrad(degrad);
190 smear->Print();
191 return smear;
192}
bool smear
Definition: RecDispNU.C:14
Definition: EdbScanCond.h:10

◆ main()

int main ( int  argc,
char **  argv 
)

Init random

Init arguments and environment

Set efficiency function

Set smearing conditions

==== generate background! ====

==== read segments from tree! ====

finished prepare

313 {
315 if(gRandom==0)gRandom=new TRandom3(0);
316 gRandom->SetSeed(0);
317 printf("Random seed=%d\n",gRandom->GetSeed());
319 read_args(argc,argv);
320 TEnv cenv("mceff_env");
322 cenv.ReadFile(envfname,kEnvAll);
324 TF1* mtk_eff=InitEfficiency(cenv);
326 EdbScanCond* mtk_smear=InitSmearing(cenv);
328
329 TFile* F=new TFile(fname,"READ");
330
331 // setup EdbDataStore object
332 EdbDataStore DS;
333 DS.eBrick=(EdbBrickP*)F->Get("Brick");
335 if(NBG>0){
337 GenerateBG(&DS);
338 }
339 if(NEV1>NEV0){
341 TTree* tree=(TTree*)F->Get("FluSim");
342 TObjArray* vtx=new TObjArray();
343 printf("tree has %lld entries\n",tree->GetEntries());
344 tree->GetBranch("Vtx")->SetAddress(&vtx);
345 cenv.WriteFile("mceff.save.rootrc");
347 if(NEV1>tree->GetEntries())NEV1=tree->GetEntries();
348 for(int nEv=NEV0; nEv<NEV1; ++nEv){
349 tree->GetEntry(nEv);
350 DS.LoadMCVertices(vtx);
352 DS.Restore_SegFromTrx(0,0,100);
353 if(nEv%10000==0){
354 printf("Evt#%d of %lld\n",nEv,tree->GetEntries());
355 }
356 DS.ClearTracks();
357 DS.ClearVTX();
358 DS.ClearSeg();
359 }
360 }
361 if(mtk_eff)DS.DoEfficiency(0,mtk_eff);
362 if(mtk_smear)DS.DoSmearing(0,mtk_smear);
363 DS.SaveToRaw("./",idset,opt,!noaff);
364 cenv.WriteFile(Form("./b%06d/mceff.save.rootrc",idset.eBrick));
365 WriteLog(Form("./b%06d/b%s.mc.log",idset.eBrick,idset.AsString()),mtk_eff,mtk_smear, &DS);
366 return 0;
367}
Definition: EdbBrick.h:38
Definition: EdbDataStore.h:15
void ClearSeg(bool hard=false)
Definition: EdbDataStore.cxx:293
void SaveToRaw(const char *dir="./", const EdbID &idset="0.0.0.0", Option_t *option="RECREATE", bool doaff=true)
save methods:
Definition: EdbDataStore.cxx:828
void Restore_TrxFromVtx()
Definition: EdbDataStore.cxx:157
void Restore_SegFromTrx(EdbSegmentCut *cut=0, int Plt0=0, int Plt1=1000)
Definition: EdbDataStore.cxx:171
void LoadMCVertices(TObjArray *vtx)
restore MC info methods
Definition: EdbDataStore.cxx:18
EdbBrickP * eBrick
Definition: EdbDataStore.h:81
void DoSmearing(EdbScanCond *cond_btk, EdbScanCond *cond_mtk=0)
methods for simulation:
Definition: EdbDataStore.cxx:372
void Restore_PatFromGeom(int np0=0, int np1=1000)
Definition: EdbDataStore.cxx:144
void DoEfficiency(TF1 *eff_seg, TF1 *eff_mtk)
Definition: EdbDataStore.cxx:386
void ClearVTX()
Definition: EdbDataStore.cxx:285
void ClearTracks(bool hard=false)
Definition: EdbDataStore.cxx:289
char * AsString() const
Definition: EdbID.cxx:26
Int_t eBrick
Definition: EdbID.h:10
void set_default(TEnv &cenv)
if true - generate BG basetracks (i.e. corellated microtracks). Ottherwise - ucorellated.
Definition: mc2raw.cxx:54
TF1 * InitEfficiency(TEnv &cenv)
Definition: mc2raw.cxx:137
EdbScanCond * InitSmearing(TEnv &cenv)
Definition: mc2raw.cxx:171
long NEV0
====================================================================
Definition: mc2raw.cxx:39
const char * opt
Definition: mc2raw.cxx:42
const char * fname
Definition: mc2raw.cxx:41
const char * envfname
Definition: mc2raw.cxx:43
EdbID idset
Definition: mc2raw.cxx:40
void read_args(int argc, char **argv)
Definition: mc2raw.cxx:87
long NEV1
Definition: mc2raw.cxx:39
void GenerateBG(EdbDataStore *DS, bool correl=false)
Definition: mc2raw.cxx:300
bool noaff
Definition: mc2raw.cxx:44
void InitBGHist(TEnv &cenv)
Definition: mc2raw.cxx:194
void WriteLog(const char *logfnm, TF1 *efff, EdbScanCond *smr, EdbDataStore *DS)
Definition: mc2raw.cxx:236

◆ read_args()

void read_args ( int  argc,
char **  argv 
)
87 {
89 if(argc<3){Help(); exit(0);}
90 for(int n=1;n<argc-1;++n){
91 if(strncmp(argv[n],"-h",2)==0){
92 Help(); exit(0);
93 }
94 if(strncmp(argv[n],"-n0=",4)==0){
95 NEV0=readNum(argv[n]+4);
96 continue;
97 }
98 if(strncmp(argv[n],"-n=",3)==0){
99 dNEV=readNum(argv[n]+3);
100 continue;
101 }
102 if(strncmp(argv[n],"-nB=",4)==0){
103 NBG=readNum(argv[n]+4);
104 continue;
105 }
106 if(strncmp(argv[n],"-env=",5)==0){
107 envfname=argv[n]+5;
108 continue;
109 }
110 if(strncmp(argv[n],"-a",2)==0){
111 opt="UPDATE";
112 continue;
113 }
114 if(strncmp(argv[n],"-noaff",6)==0){
115 noaff=true;
116 continue;
117 }
118 if(strncmp(argv[n],"-v=",3)==0){
119 gEDBDEBUGLEVEL=atoi(argv[n]+3);
120 continue;
121 }
122 if(strncmp(argv[n],"-set=",5)==0){
123 printf("SET: \"%s\"\n",argv[n]+5);
124 idset.Set(argv[n]+5);
125 continue;
126 }
127 }
128 NEV1=NEV0+dNEV;
129 // BRICK_ID=atoi(argv[argc-2]);
130 fname=argv[argc-1];
131
132 printf("Fname=\"%s\"\n BrickID=%s\n,Taking events in range [%ld, %ld].\n",fname,idset.AsString(),NEV0,NEV1);
133}
bool Set(const char *id_string)
Definition: EdbID.cxx:19
gEDBDEBUGLEVEL
Definition: energy.C:7
int readNum(char *st)
Definition: mc2raw.cxx:70
void Help()
Definition: mc2raw.cxx:20
long dNEV
Definition: mc2raw.cxx:39

◆ readNum()

int readNum ( char *  st)

read number with letters: k=10^3; m=10^6

70 {
72 TString res="";
73 int len=strlen(st);
74 for(int n=0;n<len;++n){
75 if(st[n]>='0' && st[n]<='0'+9){res+=st[n]; continue;}
76 switch(st[n]){
77 case 'k':
78 case 'K': res+="000"; break;
79 case 'm':
80 case 'M': res+="000000"; break;
81 }
82 }
83 printf("%s ---> %s\n",st,res.Data());
84 return atoi(res.Data());
85}

◆ set_default()

void set_default ( TEnv &  cenv)

if true - generate BG basetracks (i.e. corellated microtracks). Ottherwise - ucorellated.

54 {
55 cenv.SetValue("addbg.FileName", "BG_mtk_Strom.root");
56 cenv.SetValue("addbg.HistName", "bg_TXTY bg_WT");
57 cenv.SetValue("addbg.BaseTrk", 0);
58 cenv.SetValue("mceff.ApplyEff", 0);
59 cenv.SetValue("mceff.EffAlg","pol0");
60 cenv.SetValue("mceff.EffPar","0.98 0.98 0.98 0.98");
61 cenv.SetValue("mceff.TanMax",1.0);
62 cenv.SetValue("mceff.ApplySmearing", 0);
63 cenv.SetValue("fedra.smear.Sigma0", "1 1 0.013 0.013");
64 cenv.SetValue("fedra.smear.PulsRamp0","6 6");
65 cenv.SetValue("fedra.smear.PulsRamp04","6 6");
66 cenv.SetValue("fedra.smear.Degrad", 5);
67}

◆ WriteLog()

void WriteLog ( const char *  logfnm,
TF1 *  efff,
EdbScanCond smr,
EdbDataStore DS 
)
236 {
237 FILE* f=fopen(logfnm,(strcmp(opt,"UPDATE"))?"w":"a");
238 time_t rawtime;
239 struct tm * timeinfo;
240 time ( &rawtime );
241 timeinfo = localtime ( &rawtime );
242 fprintf(f,"======= mc2raw run at ======\n %s\n",asctime(timeinfo));
243 fprintf(f,"%s to b%s\n",opt,idset.AsString());
244 if(NEV1>NEV0)
245 fprintf(f," * READ INPUT : Read %ld events [%ld-%ld] from file \'%s\'\n",NEV1-NEV0,NEV0,NEV1,fname);
246 if(NBG && bg_Ang && bg_Puls){
247 fprintf(f," * GENERATE BG: %ld mtk/layer (%2.4f mtk/mm2). PDFs \'%s %s\' from file \'%s\'\n",NBG,NBG/(12.0e3),bg_hnm1,bg_hnm2,bg_fnm);
248 fprintf(f,"Background: uncorellated %s\n",bg_BaseTrk?"BASE tracks":"Microtracks");
249 fprintf(f," Angular distribution: %2.0f entries. [TX=%6.3f (RMS=%6.3f), TY=%6.3f (RMS=%6.3f)\n",
250 bg_Ang->GetEntries(),bg_Ang->GetMean(1),bg_Ang->GetRMS(1),bg_Ang->GetMean(2),bg_Ang->GetRMS(2));
251 fprintf(f," Pulse distribution: %2.0f entries. [Angle=%6.3f (RMS=%6.3f), Puls=%6.3f (RMS=%6.3f)\n",
252 bg_Puls->GetEntries(),bg_Puls->GetMean(1),bg_Puls->GetRMS(1),bg_Puls->GetMean(2),bg_Puls->GetRMS(2));
253 }
254 if(efff){
255 fprintf(f," * * Efficiency (%2.4f<Tan(theta)<%2.4f):\n", efff->GetXmin(),efff->GetXmax());
256 const int N_pt=11;
257 double x0=efff->GetXmin();
258 double dx=(efff->GetXmax()-efff->GetXmin())/(N_pt-1);
259 fprintf(f,"----------------");
260 for(int n=0;n<N_pt;++n)fprintf(f,"---------");
261 fprintf(f,"\n");
262 fprintf(f,"Tan(theta):\t|");
263 for(int n=0;n<N_pt;++n)fprintf(f," % 7.2f|",x0+n*dx);
264 fprintf(f,"\n");
265 fprintf(f,"Efficinency(%%):\t|");
266 for(int n=0;n<N_pt;++n) fprintf(f," % 7.2f|",efff->Eval(x0+n*dx)*100.);
267 fprintf(f,"\n");
268 fprintf(f,"----------------");
269 for(int n=0;n<N_pt;++n)fprintf(f,"---------");
270 fprintf(f,"\n");
271 }else fprintf(f," * * No inefficiency was applied\n");
272 if(smr){
273 fprintf(f," * * Smearing applied on microtrack level:\n");
274 fprintf(f," Sigma0[TX,TY] = %7.4f %7.4f\t",smr->SigmaTX(0),smr->SigmaTY(0));
275 fprintf(f," Sigma1[TX,TY] = %7.4f %7.4f\n",smr->SigmaTX(1),smr->SigmaTY(1));
276 fprintf(f," Sigma0[X,Y] = %7.4f %7.4f\t",smr->SigmaX(0),smr->SigmaY(0));
277 fprintf(f," Sigma1[X,Y] = %7.4f %7.4f\n",smr->SigmaX(1),smr->SigmaY(1));
278 }else fprintf(f," * * No smearing was applied\n");
279 fprintf(f," -------------Result (full eff)--------------------\n");
280 for(int np=0; np< DS->eRawPV.Npatterns(); ++np){
281 EdbPattern* pat=DS->GetRawPat(np);
282 fprintf(f," - Plate#%d side%d: %d microtracks\n",pat->Plate(),pat->Side(),pat->N());
283 }
284 fprintf(f," =======================================\n");
285 fclose(f);
286/* TCanvas c("c_bg","c_bg",800,400);
287 c.Divide(2,1);
288 c.cd(1); bg_Ang->Draw("colz");
289 c.cd(2); bg_Puls->Draw("colz");
290 printf("BG - uncorellated %s\n",bg_BaseTrk?"BASE tracks":"Microtracks");
291 printf("%ld mtk/layer (%2.4f mtk/mm2). PDFs \'%s %s\' from file \'%s\'\n",NBG,NBG/(12.0e3),bg_hnm1,bg_hnm2,bg_fnm);
292 c.Print("bg1.png");
293 printf(" Angular distribution: %2.0f entries. [TX=%6.3f (RMS=%6.3f), TY=%6.3f (RMS=%6.3f)\n",
294 bg_Ang->GetEntries(),bg_Ang->GetMean(1),bg_Ang->GetRMS(1),bg_Ang->GetMean(2),bg_Ang->GetRMS(2));
295 printf(" Pulse distribution: %2.0f entries. [Angle=%6.3f (RMS=%6.3f), Puls=%6.3f (RMS=%6.3f)\n",
296 bg_Puls->GetEntries(),bg_Puls->GetMean(1),bg_Puls->GetRMS(1),bg_Puls->GetMean(2),bg_Puls->GetRMS(2));*/
297}
EdbPattern * GetRawPat(int n)
Definition: EdbDataStore.h:48
EdbPatternsVolume eRawPV
geometry
Definition: EdbDataStore.h:82
Definition: EdbPattern.h:273
Int_t Side() const
Definition: EdbPattern.h:328
Int_t Plate() const
Definition: EdbPattern.h:327
Int_t Npatterns() const
Definition: EdbPattern.h:366
float SigmaTX(float ax) const
Definition: EdbScanCond.h:106
float SigmaTY(float ay) const
Definition: EdbScanCond.h:107
float SigmaX(float ax) const
Definition: EdbScanCond.h:102
float SigmaY(float ay) const
Definition: EdbScanCond.h:103
Int_t N() const
Definition: EdbPattern.h:86
fclose(pFile)

Variable Documentation

◆ bg_Ang

TH2F* bg_Ang =0

◆ bg_BaseTrk

bool bg_BaseTrk =false

◆ bg_fnm

const char* bg_fnm =0

◆ bg_hnm1

char* bg_hnm1 ="bg_TXTY"

◆ bg_hnm2

char* bg_hnm2 ="bg_WT"

◆ bg_Puls

TH2F * bg_Puls =0

◆ dNEV

long dNEV =0

◆ envfname

const char* envfname ="mceff.rootrc"

◆ fname

const char* fname =0

◆ idset

EdbID idset

◆ NBG

long NBG =0

◆ NEV0

long NEV0 =0

====================================================================

◆ NEV1

long NEV1 =0

◆ noaff

bool noaff =false

◆ opt

const char* opt ="RECREATE"