Package: titania
TitaniaThis is framework made for VELO LHCb data visualization.
It's made to be fully customizable.Titania on PyHEP:
(See video below)InstallationYou should start with downloading Titania framework through pip:(recommended)pip install git+https://gitlab.cern.ch/velo-calibration-software/titaniaor withpip install titaniaDevelopment installationgitclonehttps://gitlab.cern.ch/velo-calibration-software/titaniacdtitania
pipinstall-rrequirements.txtStarting projectWhen you are ready to create skeleton for your monitoring project with command:python -m titania start --name NAMEREMEMBER TO REPLACE "NAME" WITH YOUR APPLICATION NAMENow you are ready to go! Look forQuick Guideto learn how to use this framework.Running testsTo run tests from CI sometimes it is needed to add:set PYTHONPATH=%PYTHONPATH%;src;testsRun projectFrom main application folder u can run this script:python main.pyfirst you need to fill your main(look in our examples)Quick Guide:Ok, so lets say that you want add new tab to the your titania project:Right here:First: Defining dataThats very easy step. We store data related code atdatamodule. You can find some implementations in framework core.
If the thing that you are looking for is not there, you should add your own class there.
That is extendingTitaniaDataInterfaceand putting it indatafolder. It is verysimple.
The only requirements are that your class havefetch()method, that returns the actual data.
Lets implement it with an example:importrandomfromtitania.data.data_coreimportLovellDataInterfaceclassRandomNList(LovellDataInterface):def__init__(self,n=10):self.n=ndeffetch(self):return[random.random()foriinrange(self.n)]And that's it!
(TheRandomNListclass can be found in packagetitania.data)Creating the PlotWe need something that we want to look at, we can easilly implement some kind of plot by extendingMplPlot.
This class usesMatplotlibfor plotting.
(If you would like to use any other plotting framework, you must at least extendPlotInterfaceclass.)fromtitania.plots.base_plotimportMplPlotclassOurPlot(MplPlot):defdraw_plot(self):ax=self.figure.add_subplot()ax.plot(self.view.data.fetch())self.draw()Very simple, we inherit from that class, and we only need to definedraw_plot.
We already haveself.figureas matplotlib object, as a property of MplPlot class.
We can save this as a python file inplotmodule.##Part three, the prestige: Implementation of tabCreating new python fileWe will create exemplary plot.
We will create file calledexemplary_gui.py, and put it in views -> VELOView -> Exemplary -> exemplary_gui.py
Notice, that theExemplaryfolder doesnot exist, yet.
This is because we are structuring the files used to create tabs, in similar way that we structure tabs themselves.
You can look around inviewsfolder to see that this is true.
Although this is not necessary, this is the convention that we choose.Writing codeNow, we will create minimal implementation for new tab, line by line.Tab classfromtitania.QtGUIimportSimpleTabclassExemplary(SimpleTab):passFirst we create tab class, in this case calledExemplary.
All of the tab implementations need to implement at least classQtTabInterface.
This interface requires the following components:dataargument in constructor, as in__init__(self, data). This object must inherit from LovellDataInterface.plot_panel_grid- assigned in constructorlineLayout- assigned in constructorgrid_layout- assigned in constructorMethodcreate_control_panel- that creates panel for the tabMethodset_title- that returns the string with the name of the tab.Methodinitiate- that is runned after the creation of tab object, when we want to draw it on gui.
But our class is using sub-class that is already implementingTheQtTabInterfaceclass is inherited bySimpleTab,QtBaseLayoutTab,QtPlotTab.
In most of the cases you should use them instead of inheriting directly fromQtTabInterface.The recommended way is by subclassingQtBaseLayoutTab.The minimal requirements for inheriting fromQtBaseLayoutTabare as follows:callQtBaseLayoutTabconstructor withdataargumentimplement methodset_titleimplement methodcreate_control_panelimplement methodset_plotLets go back to our exampleDatafromtitania.QtGUIimportQtBaseLayoutTabfromtitania.data.data_coreimportEmptyLovellDataclassExemplary(QtBaseLayoutTab):def__init__(self,parent=None):QtBaseLayoutTab.__init__(self,data=EmptyLovellData(),parent=parent)We addedEmptyLovellDatato the call of the constructor.
The data object must inherit fromLovellDataInterface.
This interface only requirec implementation offetch()method, that will return data.NameNext we add the name of the tab, by implementing methodget_title.defget_title(self):return"example"control panelWe add control panel, that we will use to navigate through the data.defcreate_control_panel(self):returnEmptyControlPanel()For now we leave that empty, withEmptyControlPanel.PlottingNow we must defineset_plot. It must return object that InheritsPlotInterface. But we can also use partially implementedSimplePlotthat inherits from that interface.defset_plot(self):returnOurPlot(view=self)It all comes togetherFinally your file should look something like this:fromtitania.QtGUIimportQtBaseLayoutTabfromtitania.panels.main_control_panelimportEmptyControlPanelfromtitania.data.exemplary_generated_dataimportRandomNListfromtitania.plots.our_plotimportOurPlotclassExemplary(QtBaseLayoutTab):def__init__(self,parent=None):QtBaseLayoutTab.__init__(self,data=RandomNList(),parent=parent)defget_title(self):return"example"defcreate_control_panel(self):returnEmptyControlPanel()defset_plot(self):returnOurPlot(view=self)Save it in the file described in previous section.Now run your application. Can you see the new Tab? Probably not, because we are missing one key factor.We need to add this class to the configuration.Configuration fileOpen up file Config -> config.py.You can probably see something like thisfromview.VELOView.AreaPlotTestTab.stacked_area_plot_guiimportStackedAreaTestTab# ...# (Long list of imports)# ...config={"VELOView":[ThresholdsTab,BoxPlotTestTab,StackedAreaTestTab,ScatterWithHistogramPlotTestTab,ScatterPlotTestTab,CountPlotTestTab],"RUNView":[PedestalsPlot,AnotherThresholdsPlot,PedestalsSingleMatrixPlot]}This is the actual place whichdecides about the tabs placement.
So add line that imports the created class, and add it to the list, like this:fromview.VELOView.AreaPlotTestTab.stacked_area_plot_guiimportStackedAreaTestTab# ...# (Long list of imports)# ...fromview.VELOView.ExemplaryPlotTab.exemplary_guiimportExemplaryconfig={"VELOView":[ThresholdsTab,BoxPlotTestTab,StackedAreaTestTab,ScatterWithHistogramPlotTestTab,ScatterPlotTestTab,CountPlotTestTab,Exemplary],"RUNView":[PedestalsPlot,AnotherThresholdsPlot,PedestalsSingleMatrixPlot]}Now when you run your application you should be able to see your tab.Of course, everything is empty. But now, with all of the knowledge that you gained, it should be easy for you to implement anything that you want to view here.New plot typeIf you would like to create new plot, the easiest way is to inherit fromSimplePlotclass, and reimplementdraw_plotmethod.Remember to use self.view.data.fetch() to get data!Then you can return your new plot object inset_plotmethod in your tab.
Take a look at GUIWidget -> PlotWindow -> Plot to get inspiration.