File indexing completed on 2025-01-18 10:17:40
0001
0002
0003
0004
0005
0006
0007
0008 #include <unistd.h>
0009 #include <set>
0010 using namespace std;
0011
0012 #include "JEventProcessor_janaview.h"
0013 #include <JANA/JEventSource.h>
0014
0015 #include <TLatex.h>
0016 #include <TArrow.h>
0017 #include <TBox.h>
0018
0019 jv_mainframe *JVMF = NULL;
0020 JEventProcessor_janaview *JEP=NULL;
0021
0022
0023
0024 #include <JANA/JApplication.h>
0025 #include <JANA/JFactory.h>
0026
0027 extern "C"{
0028 void InitPlugin(JApplication *app){
0029 InitJANAPlugin(app);
0030 app->Add(new JEventProcessor_janaview());
0031
0032
0033
0034 app->SetParameterValue("RECORD_CALL_STACK", 1);
0035
0036 }
0037 }
0038
0039
0040
0041
0042
0043
0044
0045 bool FactoryNameSort(JFactory *a,JFactory *b){
0046 if (a->GetObjectName()==b->GetObjectName()) return string(a->GetTag()) < string(b->GetTag());
0047 return a->GetObjectName() < b->GetObjectName();
0048 }
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 void* JanaViewRootGUIThread(void *)
0059 {
0060
0061
0062
0063 int narg = 0;
0064 TApplication app("JANA Viewer", &narg, NULL);
0065 app.SetReturnFromRun(true);
0066 JVMF = new jv_mainframe(gClient->GetRoot(), 600, 600, true);
0067
0068 try{
0069 app.Run();
0070 }catch(std::exception &e){
0071 _DBG_ << "Exception: " << e.what() << endl;
0072 }
0073
0074 return NULL;
0075 }
0076
0077
0078
0079
0080
0081
0082
0083 JEventProcessor_janaview::JEventProcessor_janaview()
0084 {
0085 eventnumber = 0;
0086
0087 pthread_mutex_init(&mutex, NULL);
0088 pthread_cond_init(&cond, NULL);
0089
0090 pthread_t root_thread;
0091 pthread_create(&root_thread, NULL, JanaViewRootGUIThread, this);
0092
0093 while(!JVMF) usleep(100000);
0094
0095 JEP = this;
0096 }
0097
0098
0099
0100
0101 JEventProcessor_janaview::~JEventProcessor_janaview()
0102 {
0103
0104 }
0105
0106
0107
0108
0109 void JEventProcessor_janaview::Init()
0110 {
0111 }
0112
0113
0114
0115
0116 void JEventProcessor_janaview::BeginRun(const std::shared_ptr<const JEvent>& event)
0117 {
0118 this->loop = event;
0119 loop->GetJCallGraphRecorder()->SetEnabled(true);
0120 }
0121
0122
0123
0124
0125 void JEventProcessor_janaview::Process(const std::shared_ptr<const JEvent>& event)
0126 {
0127
0128
0129 auto app = event->GetJApplication();
0130 app->SetTicker(false);
0131
0132
0133 pthread_mutex_lock(&mutex);
0134
0135
0136
0137 this->loop = event;
0138 this->eventnumber = event->GetEventNumber();
0139
0140 JEventSource *source = event->GetJEventSource();
0141 JVMF->UpdateInfo(source->GetResourceName(), event->GetRunNumber(), event->GetEventNumber());
0142
0143 vector<JVFactoryInfo> facinfo;
0144 GetObjectTypes(facinfo);
0145 JVMF->UpdateObjectTypeList(facinfo);
0146
0147 MakeCallGraph();
0148
0149 pthread_cond_wait(&cond, &mutex);
0150
0151
0152
0153 pthread_mutex_unlock(&mutex);
0154 }
0155
0156
0157
0158
0159 void JEventProcessor_janaview::NextEvent(void)
0160 {
0161
0162 pthread_cond_signal(&cond);
0163 }
0164
0165
0166
0167
0168 void JEventProcessor_janaview::EndRun()
0169 {
0170
0171
0172
0173 }
0174
0175
0176
0177
0178 void JEventProcessor_janaview::Finish(void)
0179 {
0180
0181 }
0182
0183
0184
0185
0186 string JEventProcessor_janaview::MakeNametag(const string &name, const string &tag)
0187 {
0188 string nametag = name;
0189 if(tag.size()>0)nametag += ":"+tag;
0190
0191 return nametag;
0192 }
0193
0194
0195
0196
0197 void JEventProcessor_janaview::GetObjectTypes(vector<JVFactoryInfo> &facinfo)
0198 {
0199 if(!loop) return;
0200
0201
0202 vector<JFactory*> factories = loop->GetAllFactories();
0203 sort(factories.begin(), factories.end(), FactoryNameSort);
0204
0205
0206 for(uint32_t i=0; i<factories.size(); i++){
0207 JVFactoryInfo finfo;
0208 finfo.name = factories[i]->GetObjectName();
0209 finfo.tag = factories[i]->GetTag();
0210 finfo.nametag = MakeNametag(finfo.name, finfo.tag);
0211 facinfo.push_back(finfo);
0212 }
0213 }
0214
0215
0216
0217
0218 void JEventProcessor_janaview::GetAssociatedTo(JObject *jobj, vector<const JObject*> &associatedTo)
0219 {
0220 if(!loop) return;
0221
0222 vector<JFactory*> factories = loop->GetAllFactories();
0223 for(uint32_t i=0; i<factories.size(); i++){
0224
0225
0226 if(factories[i]->GetCreationStatus() == JFactory::CreationStatus::NotCreatedYet) continue;
0227
0228
0229 vector<JObject*> vobjs = factories[i]->GetAs<JObject>();
0230 for(uint32_t i=0; i<vobjs.size(); i++){
0231 JObject *obj = vobjs[i];
0232
0233 vector<const JObject*> associated;
0234 obj->GetT(associated);
0235
0236 for(uint32_t j=0; j<associated.size(); j++){
0237 if(associated[j] == jobj) associatedTo.push_back(obj);
0238 }
0239 }
0240 }
0241 }
0242
0243
0244
0245
0246 void JEventProcessor_janaview::MakeCallGraph(string nametag)
0247 {
0248 if(nametag=="") nametag = JVMF->GetSelectedObjectType();
0249
0250
0251 TCanvas *c = JVMF->canvas->GetCanvas();
0252 c->cd();
0253 c->Clear();
0254 c->Update();
0255
0256
0257 for(auto it : cgobjs) if(it.second) delete it.second;
0258 cgobjs.clear();
0259
0260
0261 auto stack = loop->GetJCallGraphRecorder()->GetCallGraph();
0262 if(stack.empty()) return;
0263 for(auto &cs : stack){
0264 string caller = MakeNametag(cs.caller_name, cs.caller_tag);
0265 string callee = MakeNametag(cs.callee_name, cs.callee_tag);
0266
0267 if(caller == "<ignore>") continue;
0268
0269 CGobj *caller_obj = cgobjs[caller];
0270 CGobj *callee_obj = cgobjs[callee];
0271 if( caller_obj==NULL ) caller_obj = cgobjs[caller] = new CGobj(caller);
0272 if( callee_obj==NULL ) callee_obj = cgobjs[callee] = new CGobj(callee);
0273
0274 caller_obj->callees.insert(callee_obj);
0275 }
0276
0277
0278
0279 do{
0280 bool nothing_changed = true;
0281
0282
0283 for(auto p : cgobjs){
0284 CGobj *caller_obj = p.second;
0285 for(auto callee_obj : caller_obj->callees){
0286 if(caller_obj == callee_obj) break;
0287 if( callee_obj->rank >= caller_obj->rank){
0288 caller_obj->rank = callee_obj->rank + 1;
0289 nothing_changed = false;
0290 }
0291 }
0292 }
0293
0294 if(nothing_changed) break;
0295 }while(true);
0296
0297
0298 map<Int_t, CGrankprop > rankprops;
0299 map<string, CGobj*>::iterator iter;
0300 for(auto p : cgobjs){
0301 CGobj *cgobj = p.second;
0302 CGrankprop &rankprop = rankprops[cgobj->rank];
0303
0304 rankprop.cgobjs.push_back(cgobj);
0305 rankprop.totheight += cgobj->h;
0306 if((int32_t)cgobj->w > rankprop.totwidth) rankprop.totwidth = cgobj->w;
0307 }
0308
0309
0310 Int_t totwidth = 0;
0311 Int_t totheight = 0;
0312 Int_t Nx = rankprops.size();
0313 Int_t Ny = 0;
0314 map<Int_t, CGrankprop >::iterator itrp;
0315 for(itrp=rankprops.begin(); itrp!=rankprops.end(); itrp++){
0316
0317 CGrankprop &rprop = itrp->second;
0318 totwidth += rprop.totwidth;
0319 Int_t height = rprop.totheight;
0320 if(totheight < height){
0321 totheight = height;
0322 Ny = rprop.cgobjs.size();
0323 }
0324 }
0325 Int_t xspace = 50;
0326 Int_t yspace = 10;
0327 Int_t minwidth = totwidth + (Nx+1)*xspace;
0328 Int_t minheight = totheight + (Ny+1)*yspace;
0329
0330
0331
0332
0333
0334
0335 Int_t cwidth = JVMF->fTab->GetWidth();
0336 Int_t cheight = JVMF->fTab->GetHeight();
0337 if( cwidth < minwidth ) cwidth = minwidth;
0338 if( cheight < minheight ) cheight = minheight;
0339
0340
0341
0342 xspace = (cwidth - totwidth)/(Nx+1);
0343 Int_t xpos = xspace/2;
0344 for(itrp=rankprops.begin(); itrp!=rankprops.end(); itrp++){
0345
0346 CGrankprop &rprop = itrp->second;
0347 yspace = (cheight - rprop.totheight)/(rprop.cgobjs.size()+1);
0348 Int_t ypos = yspace;
0349 for(uint32_t i=0; i<rprop.cgobjs.size(); i++){
0350 CGobj *cgobj = rprop.cgobjs[i];
0351
0352 Int_t pad = 4;
0353 cgobj->x1 = xpos - pad;
0354 cgobj->x2 = xpos + cgobj->w + pad;
0355 cgobj->y1 = ypos - pad;
0356 cgobj->y2 = ypos + cgobj->h + pad;
0357 cgobj->ymid = (cgobj->y2 + cgobj->y1)/2;
0358
0359 ypos += cgobj->h + yspace;
0360 }
0361
0362 xpos += rprop.totwidth + xspace;
0363 }
0364
0365
0366
0367
0368 for(auto it=rankprops.rbegin(); it!=rankprops.rend(); it++){
0369 CGrankprop &rprop = it->second;
0370 for(auto cgobj : rprop.cgobjs){
0371 for(auto callee_obj : cgobj->callees){
0372 callee_obj->ancestors.insert(cgobj);
0373 callee_obj->ancestors.insert(cgobj->ancestors.begin(), cgobj->ancestors.end());
0374 }
0375 }
0376 }
0377 for(auto it : rankprops){
0378 CGrankprop &rprop = it.second;
0379 for(auto cgobj : rprop.cgobjs){
0380 cgobj->decendants.insert(cgobj->callees.begin(), cgobj->callees.end());
0381 for(auto callee_obj : cgobj->callees){
0382 cgobj->decendants.insert(callee_obj->decendants.begin(), callee_obj->decendants.end());
0383 }
0384 }
0385 }
0386
0387
0388 JVMF->canvas->SetWidth( cwidth );
0389 JVMF->canvas->SetHeight( cheight );
0390 c->SetCanvasSize( cwidth, cheight );
0391 c->SetMargin(0.0, 0.0, 0.0, 0.0);
0392 c->Clear();
0393 c->Update();
0394
0395
0396 for(iter=cgobjs.begin(); iter != cgobjs.end(); iter++){
0397 CGobj *cgobj1 = iter->second;
0398 double x1 = cgobj1->x1/(double)cwidth;
0399 double y1 = cgobj1->ymid/(double)cheight;
0400 for(auto cgobj2 : cgobj1->callees){
0401 double x2 = cgobj2->x2/(double)cwidth;
0402 double y2 = cgobj2->ymid/(double)cheight;
0403
0404 bool is_ancestor = cgobj1->ancestors.count(cgobjs[nametag]) || cgobj1->nametag==nametag;
0405 bool is_descendant = cgobj2->decendants.count(cgobjs[nametag]) || cgobj2->nametag==nametag;
0406
0407 TLine *lin = new TLine(x1,y1,x2,y2);
0408 if(is_ancestor){
0409 lin->SetLineColor(kGreen+2);
0410 lin->SetLineWidth(4.0);
0411 }else if(is_descendant){
0412 lin->SetLineColor(kBlue);
0413 lin->SetLineWidth(4.0);
0414 }else{
0415 lin->SetLineColor(kBlack);
0416 lin->SetLineWidth(1.0);
0417 }
0418 lin->Draw();
0419 }
0420 }
0421
0422
0423 TLatex latex;
0424 latex.SetTextSizePixels(20);
0425 latex.SetTextAlign(22);
0426 TBox *border = new TBox();
0427 for(iter=cgobjs.begin(); iter != cgobjs.end(); iter++){
0428 CGobj *cgobj = iter->second;
0429 if(!cgobj) continue;
0430 double x1 = cgobj->x1/(double)cwidth;
0431 double x2 = cgobj->x2/(double)cwidth;
0432 double y1 = cgobj->y1/(double)cheight;
0433 double y2 = cgobj->y2/(double)cheight;
0434 double padx = 4.0/(double)cwidth;
0435 double pady = 4.0/(double)cheight;
0436
0437 TBox *box = new TBox(x1, y1, x2, y2);
0438 latex.SetTextColor(kWhite);
0439 if(cgobj->nametag == nametag){
0440 latex.SetTextColor(kBlack);
0441 box->SetFillColor(TColor::GetColor( (Float_t)1.0, 0.3, 1.0));
0442 border->SetFillColor(kGreen+1);
0443 border->DrawBox(x1-padx, y1-pady, (x1+x2)/2.0, y2+pady);
0444 border->SetFillColor(kBlue);
0445 border->DrawBox((x1+x2)/2.0, y1-pady, x2+padx, y2+pady);
0446 }else if(cgobj->ancestors.count(cgobjs[nametag])){
0447 box->SetFillColor(kGreen+3);
0448 border->SetFillColor(kGreen);
0449 border->DrawBox(x1-padx, y1-pady, x2+padx, y2+pady);
0450 }else if(cgobj->decendants.count(cgobjs[nametag])){
0451 box->SetFillColor(kBlue);
0452 border->SetFillColor(kCyan);
0453 border->DrawBox(x1-padx, y1-pady, x2+padx, y2+pady);
0454 }else{
0455 box->SetFillColor(TColor::GetColor( (Float_t)0.4, 0.4, 0.4));
0456 }
0457 box->Draw();
0458 latex.DrawLatex((x1+x2)/2.0, (y1+y2)/2.0, cgobj->nametag.c_str());
0459 }
0460
0461 TBox *box = new TBox(0.0, 0.0, 1.0, 1.0);
0462 box->SetFillStyle(0);
0463 box->SetLineWidth(4);
0464 box->SetLineColor(kRed);
0465 box->Draw();
0466
0467 c->Update();
0468
0469
0470
0471
0472 JVMF->Redraw(JVMF->gcanvas);
0473 }
0474