The inner chamber of the shell

An old fart guide to CMS software



Index

Before starting

Before starting this journey in the brave new world of CMS offline software, let's start with a pictorial presentation of CMS.

RTFM

My purpose is very simple: I would like to learn in 10 minutes how to do an histogram of a physical quantity. To do this I don't want to follow postgraduate courses on oo things. So ,first of all, of course, let's RTFM.So I'll start from the CMSDOC server. After a little search I found a Software entry.

Here I got my first batch of acronyms : SCB,SCTB,SWAD,SWCR,CRISTAL,etc. In addition to the acronyms I got tons of documents but none very promising.

Ok I got a line CMS Software and Computing Reviews:perhaps from here I can learn where I have to look.I'll check it later.

There is also a CMS Object-oriented page and a neat list of projects. So I learn that in CMS the reconstruction program is named ORCA, and the Montecarlo is OSCAR.
IGUANA(Interactive Graphical User Analysis) looks promising, but what is SCRAM(Software Configuration Release and Management)?
The other stuff (CRISTAL,FAMOS,TRIDAS,etc..) seems not to be relevant for my purpose.

In the ORCA main page I find an item about training with many tutorials: this looks promising. And also an orca users mailing list .

Well, after an hour I haven't still solved my problem but I have found a lot of material.Perhaps I will need more than 10 minutes!

ooSlang

A quick examination of available documentation unfortunately reveals that it is full of ooWords. You have first to translate to normal words. So I have to start with a kind of dictionary where I try to explain this new slang. Here it starts:wear your hat!

Explore your Federation!

Hey, now we don't read anymore those lousy event files, now we are managers of a oo distributed database. But before we start doing our histogram, it is better to explore our federation. In fact we are only allowed to explore a user federation i.e. a copy of the production federation that is used only for the analysis. To explore your federation, you don't need any more those lousy Fortran programs that you wrote yourself that gave you the content of an event file, now you have a full fledged ootoolmgr that let's you see, with a graphical interface,what databases, containers, and objects you have in the federation. Are you ready for the exploration? First you have to get the bootfile name of the user federation. For example for the Spring 2000 production we have:
cmspf01::/cms/reconstruction/user/jet0900/jet0900.boot
Now log on cms.cern.ch and add the following lines at the end of your .login file
setenv OBJY_VERS 5.2.1
setenv OO_FD_BOOT cmspf01::/cms/reconstruction/user/jet0900/jet0900.boot
if (-r /afs/cern.ch/rd45/objectivity/objyenv.csh) then
source /afs/cern.ch/rd45/objectivity/objyenv.csh
endif
Now you can run ootoolmgr with the command:
ootoolmgr
When the graphic window appears, you just select in "File" the "default..." line, then "Browse FD" in the "Tools" menu'. You should see the following window. In this window you can browse all databases, containers and objects in the federation. You have only to select which one you want and they will show up in the appropriate window. At last, this is the theory.In fact the program is very slooow. Let me guess it: my federation must be very BIG with data coming from many computers.
Before going to even more slang, let's see all the commands available with Objectivity: here you see what you have by giving the command:
oo TAB
. Out of all these commands we use oodumpcatalog to get this nice list of the federation content. 5069 files! But they seem to be almost all on the same computer(in fact this computer will only redirect access requests to the computer that really contains the file:this will create a lot of problems if the file becomes for some reason unreadable).

More slang(sorry!)

Know your objects!

By now it must be clear that you cannot do your plot if you don't know the objects used to store events and collections of events. The ORCA reference manual,produced authomatically from source code by the program doxygen, has a list of all objects defined in ORCA. Pretty cool! Fortunately not all these objects are persistent,i.e. stored in the database.But all objects in the database are described here. A federation contains two kind of "databases" with different objects inside:
  1. Metadata databases - files with meta-data objects i.e. informations about runs and other event collections and selections.
  2. Data databases - files with actual event data.
A list of all persistent objects can be done by looking at the schema with the command:
ooschemadump
. The result is this list of classes (A class is a definition of a kind of objects). The schema itself can be seen here.
It would be nice to have the data model behind these hundreds of classes explained without (much) jargon. The best approximation by now seems to be this: CMS Software Architecture almost unusable by the layperson (Vincenzo Innocente why don't you make a dummies version of this?) . This Cobra vision is an update of the previous document.
Another page that seem to be essential to understand the data model is this one in the CARF Reference Manual. Check especially the Meta-data entry.

Six degrees of complexity : recipe for the impatient user

Here is the
recipe for the impatient user from the ORCA User Guide:
cd /tmp 
mkdir $USER
cd $USER
scram project ORCA ORCA_4_3_0
cd ORCA_4_3_0/src
eval `scram runtime -csh`
cmscvsroot ORCA
cvs login 
(enter 98passwd)
cvs co -r current Workspace
cd Workspace 
touch ExRunEventInfo.cc
scram b shared_debug
scram b bin_debug_local
rehash
source myenv.csh
ExRunEvent > temp.lis &
This is the result of my first trial.
The second trial is more successfull since I can run the program "ExRunEvent" producing this output. So,what went wrong in the first trial? Was the second trial really successful?I am left in the cold. The only sure thing is that I got a ton of new files including a 10Mb executable!
But ,anyway, this example is useful to understand exactly why CMS software is so complex. If you compare CMS experiment with previous experiments you have the following additional layers of complexity between you and the data:
  1. C++ - Do you understand the code in the program copied in the Workspace directory, in the example before? Do you understand the message about the missing libraries?
  2. Objects - Which objects is this application using? How are they implemented in the code? If I want to access other informations, where should I look?
  3. ODBMS/GRID - Which objects are persistent? How do I access the events I am interested? At this level we have also HPSS and its replacement CASTOR
  4. CARF+COBRA to be replaced by EDM - Ok, this should shield me from the previous layer but I have to learn also about this.For example what is the use of the file myenv.csh.The COBRA site.EDM is Event Data Management framework is about to replace COBRA.
  5. CVS - You must know this to access and manage the source code. The manual.
  6. SCRAM - Its importance can be seen from the previous example. So what all these commands do? What is the meaning of the XML commands in the BuildFile? What are the ORCA versions available? Here is the manual. This is instead Scram in one minute.

Know your tools!

From the list in the previous section, it must be evident that now you have at your disposal a really awful set of new tools. Unfortunately it is very difficult to use them, since you don't even know what is their name! And you feel like the apprentice sorcerer that tries to use the spell book of his master. But anyhow, let's try some spells and see what happens. (In giving the commands that follow it is important to realize that "scram" and "cvs" commands result depends on the directory where you type them.)
SpellResult of the spellThings to be carefull about before you cast it
Click on Cern Computer Resourcesto have information on computers, disk space and other resources available in Cern
scram list
List of all public projects and their releases You get also the main directory of the release. By looking at .SCRAM/Linux__2.2/ after this directory, you have a list of all packages needed by the project.
scram project ORCA ORCA_4_3_0
Create your own private project starting from the public release indicated.Requires lot of disk space!
scram tool list
Lists all tools available in SCRAMThe command must be done in the directories of a private project
scram tool info toolname
Lists all information about a given toolditto
source /afs/cern.ch/rd45/objectivity/objyenv.csh
Makes Objectivity software accessible
eval `scram runtime  -csh`
Makes all the libraries known to SCRAM accessible
scram runtime  -csh
Prints the result of the previous command without executing it use -sh if you use sh like shell
cd $ORCA_DATA_DIR
cd ..
ls
List of Orca packages
scram build
The equivalent of make for SCRAM.Executes the Buildfile contained in the directory where you are.Every Buildfile uses other Build files (Command use) which use other Buildfiles,etc The command builds an executable (Command bin) and/or libraries (command lib).
Give the option echo_INCLUDE to know which directories are searched for include.
In a Buildfile put a first line with:
INCLUDE+=path/dir
to add an arbitrary directory to search for Include Files.
scram b shared
Like the previous command, but will build only shared libraries.
scram b bin
Will build only binaries(executables).
scram build clean
To undo the effect of previous scram build in your local Release Area
scram b help
To know what you can build in your local Release Area.
scram b CXXUSERFLAGS=-g
Compile with g flag for debugging
ootoolmgr
Starts a graphical tool to explore your federation Best to define in advance your federation giving the bootfile in the command
setenv OO_FD_BOOT bootfile
oodumpcatalog
List of all files in your federation(the Catalog)
Click hereList of all datasets in the testdata federation
rfdir hpsssrv1:/hpss/cern.ch/cms
rfdir /castor/cern.ch/cms/reconstruction/datafiles
list of cms federations on hpss and castor( castor is replacing gradually hpss) Use:
 rfdir /castor/cern.ch/cms/reconstruction/datafiles/ORCA_7_3_0 | grep EVD0_Digis
to know which datasets are available
oolockmon bootfile
List all current locks to the federation with given bootfile
oocleanup -transaction transid bootfile
Get rid of stale lock transidBe sure that the lock is truly stale by checking if the process with pid given in the lock list is still running
oocleanup -local bootfile
get rid of all locks coming from this machine ditto
oocheckams computer
Checks if AMS is working on computer:AMS allows local federation databases to be accessed from remote computers.
Click hereList of Orca manuals for all versions.
Click hereTo look at the code.
Click hereTo look at the code in the CVS repository.
grep raise /afs/cern.ch/cms/Releases/ORCA/ORCA_6_2_3/src/ Visualisation/*/src/*.ccTo find the lines of the code containing some word.
Click here:Cobra release notes, Minutes, ORCA mailing list, ORCA FAQLatest news on CMS software.
ooschemadump
List of all persistent objects Best to define in advance your federation giving the bootfile in the command
setenv OO_FD_BOOT bootfile
Click hereBootfile and list of datasets for Autumn 2000 production
Click hereBootfiles and list of datasets for Spring 2000 production
Click hereCMS production main page
ls -lR /afs/cern.ch/cms/oo/reconstruction/datafiles
List of sample FZ event files produced by CMSIM
iguana
To run iguana
env LOG=stderr iguana
To run iguana with detailed debug printout
cd /afs/cern.ch/cms/Releases/COBRA/COBRA_7_3_2/src/Visualisation/VisMantis/test
iguana
to run Iguana to visualize DDD detector description as implemented in OscarSelect the Mantis plugin
cmscvsroot projectname
Define CVS repository for the project so you can access the source
cvs --help-commands
List of CVS commands
cvs checkout  Modulename
or
cvs co Modulename
Get a local copy of the module source in your working directory that you can editWill get the head version i.e. the most recent version.This can also be a version not working properly.
cvs co -r version Modulename
To checkout a particular(stable) version of the module
cvs diff
To know the differences between what is in the repository and what you have in your directory
cvs update -r version
To get your local copy in synch with the repositoryThis can be necessary when the head version is no more working and you want to go back to some stable previous version. The version tag should be normally of the form ORCA_4_5_0
cvs add Modulename
To add a new module to the repositoryOnly for developers! Must be followed by a cvs ci command . The file Root in the CVS directory must contain the following line:
:kserver:cmscvs.cern.ch:/cvs_server/repositories/ORCA
cvs ci -m "message"  Modulename
To update a module in the repositoryOnly for developers!
cvs remove Modulename
To remove a module from the repositoryOnly for developers!
cvs tag -b release0
To tag a (stable)version as release0: a new branch is createdOnly for developers!
cvs rtag -b -r release0 release0.1 Modulename 
To connect branch release0.1 to branch release0. This can be useful to deal with bugs corrections to a stable version.Only for developers!
cvs log Modulename
To list the versions of a moduleWithout Modulename will work recursively on the directory
cvs log -N -d ">2002-9-1" | more
To list all revisions done after the specified date
cvs diff -r version Modulename
diff with a previous version of a module
klog.krb gzito -cell cern.ch
cvs -d :kserver:cmscvs.cern.ch:/cvs_server/repositories/IGUANACMS 
commit -m "message"  
to access repository from a node outside Cern

Recovering data from CMS software black hole

What I really need is a document that explains to me where all relevant data is (corresponding to the list of data banks of previous experiments) plus an example program that will show me how I access these data. So here is the relevant code for the impatient user example
void ExRunEventInfo::myAnalysis(G3EventProxy * ev) { 

// Just print the signal event number (see CARF/G3Event/interface/G3EventHeader.h)
cout << "===========================================================" << endl;
cout << "=== Private analysis of event #"<< ev->simTrigger()->id().eventInRun() 
<< " in run #" << ev->simTrigger()->id().runNumber() << endl;
eventsAnalysed++; // some statistics: count events and runs processed

// And now the event numbers of all pileup events
cout << "--- PileUp events are: " ;
G3EventProxy::pu_range PUrange = ev->pileups();
for (G3EventProxy::pu_iterator ipu = PUrange.first; ipu != PUrange.second; ipu++) {
PUeventsUsed++; // count them
if (ipu != PUrange.first) {
cout << ", ";
}
cout << (*ipu).id().eventInRun();
}
cout << endl;

if (ev->simTrigger()->id().runNumber() != lastrun) {
lastrun = (unsigned int) ev->simTrigger()->id().runNumber();
runsAnalysed++;
}

cout << "===========================================================" << endl;
};
At last! So, if ev points to your event, the code to get event number and run number is:
ev->simTrigger()->id().eventInRun()
ev->simTrigger()->id().runNumber()
The dataset used can be found in the myenv.csh file:
setenv OO_FD_BOOT cmsuf01::/cms/reconstruction/user/muonDIGI0300/muonDIGI0300.boot 
setenv CARF_INPUT_OWNER muonSignal0300
setenv CARF_INPUT_DATASET_NAME MB1mu_pt1

IGUANA : the ultimate tool

All these powerful tools and still no histogram! I should have used IGUANA from the beginning. Here I have everything at my disposal with a click of the mouse. I can navigate federations, analyze collections of events, have them displayed in fancy ways without having to know nothing about oothings. At least this is the theory.
And this is the result with an early version (almost unusable) using the usual file in input:
setenv OO_FD_BOOT cmspf01::/cms/reconstruction/user/jet0900/jet0900.boot
setenv CARF_INPUT_OWNER jetNoPU_CERN
setenv CARF_INPUT_DATASET_NAME eg_1gam_pt25
This is an example of SimHits display for the muon tracks in the DT muon detector with the following dataset:
setenv OO_FD_BOOT cmsuf01::/cms/reconstruction/user/muonDIGI0300/muonDIGI0300.boot
setenv CARF_INPUT_OWNER 1034PileupMEInTimeOnly_b
setenv CARF_INPUT_DATASET_NAME tt2mu

This is instead the result using a new better release described in this presentation and in this new tutorial

cd ORCA_5_1_2/src
cmscvsroot ORCA
cvs co Visualisation
cd Visualisation/OrcaVis/test
eval `scram runtime -csh`
scram build bin (you can avoid this since a working program is already available)
rehash   
source testfed.csh
OrcaVisMain &
(Remember that in addition to the buttons and menus, you can click the right mouse button to bring up a menu and experiment with the different draw styles.) This version is a lot better and I can manage to see some nice event pictures: Anyhow Iguana aims to become the Paw of the new ooWorld. A look at its modules shows an intricate mess of new oothings. A lot of new acronyms here:

An Ntuple Example

Perhaps we are near to reach our goal. But before we try, let's summarize what we have understood...
However silly is your application you have to start a new project with SCRAM creating your local Release Area. When you do this, you choose a particular version of ORCA (a stable version or just the latest head version). In the appropriate area of the hierarchy of directories created by SCRAM you checkout (i.e. get a local copy for editing) the appropriate module taken from the official Repository. The module name is usually a two level name like Examples/Tutorial indicating the name of the Orca subsystem and the name of the package. When your code is ready, you give the scram b commands to build libraries and executables. After that you can finally run the executable in the old fashioned way having set up some informations for it as environment variables and in .orcarc.

I did it! I described the edit,compile and run process like a CMS nerd!!!Let's see if I can also get the plot done.

scram project ORCA ORCA_4_3_0
cd ORCA_4_3_0/src
eval `scram runtime -csh`
cmscvsroot ORCA
cvs co -r v430_Tutorial1 Examples/Tutorial
cd Examples/Tutorial
scram build shared
scram build bin
eval `scram runtime -csh dbreading.env`
rehash
ExTutNtuple > temp.lis &
Unfortunately I got only the following error message:
** Error #2111: new() ooDBObj(): Object Manager: The Federated Database is only open for read access
Anyhow, let's look at the various files used: Since now I am getting smart, I note that the error is in the database, so I try again using myenv.csh of the recipe for the impatient user. So instead of
eval `scram runtime -csh dbreading.env`
I do a
source myenv.csc
. Bad luck. I got the following error:
checkRunSelector: warning DB 5585 for EventsToken not closed
checkRunSelector: warning DB 5585 for EventsToken still locked
** Error #906: ooHandle(ooObj)::open(): The object handle is not valid
       - context = #?-?-?-?
Segmentation fault (core dumped)
with the following output listing.
The third trial is more successful. I try again with a new dataset:
setenv OO_FD_BOOT cmspf01::/cms/reconstruction/user/jet0900/jet0900.boot
setenv CARF_INPUT_OWNER jetNoPU_CERN
setenv CARF_INPUT_DATASET_NAME eg_1gam_pt25
getting the following listing. The program actually filled a ntuple with 10 events.You can see here the result of nt/print command and of nt/list command.

You are locked!

In the Ntuple Example appear some strange messages about a DB 5585 not closed and still locked. What is this? As we proceed, we are understanding little by little, how un-transparent are the six layers of complexity indicated before. Here,we are stuck in some subtle mechanism working in the third layer: the Objectivity layer.The mechanism is connected to transactions, i.e. sets of database operations to be done all toghether.In order to avoid that concurrent transactions corrupt the federation, there is a dedicated computer that acts as lockserver. So, when you start a transaction, you can lock the federation concerning the piece of data you are accessing/modifying and thus avoid corruption of data from other transactions that now must wait that you complete your operation. Briefly this avoids problems to the data base, but causes a lot of problems to users. For example, what happens if your program crashes during a transaction? Nothing to the data base, but you are locked! The lock your program had on the federation forbids the access to you and others to the federation. For this reason you have to know how to look at locks created by your programs and how to get rid of them. The lockserver name is defined in the bootfile and you can see it listed at the beginning of the catalog as Lock Host.
It is possible to monitor all accesses done by your program to the federation by looking at what happens on the lockserver. The command:
oolockmon bootfile
will list all current locks to the federation that has the bootfile indicated in the command. For example this was the result of the command:
oolockmon cmspf01::/cms/reconstruction/user/jet0900/jet0900.boot
run during the execution of the Ntuple example on cms008. When the command was issued , the program was accessing 5 files with DBID 65535,1,8250,10478,80251. So, if you give this command from time to time during the execution of a ORCA program, you can follow all the activity connected to database access.
What you do if some lock remains pending but the program originating it is no more active? You have to delete the lock by giving the command:
oocleanup -transaction transid bootfile
The transaction number transid is taken from the previos list. Instead
oocleanup -local bootfile
will clean all locks coming from the computer where you are running.

A simple example analysis

Always more difficult!
scram project ORCA ORCA_4_4_0
cd ORCA_4_4_0/src
eval `scram runtime -csh`
cmscvsroot ORCA
cvs co Examples/ExCalorimetry
cd Examples/ExCalorimetry
scram b shared
scram b bin
rehash
setenv OO_FD_BOOT cmspf01::/cms/reconstruction/user/jet0900/jet0900.boot
setenv CARF_INPUT_OWNER jetNoPU_CERN
setenv CARF_INPUT_DATASET_NAME eg_1gam_pt25 
ExClusterHistograms

Action on demand:what is this?

Integral part of the layer 4 of complexity (CARF/COBRA) is the action on demand mechanism. This is something that is normally present in graphics oriented software:the subroutine is called only if the user does something like pushing a button, selecting a menu',etc The way this is sometime implemented with object oriented languages, is that each one of these things that can happen is an event. Each event has an event dispatcher, a piece of software that takes care of the event. If you want the event dispatcher to start your subroutine, you register your subroutine as an observer for the event with the dispatcher.Also in CARF we have a set of events like starting the processing of a new event, starting a new run, etc...If we want that ORCA starts our piece of code for the event "start of run", we must register our module to the dispatcher of this event. In fact in CMS the minimum piece of code is a module: an object with an appropriate method corresponding to the Fortran subroutine, that will process the data. The dispatcher will activate our object when the event occurs, it will pass to it the appropriate information and so we can process the run. In order the thing to work, all modules must be known to CARF, in such a way that they can be loaded when needed. In practice,as we can see in the simple example analysis you must write a one line class (file ExClusterHistograms.cpp ) to register your analysis code,and a normal class of the appropriate "observer" type to do the analysis. So
PKBuilder<ExClusterInfo> mybuilder("ExClusterInfoBuilder");
registers the class "ExClusterInfo" as observer of some event(i.e. to be called when that event will happen). Which event? This can be seen in the first line of the class "ExClusterInfo".
class ExClusterInfo : private ActiveObserver<G3EventProxy *> {
The event is "G3EventProxy" i.e. start processing of a new Montecarlo event. How can I pass the last event data to my code (in this case the "method" myAnalysis)? When the event occurs, ORCA will call the method "update" (that I must code) passing a pointer to the last event. What I do is pass along the event to my subroutine/method: this can be seen in the code
void upDate(G3EventProxy * ev) { if (ev!=0) myAnalysis(ev);}

Recovering data from CMS software black hole 2: containers and iterators

Hey,we have managed to run THREE sample programs correctly!! It's time to get professional about it, and start entering in the wonderful intricacies of C++ and Carf concerning containers(i.e. collections of objects) and iterators. First let's look at three snippets of code from the three examples:
  1. List of pile_up events
    // And now the event numbers of all pileup events
    cout << "--- PileUp events are: " ;
    G3EventProxy::pu_range PUrange = ev->pileups();
    for (G3EventProxy::pu_iterator ipu = PUrange.first; ipu != PUrange.second; ipu++) {
    PUeventsUsed++; // count them
    if (ipu != PUrange.first) {
    cout << ", ";
    }
    cout << (*ipu).id().eventInRun();
    }
    cout << endl;
    
  2. List of Calorimeter Towers
    RecItr<EcalPlusHcalTower> MyCaloTower(ev->recEvent());
    /* Print Run and Event number and fill them to our Ntuple */
    cout << "Run #" << ev->simTrigger()->id().runNumber() << "; ";
    cout << "Event #" << ev->simTrigger()->id().eventInRun() << endl;
    UserNtuples->FillGeneral(ev->simTrigger()->id().runNumber(),ev->simTrigger()->id().eventInRun());
    
    float Ecalo=0.0; // for the total calorimetric energy
    float Eecaltotal=0.0;
    float Ehcaltotal=0.0;
    HepPoint3D TowerPosition;
    
    /* Loop over all CaloCluster objects */
    while (MyCaloTower.next()) {
    Ecalo += MyCaloTower->Energy();             // sum up the total energy
    Eecaltotal+=MyCaloTower->EnergyEcalTower(); // sum up the Ecal energy
    Ehcaltotal+=MyCaloTower->EnergyHcalTower(); // sum up the Hcal energy
    TowerPosition = MyCaloTower->Position();
    /* Print energy, azimuth and pseudo-rapidity of a cluster and fill this
    * to our Ntuple */
    cout.setf(ios::showpoint);
    cout << "New Tower E(tot/Ecal/Hcal)=" << setw(8) << setprecision(3)
     << MyCaloTower->Energy() << "/"
     << MyCaloTower->EnergyEcalTower() << "/" 
     << MyCaloTower->EnergyHcalTower() << " GeV"
     << "; phi=" << setw(8) << setprecision(4) << TowerPosition.phi() << " rad"
     << "; eta=" << TowerPosition.pseudoRapidity() 
     << endl;
    UserNtuples->AddTower(MyCaloTower->Energy(),TowerPosition.phi(),
                      TowerPosition.pseudoRapidity());
    }
    
  3. List of Clusters
    RecItr<CaloCluster> MyCluster(ev->recEvent(),"EcalFixedWindow_5x5");
    
    
    // Just print the event number (see CARF/G3Event/interface/G3EventHeader.h)
    cout << "===========================================================" << endl;
    cout << "=== Private analysis of event #"<< ev->simTrigger()->id().eventInRun() 
    << " in run #" << ev->simTrigger()->id().runNumber() << endl;
    
    eventsAnalysed++; // some statistics: count events and runs processed
    if (ev->simTrigger()->id().runNumber() != lastrun) {
    lastrun = (unsigned int) ev->simTrigger()->id().runNumber();
    runsAnalysed++;
    }
    
    // Here is the loop over all clusters
    while (MyCluster.next()) {
    nClusters++; // count the clusters
    // Print some of the cluster properties 
    // see Calorimetry/CaloCommon/interface/CaloCluster.h
    cout << "Cluster " << nClusters <<": E=" << MyCluster->Energy()
     << ", eta="<< MyCluster->Eta()
     << ", phi="<< MyCluster->Phi() << endl;
    // Fill them to (our) histograms. Defined in ExClusterHistos.h
    UserHists->FillEepCluster(MyCluster->Energy(), MyCluster->Eta(), 
                          MyCluster->Phi());
    }
    
The three variables ipu, MyCaloTower and MyCluster are iterators. Iterators in oo programming are used whenever we want to examine a list or container of objects. Once you have defined an iterator for the container of objects that interests you (events, tracks, vertices, clusters, etc..) then looping through the objects becomes trivial:
while (iterator.next()){ }
in the last two cases. In the first case(list of pileup events) it is slightly more complex:
 for(iterator=firstitem;iterator!=lastitem;iterator++){ }
In any case the iterator inside the loop points to the current object and we can use it to get all information about the object.
From the code is apparent that ORCA has a general purpose iterator named RecItr that can be used for all kind of
RecObj objects. It is sufficient to write
RecItr<objectname> ip(ev->RecEvent())
and the variable ip will point to the first object of the type indicated for the event indicated.This is a reconstructed object and a Reconstruction on Demand similar to the Action on Demand of the previous section is performed in this case in the following way: if the requested RecObj is not present in the data base ,it is computed on the fly by the "default" module used for the object. In the case 3 you see that it is also possible to select a RecObj computed by a module indicated by us (EcalFixedWindow_5x5). In this way we can test new reconstruction algorithms.
What reconstructed objects are available for our analysis apart from CaloCluster and EcalPlusHcalTower? Easy, you have to look at the documentation for RecObj and there you will find a clickable map of objects connected to it (in jargon derived o inheriting objects). So CaloCluster is son of RecObj. But also these derived objects may have derived classes that are also RecObj,etc.. So EcalPlusHcalTower is son of CaloCluster. As such you have access both to quantities in CaloCluster like Energy and to quantities in EcalPlusHcalTower like EnergyHcalTower.
From the three examples is also apparent that an ActiveObserver class gets a pointer to the current G3EventProxy as an argument. This is the variable ev. Then ev->recEvent() points to the reconstructed event information with all its RecObj, instead ev->simTrigger() can be used to track informations concerning the simulated event like tracks,vertices and MCgenerator information. These are the containers ev->simTrigger()->tracks() vertices() and rawgenparts(). Instead ev->pu_range is a container of pileup_events for the current event.

A complete event, object by object.

You remember when we did an event dump to understand how various information was stored? At last, we know enough that we can try to get the equivalent with a oo data base, i.e. recovering all persistent objects describing a single event. For example, we can take the first event processed in the simple example analysis. This is an event of the dataset eg_1gam_pt25 with owner jetNoPU_CERN of the federation cmspf01::/cms/reconstruction/user/jet0900/jet0900.boot. This is event 1 of Run 37 (as you can see from the output listing). We will use ootoolmgr described previously to track all information about the event in the federation:i.e. all persistent objects describing the event.The list of all ORCA objects in the ORCA manual will be our guide: Looking in the database catalog we find 12 files connected to this dataset these are named
EVD0_Events.eg_1gam_pt25.jetNoPU_CERN
EVD0_Digis.eg_1gam_pt25.jetNoPU_CERN
EVD0_Collections.eg_1gam_pt25.jetNoPU_CERN
The other 9 have the same name but starting with EVD1 EVD2 EVD3.
These files,as you have to guess from Autumn 2000 production information, contain only the Digis objects created by running SimReader or ooDigi. To complete the description of the event we must add the files created by G3Reader or ooHits which have a different owner (jetHit120_2D_CERN) and have the following names:
EVD0_Collections.eg_1gam_pt25.jetHit120_2D_CERN
EVD0_Events.eg_1gam_pt25.jetHit120_2D_CERN
EVD0_Hits.eg_1gam_pt25.jetHit120_2D_CERN
EVD0_MCInfo.eg_1gam_pt25.jetHit120_2D_CERN
EVD0_THits.eg_1gam_pt25.jetHit120_2D_CERN
also these repeated with EVD1,EVD2,EVD3 with a total of other 20 files.
This information is summarized in the production sheet with the following lines:
eg_1gam_pt25   jetHit120_2D_CERN   Collections   0 1 2 3 
eg_1gam_pt25   jetHit120_2D_CERN   Events   0 1 2 3 
eg_1gam_pt25   jetHit120_2D_CERN   Hits   0 1 2 3 
eg_1gam_pt25   jetHit120_2D_CERN   MCInfo   0 1 2 3 
eg_1gam_pt25   jetHit120_2D_CERN   THits   0 1 2 3 

eg_1gam_pt25   jetNoPU_CERN   Collections   0 1 2 3 
eg_1gam_pt25   jetNoPU_CERN   Digis   0 1 2 3 
eg_1gam_pt25   jetNoPU_CERN   Events   0 1 2 3 
So event 1 Run 37 must be tracked in these 32 Objectivity databases! The first group of files contains the objects connected to SimTrigger; the second those pointed from RecEvent.
Here starts the "dump" of event 37 1

Scrambled (Build)files

It is time to understand those intriguing little files. What follow are the Buildfiles used in the Orca User manual examples:
  1. List of Run and event number
    <environment>
    
    <lib name=Workspace><lib>
    
    
    <Group name=RecReader>
    
    
    <External ref=COBRA Use=CARF> 
    
    
    <bin file=ExRunEvent.cpp>my favourite application</bin>
    
    </environment>
    
    
    This is the smallest set that will work. Note that all external libraries are loaded using the BuildFile in COBRA/CARF.This BuildFile uses the tag RecReader to select the classes needed to read RecHits. SimHits are read by the libraries loaded with the tag SimReader.
    The lines starting with lib and bin say to Scram that it should create a shared library libWorkspace.so and an executable ExRunEvent. To find them just give the command
     where ExRunEvent 
    then search in the bin directory given and in the nearby lib directory.
    To find out which libraries has Scram loaded, you must look at the
    output that you get from the command scram build .
  2. List of Run and event number + getting Tracker layout information
    <environment>
    
    <lib name=Workspace><lib>
    
    
      <Use name=Tracker>
    
    
    <Group name=RecReader>
    
    
    <External ref=COBRA Use=CARF> 
    
    
    <bin file=ExRunEvent.cpp>my favourite application</bin>
    
    </environment>
    
    
    We have only added a card saying to Scram that the BuildFile of the subsystem Tracker must be used.
  3. List of towers
    <environment>
    
    
    <lib name=Tutorial>
    
    
    
      <lib name=EcalPlusHcalTower>
      <lib name=CaloCluster>
    
    
      <Group name=CaloRecHitReader>
    
    
    
      <Use name=Calorimetry>
    
    
    
    
      <Group name=RecReader>
    
    
    <External ref=COBRA Use=CARF>
    <External ref=root>
    
    
    
      <bin file=ExTutNtuple.cpp></bin>
    
    
    </environment>
    
    
    The main change here , is that we request the use of the BuilFile in the subsystem Calorimetry.This BuildFile will load many different sets of libraries and the set that we want is selected by the tag CaloRecHitReader. Note that in addition to these libraries, we request explicitily the libraries of subsystem Calorimetry EcalPlusHcalTower and CaloCluster.
    Finally, to create the n-tuple, the external system root is requested.
  4. List of clusters
    
    <External ref=cern>
    <External ref=cmsim>
    <External ref=HepODBMS>
    <External ref=Objectivity>
    
    
    
    <lib name=ExCalorimetry>
    
    
    <environment>
    
      <Group name=CaloHitReader>
      <Group name=CaloRHitWriter>
      <Group name=CaloRHitReader>
    
    
      <lib name=EcalFixedWindow>
      <lib name=CaloData>   
      <lib name=CaloCluster>
    
    
      <Use name=Calorimetry>
    
    
    
      <Group name=RecReader>
    
    
      <Use name=CARF>
    
      <Use name=Utilities>
    
    
    
      <bin file=ExClusterHistograms.cpp></bin>
    
    
      </Use>
      </Use>
      </Use>
    
      </lib>
    </environment>
    
    <environment>
    
      <Group name=CaloHitReader>
      <Group name=CaloRHitWriter>
      <Group name=CaloRHitReader>
    
    
      <lib name=EcalFixedWindow>
      <lib name=EcalDynamical>
      <lib name=CaloData>   
      <lib name=CaloCluster>
    
    
      <Use name=Calorimetry>
    
    
    
      <Group name=RecReader>
    
    
      <Use name=CARF>
    
      <Use name=Utilities>
    
    
    
      <bin file=ExCompClusterers.cpp></bin>
    
    
      </Use>
      </Use>
      </Use>
    
      </lib>
    </environment>
    
    </External>
    </External>
    </External>
    </External>
    
    
So, first of all we must specify in a Build file what we want to build with a tag <bin file=sourcefile></bin> .
To build an executable scram must use
external ref=productname libraries,include files and other stuff connected to the external product
lib name=libname libraries found in the SCRAM search path.
Use name=package the package indicated.In fact this means a reference to the Buildfile of the package.
Group name=groupname The group will set a switch that will control the loading of used packages. What really happens depends on the BuildFile of the package.
The tag environment is used to group other commands.The first and the last commands in a buildfile must be <environment> and </environment>. If these are missing, SCRAM will imply their presence. Any other environment tag is used to separate different "environments" like in the example 3 where we build two executables.
The interplay between the "Use" and the "Group" tag is difficult to understand unless you have a look at the BuildFile of the "used" package, for example CARF . What libraries the package will "export" to you depends on the "Groups" named G3NoMain, G3Reader, SimReader, RecReader. Note the tag "export" used to define the interface to the package.Understanding what are the groups to use for each package should (hopefully) be documented in the ORCA manual .
How you decide wich packages to use? For this you must look in your source and see where the include files come from. Unfortunately this isn't very easy so ,it is better to proceed with another example.

Another illuminating example

scram project ORCA ORCA_4_5_0
cd ORCA_4_5_0/src
eval `scram runtime -csh`
cmscvsroot ORCA
cvs co   Examples/CompGenRec
cd Examples/CompGenRec
scram b
setenv OO_FD_BOOT cmspf01::/cms/reconstruction/user/jet0900/jet0900.boot
setenv CARF_INPUT_OWNER jetNoPU_CERN
setenv CARF_INPUT_DATASET_NAME eg_1gam_pt25
rehash
ExCompMuon
Let's look at the result: This example is interesting since the program will access generated muons, calorimeter clusters, tracker tracks and muon detector tracks through four methods(subroutines) called getGeneratorParticles, getCalorimeterClusters, getTrackerTracks, getMuonTracks. As you can see from the code the access to each kind of information is far for simple and the BuildFile itself is also complex. No wonder that we can't get a simple program filling some quantity in a histogram running:the navigation to access any single piece of information that before was as easy as counting 1,2,.. in a bank, now is a complete nightmare.

DetUnit: another piece of the puzzle

This is another important piece of the puzzle:this concerns the second layer of complexity i.e. the object model of CMS.Before introducing this new object let's see again the phases of reconstruction. We have 3 phases and each phase produces objects that can be in part persistent. Everything starts with SimHits stored in DB. Then we have Digits that must be equal to what we get with real data.Note that some Digits wan't be stored in DB since they will be immediately processed and transformed in RecHits stored in DB. Viceversa some RecHits will be only virtual objects, since will be computed on the fly when needed. At the end of the reconstruction we have the RecObj(tracks and clusters) stored in DB.
Now let's go back to DetUnit and the detector.Each module of the detector is represented in the software by a DetUnit object.Let's look first at a pictorial representation of the various objects used(the so called class diagram) .So we have thousands of DetUnits objects modelling the real detector.Every DetUnit has pointers to other objects which contain the geometrical information of the module(absolute position, orientation, etc...). From this point of view this is similar to what we had in the past. The novelty is that now you can access also event data through DetUnit.All information associated with a detector module like Digis, simulated (Geant) hits and reconstructed hits(cluster) are accessed through the corresponding DetUnit. In the case of simulated hits SimHits this happens through an object SimDet: i.e. DetUnit points to SimDet that has a method returning a vector of SimHit pointers. RecHits are instead created on the spot by the corresponding DetUnit.Digis are provided by DetUnit through another object named Readout. The Readout object can be viewed as a container of Digis corresponding to a single DetUnit. In the Orca output you see frequently the sentence:
creating a ROU Slave Factory  for:
followed by some acronym. This is connected to the mechanism seen before. The first two letters in the acronym indicate wich kind of subdetector ORCA is handling:

Raw data physical clustering

Let's think about Objectivity federation as a physical "container" composed from files("databases") segmented in containers. The problem of the people writing the CMS software was:
  1. Decide which objects should be stored and which not.
  2. If an object is not stored ensure that enough information is stored that we can recreate it from what we have in the database.
  3. Decide what happens if we recalculate the same objects:we update the previous objects or we create a copy (cloning in ooslang).
  4. Try to put toghether objects that are mostly processed toghether
  5. Decide what name to give to each database and container (not an easy thing when you have thousands of them)
  6. Decide where to store the single object.
  7. Last but not least, try to do this in such a way that can be implemented also with other databases(if CMS decides to change from Objectivity).
As you see, not an easy task. From the production page the main strategy used can be seen. In this page each number corresponds to a database: so this is a schematic representation of the federation. The databases are grouped in dataset. Each dataset is divided in two or more sections belonging to different owner. Note that a single owner encompasses many datasets. For each section you have some lines named "Events" and "Collections" which are repeated. This shows the strategy used of cloning events and collections of events(runs) instead of updating a single object. The first event object is created by ooHit, the others by running ooDigi with different parameters.The other databases (except for MCInfo) contain SimHits produced by Montecarlo and Digis(i.e. Digits and RecHits that should be equal to raw data objects). Examining these databases you can see that the names of containers refer to pieces of the detector. This is because it was decided that raw data belonging to the same sub-detector are clustered toghether.

Getting information

How easy is to get up-to-date information on CMS software. I'll check this with this example problem:
The release 5_1_2 of ORCA has a new way to define the input dataset:
InputCollections=
instead of
CARF_INPUT_OWNER=
CARF_INPUT_DATASET_NAME=
I would like to have information on this: here are my tries: Problem solved in 20':not so bad!

Happy End

This story has an happy end. After six months(!?!) I have my histogram. It is the spread of the signal generated by Rpc chambers and is obtained by plotting the Rpc RecHits.Why I needed so much time? How I did succeed in the end?
In these six months I had the chance to discover one of the worst user interfaces in my programming experience. It is even worst than the infamous Job Control Language by IBM. The solution came out just thinking on how we old farts coped with such systems in the past. You just would get from a colleague a working deck of cards and you would use it again and again without trying to understand what was the meaning of such garbage like //GO SYSYN DD *. So,get a working job. But here in the ORCA manual we have some working example but they are hardly usable for the purpose. The problem is that the "BuildFile" and the "include file" work only for the example. In my case I have to access data about Rpc and I don't have the slightest idea on how to modify the BuildFile or on which one of the 1000 Orca objects I need to define in my include file. So, you would think, this is Mission Impossible III. Yes, until I discovered in the last release (5_1_2) the package Visualisation. Thanks Ianna Osborne! This is exactly what I needed. A package with: So I define a class "TwigMuBarRpcRecHits" that will process the Rpc RecHits and write the relevant information. I will process this information outside Orca with Paw .I could have done this directly in the class but for now don't try to overdo it!
TwigMuBarRpcRecHits.h is obtained by copying TwigMubarRpcSimHits.h with trivial changes;
#ifndef TwigMuBarRpcRecHits_H
#define TwigMuBarRpcRecHits_H
 
#include <Inventor/SbString.h>
#include "Cmscan/IgCmscan/interface/IgQtTwig.h"
#include <fstream>
 
/**
*
*   Draw the reconstructed hits in the muon RPC (barrel)
*
*
*/
class TwigMuBarRpcRecHits : public IgQtTwig
{
public:
 
    typedef IgQtTwig inherited;
    explicit TwigMuBarRpcRecHits( IgQtTwig* parent, SbString nm, bool b = true,
bool c = false )
        : IgQtTwig( parent, nm, b, c ) { outfile= new ofstream("out.dat",ios::ou
t);}
~TwigMuBarRpcRecHits() { outfile->close();}
    /** Draw the reconstructed hits in the muon system.
     */
    void drawMe();
protected:
 
    //!     Provide basic information upon pick
    virtual void printInfo( ostream & ostr, const SoNode* node ) const;
 
private:
 
    ostream* ostr;
    ofstream* outfile;
 
};
 
#endif
TwigMuBarRpcRecHits.cc is obtained from TwigEndRpcRecHits.cc
#include "Utilities/Configuration/interface/Architecture.h"
#undef HEP_SHORT_NAMES
#include "Visualisation/MuonVis/interface/TwigMuBarRpcRecHits.h"
#include <iostream>
 
#include "HEPVis/nodes/SoHitsKit.h"
 
#include "Muon/MRpcDetector/interface/MRpcDetector.h"
#include "Muon/MRpcDetector/interface/MRpcChamber.h"
#include "Muon/MRpcDetector/interface/MRpcDetUnit.h"
#include "Muon/MRpcSetUp/interface/MRpcSetUp.h"
#include "Muon/MRpcDetector/interface/CMSMuonRpc.h"
 
#include "CommonDet/DetLayout/interface/DetLayer.h"
#include "CommonDet/BasicDet/interface/RecHit.h"
 
#include "Utilities/Notification/interface/Singleton.h"
 
#include <Inventor/nodes/SoMaterial.h>
 
 
void TwigMuBarRpcRecHits::drawMe()
{
{
 
    //  Count up total number of RecHit's
    //  ---------------------------------
    int nRecHits = 0;
    MRpcSetUp* muon_setup = Singleton::instance();
    CMSMuonRpc * muon = muon_setup->CMSMRpc();
    for( int ilay = 0; ilay<4; ilay++ ) {
     DetLayer* layer = muon->barrelLayers()[ilay];
     for( int ista = 0; ista< layer->detUnits().size(); ista++ ) {
        DetUnit* stat = layer->detUnits()[ ista ];
        DetUnit::RecHitContainer sits = stat->recHits();
        for( DetUnit::RecHitIterator is = sits.begin(); is != sits.end(); is++ )
 {
            LocalPoint xyzLocal = is->localPosition();
            float x = xyzLocal.x();
            float y = xyzLocal.y();
            float z = xyzLocal.z();
            float dx = is->localPositionError().xx();
            float dy = is->localPositionError().yy();
 
                        nRecHits++;
           *outfile << nRecHits << " "<< ilay <<"  " << ista << " " << x << " " << y << " " << z << "  " << dx << " " << dy << endl;
                    }
                    }
                }
 
    cout << "Number of Rpc Rechits: " << nRecHits << endl;
 
 
}
 
void TwigMuBarRpcRecHits::printInfo( ostream & ostr, const SoNode* node ) const
{
}
This is the modified Init.cc
#include "Utilities/Configuration/interface/Architecture.h"
 
 
#include "Visualisation/MuonVis/interface/TwigMuBarSimHits.h"
#include "Visualisation/MuonVis/interface/TwigMuBarRpcRecHits.h"
#include "Visualisation/MuonVis/interface/TwigMuBarSegment.h"
#include "Visualisation/MuonVis/interface/TwigMuEndSimHits.h"
#include "Visualisation/MuonVis/interface/TwigMuEndRecHits.h"
#include "Visualisation/MuonVis/interface/TwigMuEndSegment.h"
#include "Visualisation/MuonVis/interface/TwigMuEndRpcSimHits.h"
#include "Visualisation/MuonVis/interface/TwigMuBarRpcSimHits.h"
#include "Visualisation/MuonVis/interface/TwigMuSimTracks.h"
#include "Visualisation/MuonVis/interface/TwigMuRecTracks.h"
 
 
#include "Visualisation/OrcaVis/interface/TwigEvt.h"
#include "Utilities/Notification/interface/Observer.h"
 
 
class BuildMuonVisEvt : private Observer {
public:
    BuildMuonVisEvt() { init();}
private:
    void upDate(TwigEvt* theTwigEvt) {
        if (theTwigEvt==0) return;
        // Muon System
        //
        IgQtTwig * theTwigEvtMuon = new IgQtTwig( theTwigEvt, "Muon System", TRU
E, TRUE );
 
        //
        // Muon Barrel
        //
        IgQtTwig * theTwigBarMuon = new IgQtTwig( theTwigEvtMuon, "Muon Barrel",
 TRUE, TRUE );
        (void) new TwigMuBarSimHits(    theTwigBarMuon, "DT Sim Hits",       FAL
SE, FALSE );
        (void) new TwigMuBarRpcSimHits( theTwigBarMuon, "RPC Sim Hits",      FAL
SE, FALSE );
        (void) new TwigMuBarRpcRecHits( theTwigBarMuon, "RPC Rec Hits",      FAL
SE, FALSE );
        (void) new TwigMuBarSegment(    theTwigBarMuon, "DT Track Segments", FAL
SE, FALSE );
 
        //
        // Muon Endcap
        //
        IgQtTwig * theTwigEndMuon = new IgQtTwig( theTwigEvtMuon, "Muon Endcap",
 TRUE, TRUE );
        (void) new TwigMuEndSimHits(    theTwigEndMuon, "CSC Sim Hits",       FA
LSE, FALSE );
        (void) new TwigMuEndRpcSimHits( theTwigEndMuon, "RPC Sim Hits",       FA
LSE, FALSE );
        (void) new TwigMuEndRecHits(    theTwigEndMuon, "CSC Rec Hits",       FA
LSE, FALSE );
        (void) new TwigMuEndSegment(    theTwigEndMuon, "CSC Track Segments", FA
LSE, FALSE );
 
        (void) new TwigMuRecTracks(  theTwigEvtMuon, "Rec Tracks",     FALSE, FA
LSE );
 
        (void) new TwigMuSimTracks(  theTwigEvtMuon, "Sim Tracks",     FALSE, FA
LSE );
    }
};
 
#include "Utilities/Notification/interface/PackageInitializer.h"
 
static PKBuilder muonVisEvt("MuonVisEvt");

Recovering data from CMS software black hole 3

Now that we know the trick, getting data out of Orca is easy. We just add some line of code to the relevant Twig... object.
Simhits in tracker
Code added/modified to TwigTkSimHits.cc
#include  "CommonDet/BasicDet/interface/DetType.h"  
 SbVec3f *pts = new SbVec3f[nSimHits];
    SbVec3f *iPts = pts;
    cout << "Tracker found " << nSimHits << " SimHits " << endl;
    int nde=0;
    for (iDet = dets.begin(); iDet != dets.end(); iDet++) {
      SimDet* simDet = iDet->simDet();
    Module modulo = iDet->type().module();
    Part bar_fow = iDet->type().part();
    int isd  = (int)iDet->type().sides();
      if (simDet && !simDet->simHits().empty()) {
 
        const SimDet::SimHitContainer& sits = simDet->simHits();
 
        for (SimDet::SimhitIterator is = sits.begin(); is != sits.end(); is++)
       {
 
          float x = is->globalPosition().x() / 100.0;  // cm -> m
          float y = is->globalPosition().y() / 100.0;  // cm -> m
          float z = is->globalPosition().z() / 100.0;  // cm -> m
 
          *iPts++ = SbVec3f(x,y,z);
           nde++;
         *outfile << nde <<" "<< modulo << " " << bar_fow << " " << x << " " << y <<
" " << z << " "<< endl;
        }
      }
    }                          
The result:
1 pixel  forward  0.0324629 0.140936 -0.315116
2 pixel  forward  0.00167622 0.0964537 -0.324112
3 pixel  forward  0.0144903 0.0951627 -0.319427
4 pixel  forward  0.0189675 0.0740032 -0.321541
5 pixel  forward  0.0330585 0.115285 -0.330074
6 pixel  forward  0.0388094 0.105706 -0.33154    

Rechits in Tracker
Code for TwigTkRecHits.h
#ifndef __INCLUDE_TwigTkRecHits__
#define __INCLUDE_TwigTkRecHits__
 
#include <Inventor/SbString.h>
#include "Visualisation/OrcaVis/interface/AutoTwig.h"
#include "Ig_Extensions/IgGeant3/interface/G3Pars.h"
#include "CommonDet/BasicDet/interface/DetUnit.h"
#include <Inventor/SbLinear.h>
#include <fstream>
 
class TwigTkRecHits : public AutoTwig {
public:
        typedef IgQtTwig inherited;    
        explicit TwigTkRecHits(IgQtTwig* parent, SbString nm, bool b=true, bool
c=false)  :
          AutoTwig(parent, nm, b, c) {
            outSimHitF = new ofstream("SimHitF.dat",ios::out);
           }
        void drawMe();
private:
        ofstream* outSimHitF;
  };
 
#endif                  
Code for TwigTkRecHits.cc
#include "Utilities/Configuration/interface/Architecture.h"
#include "Visualisation/TrackerVis/interface/TwigTkRecHits.h"
#include <iostream>
#include "Tracker/CARFTracker/interface/FullTracker.h"
#include "Tracker/TkLayout/interface/CmsTracker.h"
#include "CommonDet/DetGeometry/interface/GlobalPoint.h"
#include "CommonDet/DetGeometry/interface/TkRotation.h"
#include "CommonDet/DetGeometry/interface/Surface.h"
#include "CommonDet/DetGeometry/interface/ActiveMediaShape.h"
#include "CommonDet/DetLayout/interface/DetLayer.h"
#include "CommonDet/BasicDet/interface/DetUnit.h"
#include "CommonDet/BasicDet/interface/Enumerators.h"
#include "CommonDet/BasicDet/interface/Det.h"
#include "CommonDet/BasicDet/interface/DetType.h"
#include "CommonDet/BasicDet/interface/RecHit.h"
 
void TwigTkRecHits::drawMe() {
    inherited::drawMe();
    // instanciate Tracker
    const CmsTracker::LayerContainer& theLayerContainer = FullTracker::instance()->Tracker()->forwardLayers();                    
    CmsTracker::layer_p_iter iLay;
    int nlay=0;
    int nmod1=0;
    int anello = 0;
    int nmod = 0;
    int nsimhit = 0;
    float r;
    float phi,phi1;
    int spicchi[] ={24,24,40,56,40,56,80};
    float rmedioS[]={0.27665, 0.3671, 0.4474, 0.5617, 0.6768, 0.8189, 0.9912};
    float rmedioP[]={0.064122, 0.0766412, 0.0899707, 0.10658, 0.12008, 0.137039, 0.145999};
    for (iLay = theLayerContainer.begin(); iLay != theLayerContainer.end(); iLay++) {
        nlay++;
        Module layer_type = (*iLay)->module();
        const CmsTracker::DetContainer theDetContainer = (*iLay)->detUnits();
        CmsTracker::det_p_iter iDet;
        for (iDet = theDetContainer.begin() ; iDet != theDetContainer.end() ; iDet++) {
             float posx = (*iDet)->surface().position().x()/ 100.0;  // cm -> m
                                      
             float posy = (*iDet)->surface().position().y()/ 100.0;  // cm -> m
             r=pow((posx*posx + posy*posy),0.5);
             phi1=atan(posy/posx);
             phi=phi1;
             if(posy < 0.&&posx>0)phi=phi1+2.*3.1415;
             if(posx < 0.)phi=phi1+3.1415;
             if(fabs(posy)<0.000001&&posx>0)phi=0;
             if(fabs(posy)<0.000001&&posx<0)phi=3.1415;
             if(fabs(posx)<0.000001&&posy>0)phi=3.1415/2.;
             if(fabs(posx)<0.000001&&posy<0)phi=3.1415/2.;
             if (layer_type==silicon) {
                 for (int i=0;i<7; i++){
                    if (fabs(r-rmedioS[i])<0.0001){
                       anello =i+1;
                       break;
                    }
                 }
                 nmod=(int)((phi/(2.*3.1415))*spicchi[anello-1]+.1)+1;
             }
             else{
              for (int i=0; i<7; i++){             
                  if(fabs(r -rmedioP[i])<0.0001){
                     anello=i+1;
                     break;
                  }
              }
               nmod=(int)((phi/(2.*3.1415))*24+.1)+1;
             }
 
            Module modulo = (*iDet)->type().module();
            Part bar_fow = (*iDet)->type().part();
            int isd  = (int)(*iDet)->type().sides();
            if (!(*iDet)->recHits().empty()) {
                DetUnit::RecHitContainer sits = (*iDet)->recHits();
                for (DetUnit::RecHitIterator is = sits.begin(); is != sits.end(); is++) {
                    float posx = is->globalPosition().x() / 100.0;  // cm -> m
                    float posy = is->globalPosition().y() / 100.0;  // cm -> m
                    float posz = is->globalPosition().z() / 100.0;  // cm -> m
                    float x = is->localPosition().x() ;
                    float y = is->localPosition().y();
                    float dx = is->localPositionError().xx();   
                    float dy = is->localPositionError().yy();
                    nsimhit++;
*outSimHitF << nsimhit << " " << (*iLay)->module() <<" "<< "forward"<< " " << nlay <<"  "<< anello << " " << nmod << " " << posx << " " << posy << " " << posz << " " << x << " " << y << " "<< dx << " " << dy << endl;
                }
            }
         }
    }
    const CmsTracker::LayerContainer& theLayerContainer1 = FullTracker::instance()->Tracker()->barrelLayers();
    CmsTracker::layer_p_iter iLay1;
    nmod1=0;
    nmod = 0;
    float oldz;
    int spicchib[] ={18,30,42,28,38,44,56,42,48,54,60,66,74};
    for (iLay1 = theLayerContainer1.begin(); iLay1 != theLayerContainer1.end();
iLay1++) {
        nlay++;
        anello = -1;
        Module layer_type1 = (*iLay1)->module();               
        const CmsTracker::DetContainer theDetContainer1 = (*iLay1)->detUnits();
        CmsTracker::det_p_iter iDet1;
        for (iDet1 = theDetContainer1.begin() ; iDet1 != theDetContainer1.end()
; iDet1++) {
             float posx = (*iDet1)->surface().position().x()/ 100.0;  // cm -> m             float posy = (*iDet1)->surface().position().y()/ 100.0;  // cm -> m             float posz = (*iDet1)->surface().position().z()/ 100.0;  // cm -> m             if (anello == -1){
            oldz = posz;
            anello = 1;
          }
          else{
            if(fabs(oldz - posz) > 0.001 )
            {
              oldz = posz;
              anello++;
            }
          }
             r=pow((posx*posx + posy*posy),0.5);
             phi1=atan(posy/posx);
             phi=phi1;              
             if(posy < 0.&&posx>0)phi=phi1+2.*3.1415;
             if(posx < 0.)phi=phi1+3.1415;
             if(fabs(posy)<0.000001&&posx>0)phi=0;
             if(fabs(posy)<0.000001&&posx<0)phi=3.1415;
             if(fabs(posx)<0.000001&&posy>0)phi=3.1415/2.;
             if(fabs(posx)<0.000001&&posy<0)phi=3.1415/2.;
             nmod=(int)((phi/(2.*3.1415))*spicchib[nlay-29]+.1)+1;
            Module modulo1 = (*iDet1)->type().module();
            Part bar_fow1 = (*iDet1)->type().part();
            int isd1  = (int)(*iDet1)->type().sides();
            if (!(*iDet1)->recHits().empty()) {
                DetUnit::RecHitContainer sits1 = (*iDet1)->recHits();
                for (DetUnit::RecHitIterator is1 = sits1.begin(); is1 != sits1.end(); is1++) {
                    float posx1 = is1->globalPosition().x() / 100.0;  // cm -> m                    float posy1 = is1->globalPosition().y() / 100.0;  // cm -> m                    float posz1 = is1->globalPosition().z() / 100.0;  // cm -> m                    float x1 = is1->localPosition().x() ;
                    float y1 = is1->localPosition().y();
                    float dx1 = is1->localPositionError().xx();
                    float dy1 = is1->localPositionError().yy();   
                    nsimhit++;
*outSimHitF << nsimhit << " " << (*iLay1)->module() <<" "<< "barrel" << " " << nlay <<"  "<< anello << " " << nmod << " " << posx1 << " " << posy1 << " " << posz1 << " " << x1 << " " << y1 << " "<< dx1 << " " << dy1 << endl;
                }
            }
         }
    }
}
      
The result:
1 silicon  forward 1  4 30 -0.557684 -0.0710207 -2.6375 -2.34123 0 0.0191961 11.04
2 silicon  forward 1  4 30 -0.555236 -0.085427 -2.6375 -0.879943 0 0.00272552 11.04
3 silicon  forward 1  4 30 -0.552633 -0.100746 -2.6375 0.673891 0 0.0016052 11.04
4 silicon  forward 1  4 29 -0.562115 -0.00838537 -2.6345 -2.31599 0 0.0187848 11.04
5 silicon  forward 1  4 29 -0.560971 -0.0287406 -2.6345 -0.277253 0 0.000285123 11.04
6 silicon  forward 1  4 29 -0.559842 -0.0488352 -2.6345 1.73538 0 0.0105539 11.04
7 silicon  forward 1  4 29 -0.559403 -0.0566546 -2.6345 2.51854 0 0.0222113 11.04
8 silicon  forward 1  4 28 -0.560256 0.0414884 -2.6375 -1.00234 0 0.0035317 11.04
9 silicon  forward 1  4 28 -0.560395 0.0389969 -2.6375 -0.7528 0 0.00199913 11.04
10 silicon  forward 1  4 28 -0.562348 0.00422147 -2.6375 2.73022 0 0.0260989 11.04                                                      

Tracker modules
Code for TwigTkRecHits.h
#ifndef __INCLUDE_TwigTkRecHits__
#define __INCLUDE_TwigTkRecHits__
 
#include <Inventor/SbString.h>
#include "Visualisation/OrcaVis/interface/AutoTwig.h"
#include "Ig_Extensions/IgGeant3/interface/G3Pars.h"
#include "CommonDet/BasicDet/interface/DetUnit.h"
#include <Inventor/SbLinear.h>
#include <fstream>
 
class TwigTkRecHits : public AutoTwig {
public:
        typedef IgQtTwig inherited;    
        explicit TwigTkRecHits(IgQtTwig* parent, SbString nm, bool b=true, bool
c=false)  :
          AutoTwig(parent, nm, b, c) {
            outSimHitF = new ofstream("SimHitF.dat",ios::out);
           }
        void drawMe();
private:
        ofstream* outSimHitF;
  };
 
#endif                  
Code for TwigTkRecHits.cc
#include "Utilities/Configuration/interface/Architecture.h"
#include "Visualisation/TrackerVis/interface/TwigTkRecHits.h"
#include <iostream>
#include "Tracker/CARFTracker/interface/FullTracker.h"
#include "Tracker/TkLayout/interface/CmsTracker.h"
#include "CommonDet/DetGeometry/interface/GlobalPoint.h"
#include "CommonDet/DetGeometry/interface/TkRotation.h"
#include "CommonDet/DetGeometry/interface/Surface.h"
#include "CommonDet/DetGeometry/interface/ActiveMediaShape.h"
#include "CommonDet/DetLayout/interface/DetLayer.h"
#include "CommonDet/BasicDet/interface/DetUnit.h"
#include "CommonDet/BasicDet/interface/Enumerators.h"
#include "CommonDet/BasicDet/interface/Det.h"
#include "CommonDet/BasicDet/interface/DetType.h"

void TwigTkRecHits::drawMe() {
    inherited::drawMe();
    const CmsTracker::LayerContainer& theLayerContainer = FullTracker::instance()->Tracker()->forwardLayers();
    CmsTracker::layer_p_iter iLay;
    int det_type=0;
    int nlay=0;
    int nmod1=0;
    int anello = 0;
    int nmod = 0;
    int ntotmod = 0;
    float r;
    float phi,phi1;    
    float hbotedge,  htopedge, hapothem, hthickness;
    int spicchi[] ={24,24,40,56,40,56,80};
    float rmedioS[]={0.27665, 0.3671, 0.4474, 0.5617, 0.6768, 0.8189, 0.9912};
    float rmedioP[]={0.064122, 0.0766412, 0.0899707, 0.10658, 0.12008, 0.137039, 0.145999};
    for (iLay = theLayerContainer.begin(); iLay != theLayerContainer.end(); iLay++) {
        nlay++;
	Module layer_type = (*iLay)->module();
	const CmsTracker::DetContainer theDetContainer = (*iLay)->detUnits();
	CmsTracker::det_p_iter iDet;
	for (iDet = theDetContainer.begin() ; iDet != theDetContainer.end() ; iDet++) {	    
             float posx = (*iDet)->surface().position().x()/ 100.0;  // cm -> m
             float posy = (*iDet)->surface().position().y()/ 100.0;  // cm -> m
             float posz = (*iDet)->surface().position().z()/ 100.0;  // cm -> m
             r=pow((posx*posx + posy*posy),0.5);
             phi1=atan(posy/posx);
             phi=phi1;
             if(posy < 0.&&posx>0)phi=phi1+2.*3.1415;
             if(posx < 0.)phi=phi1+3.1415;
             if(fabs(posy)<0.000001&&posx>0)phi=0;
             if(fabs(posy)<0.000001&&posx<0)phi=3.1415;
             if(fabs(posx)<0.000001&&posy>0)phi=3.1415/2.;
             if(fabs(posx)<0.000001&&posy<0)phi=3.1415/2.; 
             det_type=1;
             if (layer_type==silicon) {
                 det_type=2;
                 for (int i=0;i<7; i++){
                    if (fabs(r-rmedioS[i])<0.0001){
                       anello =i+1;
                       break;
                    }
                 }
                 nmod=(int)((phi/(2.*3.1415))*spicchi[anello-1]+.1)+1;
             }
             else{
              for (int i=0; i<7; i++){	
                  if(fabs(r -rmedioP[i])<0.0001){
                     anello=i+1;
                     break;
                  } 
              }
               nmod=(int)((phi/(2.*3.1415))*24+.1)+1;    
             }
             if (layer_type==silicon && (*iDet)->type().isStereo()) nmod=nmod+100; 
	     
             const vector par = (*iDet)->type().shape().parameters();  
 if (par.size() == 3) { 
         hbotedge= (*iDet)->type().shape().width()/ 100.0;
         htopedge= (*iDet)->type().shape().width()/ 100.0;
         hapothem=(*iDet)->type().shape().length()/ 100.0; 
         hthickness= (*iDet)->type().shape().thickness()/ 100.0;
       } else if (par.size() == 4) { 
         hbotedge=par[0]/100.0; 
         htopedge=par[1]/100.0;
         hapothem=par[3]/100.0;
         hthickness=par[2]/100.0;      }
            ntotmod++;
*outSimHitF << ntotmod << " " << det_type << " 1 " << nlay <<"  "<< anello << " " << nmod << " " << posx << " " << posy << " " << posz << " " << hbotedge << " " << htopedge << " " << hapothem << " "<< hthickness << endl; 
	 }
    }
    const CmsTracker::LayerContainer& theLayerContainer1 = FullTracker::instance()->Tracker()->barrelLayers();
    CmsTracker::layer_p_iter iLay1;
    nmod1=0;
    nmod = 0;
    float oldz;
    int spicchib[] ={18,30,42,28,38,44,56,42,48,54,60,66,74};
    for (iLay1 = theLayerContainer1.begin(); iLay1 != theLayerContainer1.end(); iLay1++) {
        nlay++;
        anello = -1;
	Module layer_type1 = (*iLay1)->module();
	const CmsTracker::DetContainer theDetContainer1 = (*iLay1)->detUnits();
	CmsTracker::det_p_iter iDet1;
	for (iDet1 = theDetContainer1.begin() ; iDet1 != theDetContainer1.end() ; iDet1++) {	    
             float posx1 = (*iDet1)->surface().position().x()/ 100.0;  // cm -> m
             float posy1 = (*iDet1)->surface().position().y()/ 100.0;  // cm -> m
             float posz1= (*iDet1)->surface().position().z()/ 100.0;  // cm -> m
             if (anello == -1){
            oldz = posz1;
            anello = 1;
          }
          else{
            if((nlay<36 && fabs(oldz - posz1) > 0.001) || 
               ( nlay>35 && fabs(oldz - posz1) > 0.05 ))
            {
              oldz = posz1;
              anello++;
            }
          }     
             r=pow((posx1*posx1 + posy1*posy1),0.5);
             phi1=atan(posy1/posx1);
             phi=phi1;
             if(posy1 < 0.&&posx1>0)phi=phi1+2.*3.1415;
             if(posx1 < 0.)phi=phi1+3.1415;
             if(fabs(posy1)<0.000001&&posx1>0)phi=0;
             if(fabs(posy1)<0.000001&&posx1<0)phi=3.1415;
             if(fabs(posx1)<0.000001&&posy1>0)phi=3.1415/2.;
             if(fabs(posx1)<0.000001&&posy1<0)phi=3.1415/2.; 
             nmod=(int)((phi/(2.*3.1415))*spicchib[nlay-29]+.1)+1;
             det_type=1;
             if (layer_type1==silicon)  det_type=2;
             if (layer_type1==silicon && (*iDet1)->type().isStereo()) nmod=nmod+100; 
            const vector par = (*iDet1)->type().shape().parameters();
 if (par.size() == 3) { // Rectangular
         hbotedge= (*iDet1)->type().shape().width()/ 100.0;// cm -> m
         htopedge= (*iDet1)->type().shape().width()/ 100.0; // cm -> m
         hapothem=(*iDet1)->type().shape().length()/ 100.0; // cm -> m
         hthickness= (*iDet1)->type().shape().thickness()/ 100.0; // cm -> m 
        } else if (par.size() == 4) { // Trapezoidal
         hbotedge=par[0]/100.0; // cm -> m
         htopedge=par[1]/100.0; // cm -> m
         hapothem=par[3]/100.0; // cm -> m
         hthickness=par[2]/100.0; // cm -> m  
      }
            ntotmod++;
 
*outSimHitF << ntotmod << " " << det_type <<" 2 " << nlay <<"  "<< anello << " " << nmod << " " << posx1 << " " << posy1 << " " << posz1 << " " << hbotedge << " " << htopedge << " " << hapothem << " "<< hthickness << endl; 
	 }
    }
}
The result:
1 2 1 1  4 30 -0.553762 -0.0941021 -2.6375 0.029 0.0356 0.05755 0.00015
2 2 1 1  4 29 -0.560816 -0.0315088 -2.6345 0.029 0.0356 0.05755 0.00015
3 2 1 1  4 28 -0.560817 0.0314807 -2.6375 0.029 0.0356 0.05755 0.00015
4 2 1 1  4 27 -0.553766 0.0940744 -2.6345 0.029 0.0356 0.05755 0.00015
5 2 1 1  4 23 -0.458109 0.325028 -2.6375 0.029 0.0356 0.05755 0.00015
6 2 1 1  4 22 -0.418837 0.374276 -2.6345 0.029 0.0356 0.05755 0.00015
7 2 1 1  4 21 -0.374298 0.418818 -2.6375 0.029 0.0356 0.05755 0.00015
8 2 1 1  4 20 -0.325051 0.458092 -2.6345 0.029 0.0356 0.05755 0.00015
9 2 1 1  4 16 -0.0941023 0.553761 -2.6375 0.029 0.0356 0.05755 0.00015
10 2 1 1  4 15 -0.0315091 0.560816 -2.6345 0.029 0.0356 0.05755 0.00015 

Standalone Installation of Orca:the nightmare

This is the report of a Standalone Installation of Orca : something that according the tutorial should be very easy and fast. I like the understatements in those tutorials ("take ORCA with you on the seashore"; copy and paste a few instructions and it's done!). The reality is that you can do it only if you are an expert Unix/Linux system manager and you need in any case (at least) two weeks. So let's tell the truth. The installation is described also here ( without SCRAM) and here with SCRAM. This is the complete sequence:
  1. Prepare the PC (that presumably has Windows installed) for Linux installation (1 day)
    For this I used the program Partition Magic. You must understand what are partitions and how the dual boot works. Of course, if you don't need Windows, than you can skip this phase and everything is more easy.
  2. Install Linux (Red Hat 6.1) 1 week
    Here the main problem is that RH6.1 is an old version and won't recognize a few devices in your computer (in my case the network and the video card) . So you have to do it by hand.
  3. Download Cern and CMS software - 1 day
    This part is relatively easy, although it is difficult to understand in wich directories the tons of files should go.
  4. Copy a Objectivity data base to test the installation - 1 week
    Here the biggest problem is size! I copied the ORCATEST.boot Objectivity data base and this is 13 Gigabytes! You need space (on the Cern machines) and a lot of time to copy it!
  5. Make Orca run (2 days)
    Have you defined correctly LD_LIBRARY_PATH? Are there other missing shared libraries?
  6. Make Orca compile (2 weeks) You do scram build and nothing happens! What's wrong? To discover the reason you have first to understand how SCRAM works and look inside the hundreds of files it uses to create the makefile that gets the code compiled.
Here a more detailed report on the whole operation and some resources:cerm.linux newsgroup.

Developer!

Hey! I have become a CMS developer! I feel like a mediaeval knight after the investiture. How you become a developer? Only another knight (pardon developer) can give you the title by adding your name to the list of developers responsible for some module in the repository. After that you are able to commit your changes to the repository.
Now I feel a big responsibility: how can my brain damaged by decades of Fortran programming cope with the new generation of oo knights? The code in the previous sections gives an idea on how my C++ programming is Fortran-like. I have really to start studying these 3 documents like the bible: Reading these guidelines, it is clear that I have to give up using my beloved Fortran arrays and to start using STL containers and iterators.

Changes,changes and more changes!

The good news about the programmer's life is that you never get bored. The bad news is that everything keeps changing and CMS software is no exception. This picture gives a vivid idea on how releases follow releases and everything changes.
Let's start with a few new acronyms:

DDD - Detector Description Database is a database describing (guess it!) the detector on ascii files containing XML tags plus a C++ Api to access this description. Fortunately for us the final users can (probably) safely ignore all the technicalities.

LCG - LHC Computing Grid project. A group of people working (among other things) on the replacement of Objectivity with Root.

Root - A Cern software by the same people that gave us Paw and Zebra. Root is intended in fact as a OO replacement for these successfull packages. Root will provide also the object persistency replacing Objectivity. In principle COBRA will hide end-users like us from the complexities of Root. But ,judging from the Root home page it is also possible that,in the future, it will bring at last an easy interface Paw-like for those that don't know oop.

POOL - Pool Of persistent Objects for LHC is the software provided by LCG that will take care of persistency of objects(in slang the persistency framework) this is the name of the root replacement of Objectivity.

For what concerns this document the most important change was the release of Iguana 4 with the new plugin architecture. This means ,said in plain words, that the objects like TwigMuBarRpcSimHits that we used in the previous paragraphs don't anymore exist:i.e. catastrophe! We have to restart from scratch!

ORCA_7.0 brings all these new things and it is interesting to compare the list of used packages with the same list for the previous release.

An inspection of the CVS repository for Visualization/MuonVis shows that the objects used in the previous paragraph have been thrown in the Attic but they seems to be replaced by the following new objects:

But first things first, let's try to run Iguana! After many hours of browsing the code and the documentation , in the Release note of ORCA_6_3_0 I find the magic words:
To start the visualisation, type "iguana" and select "COBRA". To display an object, first select the object and then click on the visualisaton box next to it.
Obvious? Isn't it! So these are the steps to run the iguana plugin with ORCA_6_3_0 (this is the first release the plugin architecture was introduced in Orca)
  1. cd /afs/cern.ch/cms/Releases/ORCA/ORCA_6_3_0/src
  2. eval `scram runtime -csh`
  3. cd
  4. source testfed.csh
  5. iguana

Now we try to add a branch "Event/Muon/Barrel/RpcMyHits" by cloning the branch "Event/Muon/Barrel/RpcSimHits" The complete procedure is:

  1. cd your local area
  2. project ORCA
  3. scram project ORCA ORCA_6_3_0
  4. cd ORCA_6_3_0/src
  5. cvs co -r ORCA_6_3_0 Visualisation
  6. cd Visualisation
  7. scram build
  8. iguana (it should work like before but using the code compiled in our area)
  9. cp MuonVis/src/VisMuBarRpcSimHitsTwig.cc MuonVis/src/VisMuBarRpcMyHitsTwig.cc
  10. cp MuonVis/interface/VisMuBarRpcSimHitsTwig.h MuonVis/interface/VisMuBarRpcMyHitsTwig.h
  11. modify MuonVis/src/VisMuBarRpcMyHitsTwig.cc
  12. modify MuonVis/interface/VisMuBarRpcMyHitsTwig.h
  13. modify MuonVis/interface/xtypeinfo.h
  14. modify MuonVis/src/plugin.cc
  15. modify MuonVis/src/VisMuDataProxy.cc
  16. scram build
  17. iguana (cross your finger!):result file
Hey , we are still in business! These are instead the steps to create a new branch in the Event subtree.
  1. modify CobraVisMain/src/CobraVisMain.cc adding:
     m_document->addContentProxy ("COBRA/Event/CustomTracker");  
    
  2. Create a bunch of classes

Objectivity out, enters ROOT!

Let's enter in a brave new world : Root, Grid, RH7.3, LCG, etc ... Let's try ORCA_7_1_1 !
  1. cd /afs/cern.ch/cms/Releases/ORCA/ORCA_7_1_1/src
  2. eval `scram runtime -csh`
  3. cd
  4. cp orcarc .orcarc
  5. iguana
The result is the following error message:
Xlib:  extension "GLX" missing on display "lxplus080:23.0".
Inventor error in SoQtGLWidget::SoQtGLWidget(): OpenGL not available!
The brave new world has to wait...

Second try a few days later

  1. cd orca
  2. project ORCA
  3. scram project ORCA ORCA_7_2_0_pre13
  4. cd ORCA_7_2_0_pre13/src
  5. cvs co -r ORCA_7_2_0_pre13 Visualisation
  6. cd Visualisation
  7. setenv SCRAM_ARCH Linux__2.4/gcc3
  8. scram build
  9. cp ~/orcarc .orcarc
  10. eval `scram runtime -csh`
  11. iguana
The result is still:
Xlib:  extension "GLX" missing on display "lxplus010:15.0". 
But now I know that the problem is with my computer X server that lacks this Opengl extension.

Third try a month later, after I have installed XFree86 Version 4.1.0 and solved a problem of test data samples inaccessibility with the help of Werner Jank

  1. cd orca
  2. project ORCA
  3. scram project ORCA ORCA_7_2_1
  4. cd ORCA_7_2_1/src
  5. cvs co -r ORCA_7_2_1 Visualisation
  6. cd Visualisation
  7. scram build
  8. cp ~/orcarc .orcarc
  9. eval `scram runtime -csh`
  10. iguana
It works again!
Not obvious with all the changes done. The most important is that there is no Objectivity data base. Now you can get a list of the data files with a simple:
rfdir suncmsc:/data/valid/ORCA_7_2_0
Iguana (that now uses the Coin 3D implementation of OpenInventor) is again almost unusable. We are two years back with many visualizations no more working and continuous crashes.

Fourth try with the next version of Orca containing Iguana

  1. cd orca
  2. project ORCA
  3. scram project ORCA ORCA_7_3_0
  4. cd ORCA_7_3_0/src
  5. cvs co -r ORCA_7_3_0 Visualisation
  6. cd Visualisation
  7. scram build
  8. cp ~/orcarc .orcarc
  9. eval `scram runtime -csh`
  10. env LOG=stderr iguana
    note where iguana freezes and remove the .reg file with following command:
  11. rm /afs/cern.ch/user/g/gzito/orca/ORCA_7_3_0/lib/Linux__2.4/iguana-plugins/MuonVis.reg
  12. env LOG=stderr iguana (now is OK) but the next time I run Iguana after changing something in the plugins, I must remove the plugin cache with following command:
  13. rm /afs/cern.ch/user/g/gzito/orca/ORCA_7_3_0/lib/Linux__2.4/iguana-plugins/.cache
Some not very obvious things to do.(This version has also a change in the name of plugin: this is no more named "COBRA" but "ORCA").

Running ORCA_7_4_0

Orca 7_4_0 doesn't have Iguana but we try to run a modified ExRunEventInfo.cc in Workspace in order to get out the tracker data.
  1. cd orca
  2. project ORCA
  3. scram project ORCA ORCA_7_4_0
  4. cd ORCA_7_4_0/src
  5. cvs co -r ORCA_7_4_0 Workspace
  6. cd Workspace
  7. scram b shared
  8. scram b bin
  9. eval `scram runtime -csh`
  10. cp ~/orcarc .orcarc
  11. ExRunEvent
Here the modified Buildfile, ExRunEventInfo.cc and two other files added in the same directory: CuTkBuilderInORCA.cc,CuTkBuilderInORCA.h
Note in the .orcarc file that for the first time the informations about datasets are taken from this catalog in Xml.
This is the first ORCA release that uses POOL for persistency.In fact a look at the list of used packages reveals a host of new acronyms. These are LCG Applications shared among LHC experiments.

Running ORCA_7_5_0

We proceed as for ORCA_7_4_0
  1. cd orca
  2. project ORCA
  3. scram project ORCA ORCA_7_5_0
  4. cd ORCA_7_5_0/src
  5. cvs co -r Tutorial031114a Workspace
  6. cd Workspace
  7. scram b shared
  8. scram b bin
  9. eval `scram runtime -csh`
  10. cp ~/orcarc .orcarc
  11. ExRunEvent

Running IGUANACMS 1.1.0 with ORCA_7_5_0

The examinations never end (this is the title of a Eduardo De Filippo play)!
We have to switch from IGUANA to IGUANACMS.
New site, new manual.
All the code in ORCA/Visualisation is obsolete.
Let's start again from scratch!
  1. cd orca
  2. project IGUANACMS
  3. scram project IGUANACMS IGUANACMS_1_1_0
  4. cd IGUANACMS_1_1_0
  5. cvs co -d src -r IGUANACMS_1_1_0 IGUANACMS
  6. cd src
  7. scram build
  8. eval `scram runtime -csh`
  9. cd VisOrca/VisOrcaMain/test
  10. cp ~/orcarc .orcarc
  11. iguana --list
Now we try to build a new module "VisCustomTracker"
  1. cd IGUANACMS_1_1_0/src/VisOrca
  2. cp -r VisTracker VisCustomTracker
  3. modify VisOrcaMain/src/VisOrcaMain.cc adding the following line:
     m_document->addContentProxy ("ORCA/Event/CustomTracker");   
  4. in VisCustomTracker rename the following files:
    mv  src/VisTkEventContent.cc  src/VisCuTkEventContent.cc
    mv  src/VisTkTwig.cc  src/VisCuTkTwig.cc
    mv  src/VisTkSimHitsTwig.cc  src/VisCuTkSimHitsTwig.cc
    mv  interface/VisTkEventContent.h  interface/VisCuTkEventContent.h
    mv  interface/VisTkTwig.h  interface/VisCuTkTwig.h
    mv  interface/VisTkSimHitsTwig.h  interface/VisCuTkSimHitsTwig.h
    
  5. Now modify these 8 files: .src/VisCuTkEventContent.cc , src/VisCuTkTwig.cc , src/VisCuTkSimHitsTwig.cc , src/plugin.cc , interface/VisCuTkEventContent.h , interface/VisCuTkTwig.h , interface/VisCuTkSimHitsTwig.h , interface/xtypeinfo.h
  6. scram b
  7. cd ..
  8. iguana
This is the result

Running IGUANACMS 1.3.0 with ORCA_7_5_2

This new version of Iguanacms contains also the CustomTracker plugin.
  1. cd orca
  2. project IGUANACMS
  3. scram project IGUANACMS IGUANACMS_1_3_0
  4. cd IGUANACMS_1_3_0/src
  5. cvs co -r IGUANACMS_1_3_0 VisOrca
  6. cd VisCustomTracker
  7. scram build
  8. eval `scram runtime -csh`
  9. cd ../VisOrca/VisOrcaMain/test
  10. iguana

Running IGUANACMS 1.7.0 with ORCA_8_1_1 and COBRA_7_8_1

  1. cd orca
  2. project IGUANACMS
  3. scram project IGUANACMS IGUANACMS_1_7_0_pre1
  4. cd IGUANACMS_1_7_0_pre1/src
  5. cvs co VisOrca/VisCustomTracker
  6. cvs co VisOrca/VisOrcaMain
  7. cd VisOrca/VisCustomTracker
  8. scram build
  9. eval `scram runtime -csh`
  10. cd VisOrcaMain/test
  11. vi .orcarc (to add :ORCA/Event/CustomTracker)
  12. iguana

Running IGUANACMS 1.10.0 based on IGUANA_5_1_1 with ORCA_8_3_0,OSCAR 3.3.1 and COBRA_7_8_6

  1. cd orca
  2. project IGUANACMS
  3. scram project IGUANACMS IGUANACMS_1_10_0
  4. cd IGUANACMS_1_10_0/src
  5. cvs co VisOrca/VisCustomTracker
  6. cd VisOrca/
  7. scram build
  8. eval `scram runtime -csh`
  9. cp ~/orca/IGUANACMS_1_9_1/src/VisOrca/VisOrcaMain/test/.orcarc orcarc
  10. iguana -c orcarc

Explore your Federation(2)!

Objectivity is out, but we still have Federations.They are now implemented using LCG software.This means that you can have your federation on your computer but also on the Grid. Now we will do again this exercise of exploring our federation in order to discover what is changed.The good things are: Are you ready for the exploration? First you have to get the catalog name of the federation. For example : http://cmsdoc.cern.ch/orca/catalog/PoolFileCatalog_7_5_0.xml.I have a text copy here in case your browser doesn't see xml. This catalog describes the federation contained in /castor/cern.ch/cms/reconstruction/datafiles/ORCA_7_5_0/ and composed by 341 files.
In order to use FCBrowser.py we have to:
  1. setenv PATH /afs/cern.ch/sw/lcg/app/spi/scram:$PATH
  2. setenv SCRAM_ARCH rh73_gcc32
  3. setenv CVSROOT :pserver:anoncvs@lcgapp.cern.ch:/cvs/POOL
  4. cvs login
  5. type password cvs
  6. mkdir ~/mypool
  7. cd mypool
  8. scram project POOL POOL_1_4_0
  9. cd ~/mypool/POOL_1_4_0/src
  10. cvs co -r POOL_1_4_0 Examples
  11. cd Examples/
  12. cd SimpleWriter
  13. scram b
  14. eval `scram runtime -csh`
  15. rehash
  16. SimpleWriter
  17. cd ../../
  18. cp Examples/SimpleWriter/pool.env .
  19. Modify pool.env replacing xmlcatalog_file:FileCatalog.xml with xmlcatalog_http://cmsdoc.cern.ch/orca/catalog/PoolFileCatalog_7_5_0.xml
  20. eval `scram runtime -csh pool.env`
  21. FCBrowser.py
Playing with this you discover that each file has a LFN Logical File Name and a PFN Physical File Name.There are also for each file 7 "metadata" attributes: jobid , dataset, DataType, FileCategory, runid, DBoid, owner. Note that each "file" corresponds to the Objectivity "database".

(Real) Developers see (design) patterns everywhere!

As I enter more in the intricacies of the CMS object model, I am starting to understand some strange slang real OO developers use when they refer to the objects implemented.For example Observer, Lazy Observer, Dispatcher, Builder, Proxy, Singleton, Adapter, Facade, Factory ... These are all Design Patterns: more or less programming recipes to solve well known problems that appear frequently in OO programming.We have already in this document used this pattern jargon when we spoke about Action on demand , containers and iterators.
The idea is good: don't reinvent the wheel and use some clever ways already tested. The only problem is that it is very difficult for a newbie to OO programming to realize that his problem can be solved by the Singleton pattern nicely provided by other CMS developers in this directory.

Standalone Installation of Iguanacms: with XCMSI the nightmare is (almost) over!

This is the report of a Standalone Installation of Iguanacms : something that now using XCMSI should be done in a few hours.(Installing Orca 3 years ago took 2 weeks and the help of a system manager). So let's see what happens! The sight of the list of packages gives an idea on how complex CMS software is and how it is becoming more and more complex as we add new functionality with LCG software. More than 1 GB of code in around 100 rpm! I start by following the "Installation Step by Step" instructions. After two hours of downloading and installing:
error: failed dependencies:
        LCG.root-rh73_gcc32-3.10.02-1 = cms is needed by CMS.pax-rh73_gcc32-1.02.02-cms-2
        LCG.rootcore-rh73_gcc32-3.10.02-1 = cms is needed by CMS.pax-rh73_gcc32-1.02.02-cms-2
rpm install failed! Installation aborted!
Not very encouraging.Perhaps I should read the XCMSI manual!
Apparently what you do , is creating a copy of all rpm on your desktop in the directory DVD_x_y.Then this copy is used by the Perl program to install the software in VO_CMS_SW_DIR/cms/Releases.
I try again after a few days. After many hours of trying to fix the problem by hand, I decide to proceed gradually installing first IGUANA.IGUANA_5_1_1 is installed almost without problems. I don't understand the difference between "Start" and "Update". Here is the procedure used: I install in the same way COBRA_7_8_6. Although I get a message "rpm install failed! Installation aborted!" COBRA seems to have been installed correctly :i.e. "scram list" gives it installed.ORCA_8_3_0 installed (same error message) but " ExRunEvent" working without problems! Ditto for OSCAR_3_3_1.Now let's try again IGUANACMS_1_10_0. Guess it: I got the same error of the other day:
error: failed dependencies:
        LCG.root-rh73_gcc32-3.10.02-1 = cms is needed by CMS.pax-rh73_gcc32-1.02.02-cms-2
        LCG.rootcore-rh73_gcc32-3.10.02-1 = cms is needed by CMS.pax-rh73_gcc32-1.02.02-cms-2
rpm install failed! Installation aborted!
It's time to send some mail around!The first tip is to add "--nodeps" to the install options (since the problems seems only to be the misnaming of dependencies in a package).This is done clicking on "Options". I try again and ,apart from the usual last message, IGUANACMS is installed! It works! Total time elapsed:around 2 days. Not so bad!

Running the CMS Helloworld on one hundred computers all around the world

[Added February 2005] This is getting like a blog, so from now on I'll add the date the item was written.
By now you should know what is the CMS "Helloworld": it is the famous ExRunEvent in module Workspace. This program doesn't do nothing useful but reading input events and giving a summary of how many they were.In principle you can use it as a template to write more interesting programs but this is not straightforward since you must know the CMS data model! Anyhow we would like to run this program on the Grid. But before doing this we review briefly how to run it on your desktop. To run it in local , you must have access to some datasets accessible with rfio. In .orcarc you specify the Pool catalogue for the dataset:
InputFileCatalogURL = @{xmlcatalog_http://webcms.ba.infn.it/cms-software/orca/hg03_hzz_2e2mu_130a_rfio.xml}@
and the Input Collection
InputCollections = /System/hg_2x1033PU761_TkMu_g133_CMS/hg03_hzz_2e2mu_130a/hg03_hzz_2e2mu_130a

Now we run ExRunEvent on the Grid: The following steps are very well documented and are needed to be done only once.

Now you can give the command (always on the UI):
grid-proxy-init
that will enable you to use the grid for 12 hours.
Now you can try all the commands described in the LCG-2 User Guide. For example executing some command on another Grid computer:
globus-job-run gridba2.ba.infn.it /bin/hostname
To run our Helloworld on the Grid we must write a file in a language called jdl (job description language) and specify which program we must run , the input files, the output files, etc.. and then send this file to the Grid. Not easy for a newby. So I'll use the tool CRAB that will do everything for you. First of all you download CRAB using CVS. Then you have to modify the CRAB file crab.cfg The program needs only the name "ExRunEvent" but you must have before done a
eval `scram runtime -csh`
in the correct directory (i.e. the program will use the environment variables set by SCRAM to get everything).
The program needs also a copy of ".orcarc" To create and send your first 2 jobs to the Grid now you write:
./crab.py -bunch_creation 2 -bunch_submission 2
To check job status:
edg-job-status -i Jobs/log/submission_id.log

Let's start again from EDM!

Up to now changes in CMS software have been relatively small. The change from Objectivity to POOL federations has been gradual and in some way transparent to an end user like me , because I was always using COBRA the CMS framework. But now that's a BIG change! Let's rewrite the CMS framework. Forget COBRA, start using EDM! Well not really, since ,if we drop Cobra now, we have to stop everything. Let's say, for sometime (hopefully a few months, but who knows?) we have to provide two versions of each CMS application, one for Cobra, the other for EDM. Wow, that's something! It's interesting to know the reasons for such rewriting. I'll paste some citations: New acronyms:CMSSW contains the new software.

Online(Almost)

Proper data taking will start only in 2007, but we have to get ready! So I have started experimenting with what online access to CMS data could be. I am interested in tracker monitoring so the proper place for me to get data is the so called Filter Farm. A kind of computer cluster of Filter Units that make possible access to raw data to be used for data quality monitoring(DQM. Filter Farm, FU, DQM a whole new bunch of acronyms to learn. However , considering the complexity behind it, Physics and Data Quality Monitoring infrastructure is really simple. It is based on a three tiered architecture with a Collector that receives data from many hardware and software Sources and makes them available to many Clients. Collector, Source (this should be a FU during data taking) and Client can run on different computers.The basic unit handled is a Monitoring Element (which corresponds more or less to a single online histogram). Monitoring Elements are served by sources in a tree: the Client will build also its tree of ME by registering those ME in which is interested.Easy piece...
That's refreshing after all the obscurities of the so called "CMS event data model" at least before EDM! Now , what kind of software you run on a DQM application? Exactly the same that you run offline:i.e. Orca. The new software layer added for online called COSINE has the only purpose to make Orca applications also run on online data. For this reason most monitoring software is part of ORCA and also (but this only momentarily) of COBRA (Module DaqPrototype). That's also something very good for the poor user like me. But let's try to put the concept to work:

DQM Version v0.0.40: Based on XDAQ_3_1, ROOT v4.04.02, COSINE_2_0_1_pre3
I run everything on a single computer to make more easy the installation. (The automatic installation suggested in the guide doesn't work for me: so I do everything manually). Very nice, but now I want to build a scatter plot of all simhits in the Tracker. Of course now I don't need to start from scratch.I open the 3 windows on the same computer and start the collector and the client on two of them with:
gocosine;eval`scramv1 run csh`;HistoServer;
gocosine;eval`scramv1 run csh`;testClient;
For the server I proceed in the following way:my original program runs in Orca in "ORCA/Tracker/SiPixelDet/test". But , remember, COSINE replaces ORCA: so I start by committing Tracker/SiPixelDet in the directory COSINE_2_0_1_pre3/src. My program is called BuildMap and I have to do some small changes in order to run it under COSINE:
//added following include
#include "SubfarmManager/RootMonitorThread/interface/RootMonitorThread.h"
#include "DaqPrototype/DaqMonitor/interface/MonitorElement.h"
#include "DaqPrototype/DaqMonitorRoot/interface/DaqMonitorROOTBackEnd.h"

//Before starting analysis,instead of histogram booking:
if(firstevt){
   firstevt=false;
 // default source name
  string sfuname = "FU0";
  // default collector host name
  string hostname = "localhost";
  // default monitoring period (microsecs)
  int period = 1000000;
  // default # of monitoring cycles
  //unsigned int n_cycles = 20000;

  cout << " Source " << sfuname << " begins sending monitoring to host " <<
    hostname << "\n with period " << period << " microsecs" << endl;

  RootMonitorThread *od =
    new RootMonitorThread(hostname, 9090, period, sfuname);

  // start back-end interface instance
  DaqMonitorBEInterface *dbe =  DaqMonitorROOTBackEnd::instance();

   dbe->setCurrentFolder("C1");
   count = dbe->book2D("histo1", "Count ",
                                    NBINS, 0, float (NBINS), NBINS1, 0.0, NBINS1);
   total = dbe->book2D("histo2", "Total",
                                    NBINS, 0, float (NBINS), NBINS1, 0.0, NBINS1);
  dbe->showDirStructure();
  od->release();
}

//This code replaces histogram filling
   count->Fill(idLayer+1,idModule+1);
   total->Fill(idLayer+1,idModule+1,simHitsSize);
//We add also this call to avoid data lost because the data is sent too fast:
      usleep(1000); // this is 1 ms
We compile the program and run it like we did with Orca. But now the data is automatically collected from the collector. The client doesn't need any modification since it subscribes all data from the collector. Now the result is having the scatter plots saved from the client. It is a complex way to do an histogram but the server is just simulating online data taking(well online we don't have simhits: but here we would like only to see how it works).

The last word

Just for fun this is a document assembled with citations from CMS pages.
Page author Giuseppe Zito: zito@ba.infn.it
Last update: