luaXroot is combining the classic Lua interpreter with the ROOT interpreter.
In practice, it translates for the end user into something which looks very similar to the Lua console command interpreter.
It has exactly the same functionalities: you can type commands that will be interpreter in real time, load libraries, execute scripts...
But in the background, a ROOT TApplication is running. It controls all the display functionalities and is called each time a histogram or a graph needs to be drawn or updated, but also when the user interacts with the TCanvas to zoom in or out, change the binning, or simply move the mouse over the canvas...
Index of the Functionalities section:
The TApplication
The userlogon.lua
Helper functions
Lua "classes" implementation
More about the userdata type
userdata as substitutes to C++ classes
Editing existing Lua classes with AddPostInit
Derived classes
System calls binding
Inter-Process Communication
The ROOT binders
Adding custom classes
The TApplication (theApp)
Only one instance of the TApplication can run for one instance of luaXroot. It is started on a concurrent thread when luaXroot launched.
A set of messages and mutexes are put in place to ensure that the user's action in the Lua command interpreter won't interfere with an action the TApplication is currently
resolving, effectively putting action requests in a queue until they can be resolved.
This TApplication instance can be accessed through calls to theApp either from the Lua command interpreter or from scripts loaded later. You should though never have to call it
except for occasional request to manually *Update* the status of the TApplication instance. Basically leave that alone if you are not totally sure that you absolutely need to interact with it.
The userlogon.lua
When starting luaXroot a bunch of scripts are loaded, the main one being luaXrootlogon.lua
The core modules are loaded via calls to require in this luaXrootlogon.lua script, as well as some general functions.
At the very end of the loading process, a call to require("userlogon.lua") is made. If such a script is found in the "user" folder of the luaXroot repository
(it should exist at the first place but be empty save for a few line of comments. If not it is safe to create it) it is then loaded. this "user/userlogon.lua" is where the user will want to put
any additional module that he/she would want to load at startup. Bear in mind these modules will be loaded last.
Helper functions
A set of helper function to make the user's life simpler are provided. These functions goes from simple macros to more complex and effective tools.
These functions are documented in this section.
Lua "classes" implementation
Lua doesn't have classes (C++) nor a notion of struct (C). Instead it uses tables to store data of different types inside a unique container. But unlike a C struct, Lua tables are dynamic. Objects
can be added or removed from them at anytime.
Concerning table, there is no direct comparison possible. Tables don't offer inheritence nor a direct way to create object from them or call methods. A similar behavior can be achieved though using
a specific type of tables: metatables.
For simplicity sake, let's consider the metatables as the table that will contain our "class" methods and members. They can be used to achieve something similar to what C++ classes do and we won't go
into the details of their implementation here as it is not relevant to the end user. For more information: luaXroot "class" implementation is based on the
model presented here.
As explained previously, userdata are a special type of variables. They are links to C pointer and allow the user to manipulate any type of object. To be able to do anything meanigful, binders have to be created beforehands. This subject is discussed in this section.
System calls binding
Though most system calls could be done through an os.execute([insert system call]) here, some of them cannot and it is sometime more convenient to have binder to Lua functions for them.
Please note that I abusively use the term system call for some functions but decided to group them with the actual system calls due to the type of operations they perform.
These function are documented in this section and include calls such as open, close, getenv, fork, ftruncate, pipe, ...
Inter-Process Communication (IPC)
Most of the tools which allows 2 different processes to communicate together (either on the same machine or on 2 separate machines, over LAN or WAN) are described in this section.
It includes message queues, semaphores, shared memory, memory mapped files and sockets.
The ROOT binders
As you probably guessed from the previous paragraphs, direct calls to C or C++ functions are not how Lua works. It goes the same with all the ROOT functionalities and classes.
Binders to the most useful classes are provided and documented here.
It includes
- TFile
- TF1
- TGraphErrors (TGraph is treated as a TGraphErrors in luaXroot)
- TH1D (all 1D histograms are treated as TH1D in luaXroot)
- TH2D (all 2D histograms are treated as TH2D in luaXroot)
- TSpectrum
- TCutG (to make graphical selection on graphs)
Adding custom classes
This is an advanced topic and is treated in details here.
Tools, helper and wrapper functions are provided to make the process of adding custom classes and interacting with them in Lua as streamlined as possible. A base class LuaUserClass
is provided and any custom class should inherit from it to be able to benefit from these helpful tools.