Implementig checkers

Dear all,

I am currently trying to implement checkers for the QC. I am using source and header skeleton files available in QC. I have a working checker now but we came upon a more software engineering related question.

Right now the QC checker is able to get chosen monitor objects from chosen QC Task. If only one monitoring object is passed the function beautify() is triggered and the histogram can be modified (text added, colors changed, etc.). If more than one monitoring objects is passed, the beautify() function is not triggered.

I am working on TPC QC and currently we have implemented the QC task which has a vector of histograms as a monitor object instead of each histogram being a separate monitor object. I tested, and we can still pass the separate histograms in json file, but the checker sees the number of passed objects as the length of the vector. Which means that the beautify() is never triggered even if we pass only one histogram from the vector.

So the questions:

  1. We would like to keep the QC structure as we have it now. Our argument is that if we have for example multiple histograms important for the PID, it is better to just always have them in one vector. Is this fine or was the software developed for the usage when one QC task has only separate histograms as monitoring objects and not a vector of them?
  2. If having the vector would not cause any additional problems in further development and we decide to develop all our tasks like this, how should we solve the beautify() function problem? We would actually prefer to do all checks for one QC tasks in one QC checker, just looping over the histograms. But to change the histograms, we would have to call the beautify() function from check() function. Is this ok for the framework or not, as it is not the intended use?

best
Laura

Hello Laura,
We have recently reworked the relationship between Checks and Monitor Objects (MOs), which allows for more flexibility now, but we might have overlooked some corner cases and this is probably one of them.
As far as I remember, the idea was that an MO shouldn’t be beautified in more than one CheckRunner (a process running Checks), so we don’t end up with more than one version of an MO. I agree that a limitation of having 1 MO per Check to beautify it is probably too strict and we should revisit it. I will have a closer look in the coming days and we will discuss it with @bvonhall when he’s back from holidays next week.

However, I am wondering how do you arrange your MOs in vectors. These are TCollections? I am surprised how come your vectors are still seen as multiple histograms. Do you have perhaps your code in some branch on Github, so I could have a look?

Answering your questions:

  1. A possible drawback of storing multiple histograms in one vector is that you wouldn’t be able to inspect them in QCG (QC GUI). However, if you name them “PID/myfirstobject”, “PID/mysecondobject” and so on, that should arrange them properly in the objects tree (I haven’t tried myself though). Then you should be able to keep your structure. Alternatively, you can assign them some metadata, for example “type” : “PID”. So personally, I would avoid storing them in vectors, unless strongly justified. That being said, I would like to see how do you actually do that, if possible.
  2. We will try to lift that limitation as high as possible without getting into dangerous situations. Calling beautify() from check() is not an intended use. However, it should work if QC generates only CheckRunner in your workflow. So, for the time being you might want to use it for development, but it is surely to be avoided in the production code.

Cheers,
Piotr

Dear Piotr,

my assumption that the checker sees the number of all published objects was based on a fact that the checker device output says “Running 1 checks for 6 monitor objects” (6 objects is how many histograms we have) and the beautify() function is never triggered.

We looked at our implementation and even though we store the histograms in a vector, we publish them separately one by one. So now I have another question - how is actually the data transfered from the QC task to the QC checker? So for example, when I write in json file:

"dataSource": [{
          "type": "Task",
          "name": "TPCQCPID",
          "MOs": "all"
        }]

What is seen as MOs? All objects published by the TPCQCPID task? Or some data members of the task? Or?

Answering to your questions, I pushed my latest code to:

My checker is in QualityControl/Modules/TPC include and src directories called LauraCheck.*
The right json file is tpcQCPIDChecker.json.

The TPCQCPID task is implemented in the same location, files called PID.*
The files used in the QC PID task from O2, you can find in O2/Detectors/TPC/qc. As before, the files are called PID.* This is already in the central O2 repository, so you should have it as well.

To run the same workflow as mine:
o2-qc-run-tpctrackreader | o2-qc --config json://YOURDIRECTORY/QualityControl/Modules/TPC/run/tpcQCPIDChecker.json

And thanks for such a fast response!
Cheers
Laura

Dear Laura,

We looked at our implementation and even though we store the histograms in a vector, we publish them separately one by one.

Then this is why you are seeing them as separate objects. There is nothing wrong with keeping your objects in a vector and using startPublishing() on each of them separately, as you are doing now.

So now I have another question - how is actually the data transfered from the QC task to the QC checker?

All the MOs are sent to CheckRunners in a TObjArray, which is unpacked upon reception. That an internal detail of the framework and you won’t see a TObjArray from your Checks (you see a map instead).

What is seen as MOs? All objects published by the TPCQCPID task? Or some data members of the task? Or?

It is everything that you register as an MO in this task by using startPublishing().

I hope that helps. I will try to improve some log messages, so it is more clear what is happening.
Cheers,
Piotr