ROOT logo
/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/
 // Author: Mihai Niculescu 2013
 
 
 /*
 * This script creates a collage containing all OpenGL views from a running AliEve
 *
 * Given Collage size (width, height), the size for all OpenGL 
 * views are computed using the same aspect ratio (width/height) as the main 3D View
 */

#include <TASImage.h>
#include <TGLViewer.h>
#include <TEveViewer.h>
#include <TEveManager.h>
#include <TMath.h>
#include <TSystem.h>
#include <TTimeStamp.h>

#include <STEER/ESD/AliESDEvent.h>
#include <STEER/ESD/AliESDRun.h>
#include <STEER/STEER/AliGRPObject.h>
#include <STEER/CDB/AliCDBEntry.h>
#include <STEER/CDB/AliCDBManager.h>
#include <RAW/AliRawReader.h>
#include <RAW/AliRawEventHeaderBase.h>
#include <EVE/EveBase/AliEveEventManager.h>

TString getEventInfo();

/***********Save all OpenGL views into one picture
	compositeImgFileName - save final image to this file	
  showLiveBar - whether to show the LIVE bar, useful when not online (using offline)
	width - of the collage image
	height -of the collage image
*/
void saveViews(const char* compositeImgFileName="views.png", Bool_t showLiveBar=kTRUE, Int_t width = 1440, Int_t height= 900)
{
	Info("saveViews.C", "saving views to [%s]", compositeImgFileName);

	Int_t heightInfoBar = 65; // hold height of the Information bar
	
	TASImage* compositeImg=0; // this holds the final image
	TASImage* tempImg=0; // temporary used for loading images
	
	TEveViewerList* viewers = gEve->GetViewers();
	Int_t Nviewers = viewers->NumChildren()-2; // remark: 3D view is counted twice
		
	compositeImg = new TASImage(width, height);
		
	// 3D View size	
	Int_t width3DView = TMath::FloorNint((float)Nviewers*width/(float)(Nviewers+1)); // the width of the 3D view
	Int_t height3DView= height-heightInfoBar; // the height of the 3D view
	Float_t aspectRatio = (float)width3DView/(float)height3DView; // 3D View aspect ratio
		
	// Children View Size
	Int_t heightChildView = TMath::FloorNint((float)height3DView/(float)Nviewers);
	Int_t widthChildView  = TMath::FloorNint(aspectRatio*heightChildView); // has the same aspect ratio as the 3D view
	
	int index=0; // iteration counter
	int x = width3DView; // x position of the child view
	int y = 0;// y position of the child view
	TString viewFilename; // save view to this file
	for(TEveElement::List_i i = (++viewers->BeginChildren()); i != viewers->EndChildren(); i++){ // NB: this skips the first children (first 3D View)
		TEveViewer* view = ((TEveViewer*)*i);
		viewFilename = Form("view-%d.png", index);

    // Save OpenGL views in files
    if(index==0){
			view->GetGLViewer()->SavePictureUsingFBO(viewFilename, width3DView, height3DView);
		}
		else {
			view->GetGLViewer()->SavePictureUsingFBO(viewFilename, widthChildView, heightChildView);
		}
		
		tempImg = new TASImage(viewFilename);
		
		// copy view image in the composite image
		if(index==0){
			tempImg->CopyArea(compositeImg, 0,0, width3DView, height3DView);
		}
		else {
			tempImg->CopyArea(compositeImg, 0,0, widthChildView, heightChildView, x,y);
		    
    // draw a border around child views
    compositeImg->DrawRectangle(x,y, widthChildView, heightChildView, "#C0C0C0");
    }
    
    /*
     final touches inside loop
    */
    delete tempImg;
    if(index>0) // skip 3D View
    	y+=heightChildView;
    	
    index++;
   }
   
	// Create a glow (bloom) effect
	tempImg = (TASImage*)compositeImg->Clone("tempImg");
	tempImg->Blur(10.0,10.0);
	compositeImg->Merge(tempImg, "lighten");
	delete tempImg; tempImg = 0;

 
 // show LIVE bar
 if(showLiveBar){
	TTimeStamp ts;
	TString tNow = ts.AsString("s"); // display date & time
 
	compositeImg->Gradient( 90, "#EAEAEA #D2D2D2 #FFFFFF", 0, 75, 0, 239, 95);
	compositeImg->Gradient( 90, "#D6D6D6 #242424 #000000", 0, 155, 60, 152, 26);
	compositeImg->BeginPaint();
	compositeImg->DrawRectangle(50,0, 264, 94);
	compositeImg->DrawText(162, 6, "LIVE", 70, "#FF2D00", "FreeSansBold.otf");
	compositeImg->DrawText(162, 65, tNow, 16, "#FFFFFF", "arial.ttf");
	compositeImg->EndPaint();
	//include ALICE Logo
	tempImg = new TASImage( Form("%s/picts/2012-Jul-04-4_Color_Logo_small_CB.png", gSystem->Getenv("ALICE_ROOT")) );
	tempImg->Scale(64,86);
	//tempImg->CopyArea(compositeImg, 0,0, 236, 319, 59, 4);
	compositeImg->Merge(tempImg, "alphablend", 82, 4);
	delete tempImg; tempImg = 0;
	}
	
	// show Information bar
	TString stringInfo;
	stringInfo = getEventInfo();
	compositeImg->Gradient( 90, "#1B58BF #1D5CDF #0194FF", 0, 0, height-heightInfoBar, width, heightInfoBar);
	compositeImg->BeginPaint();
	compositeImg->DrawText(10, height-heightInfoBar+15, stringInfo, 28, "#FFFFFF", "FreeSansBold.otf");
	compositeImg->EndPaint();
		
	
	// write composite image to disk
	compositeImg->CopyArea(compositeImg, 0,0, width, height);
	compositeImg->WriteImage(compositeImgFileName);
	
	delete compositeImg;
	
	return;
}

// This function retrieves a string containing some information regarding the current event
TString getEventInfo()
{
	// For general public please show as less or technical information as possible

	TString rawInfo, esdInfo;

  if (!AliEveEventManager::HasRawReader())
  {
    rawInfo = "";
  }
  else
  {
  	AliRawReader* rawReader = AliEveEventManager::AssertRawReader();
		if(!rawReader) return "";
		rawInfo.Form("Run: %d  Event#: %d (%s)",
		rawReader->GetRunNumber(),
		AliEveEventManager::CurrentEventId(),
		AliRawEventHeaderBase::GetTypeName(rawReader->GetType())
		);
		
	 return rawInfo;
  }

  if (!AliEveEventManager::HasESD())
  {
    esdInfo = "";
  }
  else
  {
		AliESDEvent* esd =  AliEveEventManager::AssertESD();

		esdInfo.Form("Colliding: %s Run: %d  Event: %d (%s)",
		esd->GetESDRun()->GetBeamType(),
		esd->GetRunNumber(),
		AliEveEventManager::CurrentEventId(),
			     "PHYSICS_EVENT"
			     /*AliRawEventHeaderBase::GetTypeName(esd->GetEventType())*/
		);
  }

  return esdInfo;
}
 saveViews.C:1
 saveViews.C:2
 saveViews.C:3
 saveViews.C:4
 saveViews.C:5
 saveViews.C:6
 saveViews.C:7
 saveViews.C:8
 saveViews.C:9
 saveViews.C:10
 saveViews.C:11
 saveViews.C:12
 saveViews.C:13
 saveViews.C:14
 saveViews.C:15
 saveViews.C:16
 saveViews.C:17
 saveViews.C:18
 saveViews.C:19
 saveViews.C:20
 saveViews.C:21
 saveViews.C:22
 saveViews.C:23
 saveViews.C:24
 saveViews.C:25
 saveViews.C:26
 saveViews.C:27
 saveViews.C:28
 saveViews.C:29
 saveViews.C:30
 saveViews.C:31
 saveViews.C:32
 saveViews.C:33
 saveViews.C:34
 saveViews.C:35
 saveViews.C:36
 saveViews.C:37
 saveViews.C:38
 saveViews.C:39
 saveViews.C:40
 saveViews.C:41
 saveViews.C:42
 saveViews.C:43
 saveViews.C:44
 saveViews.C:45
 saveViews.C:46
 saveViews.C:47
 saveViews.C:48
 saveViews.C:49
 saveViews.C:50
 saveViews.C:51
 saveViews.C:52
 saveViews.C:53
 saveViews.C:54
 saveViews.C:55
 saveViews.C:56
 saveViews.C:57
 saveViews.C:58
 saveViews.C:59
 saveViews.C:60
 saveViews.C:61
 saveViews.C:62
 saveViews.C:63
 saveViews.C:64
 saveViews.C:65
 saveViews.C:66
 saveViews.C:67
 saveViews.C:68
 saveViews.C:69
 saveViews.C:70
 saveViews.C:71
 saveViews.C:72
 saveViews.C:73
 saveViews.C:74
 saveViews.C:75
 saveViews.C:76
 saveViews.C:77
 saveViews.C:78
 saveViews.C:79
 saveViews.C:80
 saveViews.C:81
 saveViews.C:82
 saveViews.C:83
 saveViews.C:84
 saveViews.C:85
 saveViews.C:86
 saveViews.C:87
 saveViews.C:88
 saveViews.C:89
 saveViews.C:90
 saveViews.C:91
 saveViews.C:92
 saveViews.C:93
 saveViews.C:94
 saveViews.C:95
 saveViews.C:96
 saveViews.C:97
 saveViews.C:98
 saveViews.C:99
 saveViews.C:100
 saveViews.C:101
 saveViews.C:102
 saveViews.C:103
 saveViews.C:104
 saveViews.C:105
 saveViews.C:106
 saveViews.C:107
 saveViews.C:108
 saveViews.C:109
 saveViews.C:110
 saveViews.C:111
 saveViews.C:112
 saveViews.C:113
 saveViews.C:114
 saveViews.C:115
 saveViews.C:116
 saveViews.C:117
 saveViews.C:118
 saveViews.C:119
 saveViews.C:120
 saveViews.C:121
 saveViews.C:122
 saveViews.C:123
 saveViews.C:124
 saveViews.C:125
 saveViews.C:126
 saveViews.C:127
 saveViews.C:128
 saveViews.C:129
 saveViews.C:130
 saveViews.C:131
 saveViews.C:132
 saveViews.C:133
 saveViews.C:134
 saveViews.C:135
 saveViews.C:136
 saveViews.C:137
 saveViews.C:138
 saveViews.C:139
 saveViews.C:140
 saveViews.C:141
 saveViews.C:142
 saveViews.C:143
 saveViews.C:144
 saveViews.C:145
 saveViews.C:146
 saveViews.C:147
 saveViews.C:148
 saveViews.C:149
 saveViews.C:150
 saveViews.C:151
 saveViews.C:152
 saveViews.C:153
 saveViews.C:154
 saveViews.C:155
 saveViews.C:156
 saveViews.C:157
 saveViews.C:158
 saveViews.C:159
 saveViews.C:160
 saveViews.C:161
 saveViews.C:162
 saveViews.C:163
 saveViews.C:164
 saveViews.C:165
 saveViews.C:166
 saveViews.C:167
 saveViews.C:168
 saveViews.C:169
 saveViews.C:170
 saveViews.C:171
 saveViews.C:172
 saveViews.C:173
 saveViews.C:174
 saveViews.C:175
 saveViews.C:176
 saveViews.C:177
 saveViews.C:178
 saveViews.C:179
 saveViews.C:180
 saveViews.C:181
 saveViews.C:182
 saveViews.C:183
 saveViews.C:184
 saveViews.C:185
 saveViews.C:186
 saveViews.C:187
 saveViews.C:188
 saveViews.C:189
 saveViews.C:190
 saveViews.C:191