Operate with DccTables

The main goal for dccQuantities is to allow operating over the tables that contain the data of the DCC file. This section explain some basic cases to operate with already existing data.

Reading a table

The first step is always to obtain the table from the file. dccQuantities allows reading valid tables from any XML file, which they don't need to be a complete and valid DCC file. The data of each table is extractable using the extract_dcc_elements(...) function, which returns a list of all the tables' data (as a python dictionary) contained within the file.

from dcc_quantities import DccQuantityTable, extract_dcc_tables

listed_dcc_tables = extract_dcc_tables("path/to/tables_data.xml")
first_table = DccQuantityTable.from_dcc_data(listed_dcc_tables[0])
last_table = DccQuantityTable.from_dcc_data(listed_dcc_tables[-1])

The class method DccQuantityTable.from_dcc_data(...) initializes and returns the correct type (either Flat- or Long-Table) for the table based on the provided data.

Hint

Creating a table from raw data is also possible, but is a more complex case. See DccQuantities_examples.ipynb for more complex examples (in a Jupyter Notebook) where this case is included.

The DCC tables are defined by DccQuantityType instances, where each one defines a column of the table. Quantities are mainly defined by their name, unit and values, but dccQuantities adds one more layer defining a unique ID (or UUID) for every element in the table. Specific quantities can be extracted from any table by providing this UUID.

from dcc_quantities import DccLongTable, DccQuantityType

table: DccLongTable
frequency_uuid: str

frequency_quantity: DccQuantityType = table[frequency_uuid]

However, to extract the quantity is required to know its UUID. While there might be cases where this ID is known, the most common case is where this is unknown. For that reason, DccQuantityTables allow searching for these UUID based either in the name, unit or refType:

from dcc_quantities import DccLongTable, DccQuantityType

table: DccLongTable

frequency_uuid: str = table.get_quantity_ids_by_field("name", "Frequency")
frequency_quantity: DccQuantityType = table[frequency_uuid]

Slicing tables

There are cases where the goal is to obtain a sub-table from the original, where all rows were selected based on the values of their quantities. This is possible by following two steps:

  1. Obtaining a numpy.ndarray[bool] which defines de positions in the table (with boolean True) that are interesting for our subtable.
  2. Providing the array to the original table to obtain a new subtable.

To obtain the array of booleans, all tables instances in dccQuantities provide a .where(...) method to extract the conditions based on the values and uncertainties of a single quantity (which is defined by its UUID).

from dcc_quantities import DccLongTable, DccQuantityType

table: DccLongTable
frequency_uuid: str = table.get_quantity_ids_by_field("name", "Frequency")

condition_array = table.where(
    lambda x, u: (x > 50) & (x < 1_000) & (u > 0.002),
    ref_uuid=frequency_uuid,
)

At the example code before, the condition is defined by a lambda function over the "Frequency" quantity. The condition is defined as the union1 of both:

  • All the positions where the quantity value x is greater than 50 and lower than 1000.
  • All the position where the quantity uncertainty u is greater than 0.002.

To obtain condition arrays over multiple quantities is required to obtain those conditions per quantity, then create a single condition array among all arrays:

frequency_condition = table.where(
    lambda x, u: (x > 50) & (x < 1_000) & (u > 0.002),
    ref_uuid=frequency_uuid,
)
accel_condition = table.where(
    # Recommendation: Use epsilon comparison instead of `==` due to the float point error.
    lambda x, _: (abs(x - 0.35) < 1e-6), 
    ref_uuid=acceleration_uuid,
)
condition_array = frequency_condition | accel_condition

Once the condition array is well-defined, it can be parsed directly to the table to obtain a sub-table2.

subtable = table[condition_array]

Warning

After obtaining a subtable, all instances composing the subtable will have different UUIDs. In other words, even if the information is shared dccQuantities defines all instances from new sub-tables as new and different instances thant the ones at the original table.

Hint

  1. The operations among conditions are defined with the bit operators:
    • & for AND operations.
    • | for OR operations.
    • ^ for XOR operations.
    • ~ for NOT operations.
  2. Obtaining a sub-table through slices as table[5:10] is also possible, but it is recommended to always use conditional arrays of booleans.