atoti package

Module contents

atoti.at(measure, coordinates)

Return a measure equal to the passed measure at some other coordinates of the cube.

Parameters
  • measure (Measure) – The measure to take at other coordinates.

  • coordinates (Mapping[Level, Any]) –

    A {level_to shift_on: value_to_shift_to} mapping. Values can either be:

    • A literal matching an existing member of the key level:

      # Return the value of Quantity for France on each member of the Country level.
      atoti.at(m["Quantity"], {lvl["Country"]: "France"})
      
    • Another level whose current member the key level will be shifted to:

      # Return the value of Quantity for the current member
      # of the Target Country and Target City levels.
      atoti.at(m["Quantity"], {
          lvl["Country"]: lvl["Target Country"],
          lvl["City"]: lvl["Target City"],
      })
      

      If this other level is not expressed, the shifting will not be done.

atoti.copy_tutorial(path)

Copy the tutorial files to the given path.

atoti.create_session(self, name='Unnamed', *, config=None, **kwargs)

Create a session.

Parameters
  • name (str) – The name of the session.

  • config (Union[SessionConfiguration, Path, str, None]) –

    The session configuration regrouping all the aspects of the session that might change dependending on where it is deployed. It can be passed either as:

    • A Python object created with atoti.config.create_config().

    • A path to a YAML file, enabling the config to be changed without modifying the project’s code. Environment variables can be referenced (even recursively) in this file:

      >>> yaml_config = '''
      ... url_pattern: ${{ env.SOME_ENVIRONMENT_VARIABLE }}
      ... '''
      

Return type

Session

atoti.date_diff(from_date, to_date, *, unit='days')

Return a measure equal to the difference between two dates.

If one of the date is N/A then None is returned.

Parameters
  • from_date (Union[Measure, MeasureConvertible, date, datetime]) – The first date measure or object.

  • to_date (Union[Measure, MeasureConvertible, date, datetime]) – The second date measure or object.

  • unit (Literal[‘seconds’, ‘minutes’, ‘hours’, ‘days’, ‘weeks’, ‘months’, ‘years’]) – The difference unit. Seconds, minutes and hours are only allowed if the dates contain time information.

Example

>>> df = pd.DataFrame(
...     columns=["From", "To"],
...     data=[
...         ("2020-01-01", "2020-01-02"),
...         ("2020-02-01", "2020-02-21"),
...         ("2020-03-20", None),
...         ("2020-05-15", "2020-04-15"),
...     ],
... )
>>> store = session.read_pandas(
...     df,
...     store_name="date_diff example",
...     types={
...         "From": tt.type.LOCAL_DATE,
...         "To": tt.type.local_date("yyyy-MM-dd", nullable=True),
...     },
... )
>>> cube = session.create_cube(store)
>>> lvl, m = cube.levels, cube.measures
>>> m["Diff"] = tt.date_diff(lvl["From"], lvl["To"])
>>> cube.query(
...     m["Diff"], m["contributors.COUNT"], levels=[lvl["From"], lvl["To"]]
... )
                      Diff contributors.COUNT
From       To
2020-01-01 2020-01-02    1                  1
2020-02-01 2020-02-21   20                  1
2020-03-20 N/A                              1
2020-05-15 2020-04-15  -30                  1
Return type

Measure

atoti.date_shift(measure, on, offset, *, method='exact')

Return a measure equal to the passed mesure shifted to another date.

Parameters
  • measure (Measure) – The measure to shift.

  • on (Hierarchy) – The hierarchy to shift on. Only hierarchies with a single level of type date (or datetime) are supported. If one of the member of the hierarchy is N/A their shifted value will always be None.

  • offset (str) – The offset of the form xxDxxWxxMxxQxxY to shift by. Only the D, W, M, Q, and Y offset aliases are supported. Offset aliases have the same meaning as Pandas’.

  • method (Literal[‘exact’, ‘previous’, ‘following’, ‘interpolate’]) –

    Determine the value to use when there is no member at the shifted date:

    • exact: None.

    • previous: Value at the previous existing date.

    • following: Value at the following existing date.

    • interpolate: Linear interpolation of the values at the previous and following existing dates:

      Example:

      m2 = atoti.date_shift("m1", on=h["date"], offset="1M", method="interpolate")
      

      date

      m1

      m2

      explanation

      2000-01-05

      15

      10.79

      linear interpolation of 2000-02-03’s 10 and 2000-03-03’s 21 for 2000-02-05

      2000-02-03

      10

      21

      exact match at 2000-03-03: no need to interpolate

      2000-03-03

      21

      9.73

      linear interpolation of 2000-03-03’s 21 and 2000-04-05’s 9 for 2000-04-03

      2000-04-05

      9

      no record after 2000-04-05: cannot interpolate

Return type

Measure

atoti.filter(measure, condition)

Return a filtered measure.

The new measure is equal to the passed one where the condition is True and to None elsewhere.

Different types of conditions are supported:

  • Levels compared to literals of the same type:

    lvl["city"] == "Paris"
    lvl["date"] > datetime.date(2020,1,1)
    lvl["age"] <= 18
    
  • A conjunction of conditions using the & operator:

    (lvl["source"] == lvl["destination"]) & (lvl["city"] == "Paris")
    
Parameters
Return type

Measure

atoti.open_query_session(self, url, name=None, *, auth=None)

Open an existing session to query it.

This can be used to connect to:

  • Other sessions with another atoti process.

  • ActivePivot cubes built with a classic Java project, if version >= 5.7.0.

Parameters
Return type

QuerySession

atoti.parent_value(measure, on, *, apply_filters=False, total_value=None, degrees=None)

Return a measure equal to the passed measure at the parent member on the given hierarchies.

Example

Measure definitions:

m1 = parent_value(m["Quantity.SUM"], h["Date"]) = parent_value(m["Quantity.SUM"], h["Date"], degrees={h["Date"]: 1})
m2 = parent_value(m["Quantity.SUM"], h["Date"], degrees={h["Date"]: 3})
m3 = parent_value(m["Quantity.SUM"], h["Date"], degrees={h["Date"]: 3}, total_value=m["Quantity.SUM"]))
m4 = parent_value(m["Quantity.SUM"], h["Date"], degrees={h["Date"]: 3}, total_value=m["Other.SUM"]))

Considering a non slicing hierarchy Date with three levels Years, Month and Day:

Year

Month

Day

Quantity.SUM

Other.SUM

m1

m2

m3

m4

2019

75

1000

110

null

110

1500

7

35

750

75

null

110

1500

1

15

245

35

110

110

110

2

20

505

35

110

110

110

6

40

250

75

null

110

1500

1

25

115

40

110

110

110

2

15

135

40

110

110

110

2018

35

500

110

null

110

1500

7

15

200

35

null

110

1500

1

5

55

15

110

110

110

2

10

145

15

110

110

110

6

20

300

35

null

110

1500

1

15

145

20

110

110

110

2

5

155

20

110

110

110

Considering a slicing hierarchy Date with three levels Years, Month and Day:

Year

Month

Day

Quantity.SUM

Other.SUM

m1

m2

m3

m4

2019

75

1000

75

null

75

1000

7

35

750

75

null

75

1000

1

15

245

35

75

75

75

2

20

505

35

75

75

75

6

40

250

75

null

75

1000

1

25

115

40

75

75

75

2

15

135

40

75

75

75

2018

35

500

35

null

35

500

7

15

200

35

null

35

500

1

5

55

15

35

35

35

2

10

145

15

35

35

35

6

20

300

35

null

35

500

1

15

145

20

35

35

35

2

5

155

20

35

35

35

Parameters

See also

atoti.total() to take the value at the top level member on each given hierarchy.

Return type

Measure

atoti.rank(measure, hierarchy, ascending=True, apply_filters=True)

Return a measure equal to the rank of a hierarchy’s members according to a reference measure.

Members with equal values are further ranked using the level comparator.

Example:

m2 = atoti.rank(m1, hierarchy["date"])

Year

Month

Day

m1

m2

Comments

2000

90

1

01

25

2

01

15

1

02

10

2

02

50

1

01

30

1

same value as 2000/02/05 but this member comes first

03

20

3

05

30

2

same value as 2000/02/01 but this member comes last

04

15

3

05

5

2

05

10

1

Parameters
  • measure (Measure) – The measure on which the ranking is done.

  • hierarchy (Hierarchy) – The hierarchy containing the members to rank.

  • ascending (bool) – When set to False, the 1st place goes to the member with greatest value.

  • apply_filters (bool) – When True, query filters will be applied before ranking members. When False, query filters will be applied after the ranking, resulting in “holes” in the ranks.

Return type

Measure

atoti.shift(measure, on, *, offset=1)

Return a measure equal to the passed measure shifted to another member.

Parameters
  • measure (Measure) – The measure to shift.

  • on (Level) – The level to shift on.

  • offset (int) – The amount of members to shift by.

Return type

Measure

atoti.total(measure, *hierarchies)

Return a measure equal to the passed measure at the top level member on each given hierarchy.

It ignores the filters on this hierarchy.

If the hierarchy is not slicing, total is equal to the value for all the members. If the hierarchy is slicing, total is equal to the value on the first level.

Example

Considering a hierarchy Date with three levels Year, Month and Day. In the first case Date is not slicing. In the second case Date is slicing.

Year

Month

Day

Price

total(Price) NON SLICING

total(Price) SLICING

2019

75.0

110.0

75.0

7

35.0

110.0

75.0

1

15.0

110.0

75.0

2

20.0

110.0

75.0

6

40.0

110.0

75.0

1

25.0

110.0

75.0

2

15.0

110.0

75.0

2018

35.0

110.0

35.0

7

15.0

110.0

35.0

1

5.0

110.0

35.0

2

10.0

110.0

35.0

6

20.0

110.0

35.0

1

15.0

110.0

35.0

2

5.0

110.0

35.0

Parameters
  • measure (Measure) – The measure to take the total of.

  • hierarchies (Hierarchy) – The hierarchies on which to find the top-level member.

Return type

Measure

atoti.value(column, *, levels=None)

Return a measure equal to the value of the given store column.

Parameters
  • column (Column) – The store column to get the value from.

  • levels (Optional[Collection[Level]]) –

    The levels that must be expressed for this measure to possibly be non-null.

    When None, the measure will also be None if the levels corresponding to the keys of column’s store are not expressed.

    Passing an empty collection propagate the value on all levels when possible.

Example

>>> df = pd.DataFrame(
...     columns=["Month", "City", "Product", "Price"],
...     data=[
...         ("January", "Manchester", "Pretzel", 10.0),
...         ("January", "London", "Pretzel", 10.0),
...         ("January", "London", "Burger", 10.0),
...         ("March", "New York", "Pretzel", 10.0),
...         ("March", "New York", "Burger", 8.0),
...     ],
... )
>>> store = session.read_pandas(
...     df, keys=["Month", "City", "Product"], store_name="value example"
... )
>>> cube = session.create_cube(store)
>>> lvl, m = cube.levels, cube.measures
>>> m["Product Price"] = tt.value(store["Price"])

By default, the values do not propagate:

>>> cube.query(
...     m["Product Price"],
...     m["contributors.COUNT"],
...     include_totals=True,
...     levels=[lvl["Month"], lvl["City"], lvl["Product"]],
... )
                           Product Price contributors.COUNT
Month   City       Product
Total                                                     5
January                                                   3
        London                                            2
                   Burger          10.00                  1
                   Pretzel         10.00                  1
        Manchester                                        1
                   Pretzel         10.00                  1
March                                                     2
        New York                                          2
                   Burger           8.00                  1
                   Pretzel         10.00                  1

To propagate the values to the City level, the measure can instead be defined as follows:

>>> m["Product Price"] = tt.value(store["Price"], levels=[lvl["City"]])

With this definition, if all products of a city share the same price, then the city inherits that price:

>>> cube.query(
...     m["Product Price"],
...     m["contributors.COUNT"],
...     include_totals=True,
...     levels=[lvl["Month"], lvl["City"], lvl["Product"]],
... )
                           Product Price contributors.COUNT
Month   City       Product
Total                                                     5
January                                                   3
        London                     10.00                  2
                   Burger          10.00                  1
                   Pretzel         10.00                  1
        Manchester                 10.00                  1
                   Pretzel         10.00                  1
March                                                     2
        New York                                          2
                   Burger           8.00                  1
                   Pretzel         10.00                  1

Since the measure has not been defined to propagate on Product, changing the order of the levels prevents any propagation:

>>> cube.query(
...     m["Product Price"],
...     m["contributors.COUNT"],
...     include_totals=True,
...     levels=[lvl["Month"], lvl["Product"], lvl["City"]],
... )
                           Product Price contributors.COUNT
Month   Product City
Total                                                     5
January                                                   3
        Burger                                            1
                London             10.00                  1
        Pretzel                                           2
                London             10.00                  1
                Manchester         10.00                  1
March                                                     2
        Burger                                            1
                New York            8.00                  1
        Pretzel                                           1
                New York           10.00                  1

Finally, using levels=[], the value propagates to Month too:

>>> m["Product Price"] = tt.value(store["Price"], levels=[])
>>> cube.query(
...     m["Product Price"],
...     m["contributors.COUNT"],
...     include_totals=True,
...     levels=[lvl["Month"], lvl["City"], lvl["Product"]],
... )
                           Product Price contributors.COUNT
Month   City       Product
Total                                                     5
January                            10.00                  3
        London                     10.00                  2
                   Burger          10.00                  1
                   Pretzel         10.00                  1
        Manchester                 10.00                  1
                   Pretzel         10.00                  1
March                                                     2
        New York                                          2
                   Burger           8.00                  1
                   Pretzel         10.00                  1
Return type

Measure

atoti.where(condition, true_measure, false_measure=None)

Return a conditional measure.

This function is like an if-then-else statement:

  • Where the condition is True, the new measure will be equal to true_measure.

  • Where the condition is False, the new measure will be equal to false_measure.

If one of the values compared in the condition is None, the condition will be considered False.

Different types of conditions are supported:

  • Measures compared to anything measure-like:

    m["Test"] == 20
    
  • Levels compared to levels, (if the level is not expressed, it is considered None):

    lvl["source"] == lvl["destination"]
    
  • Levels compared to literals of the same type:

    lvl["city"] == "Paris"
    lvl["date"] > datetime.date(2020,1,1)
    lvl["age"] <= 18
    
  • A conjunction or disjunction of conditions using the & operator or | operator:

    (m["Test"] == 20) & (lvl["city"] == "Paris")
    (lvl["Country"] == "USA") | (lvl["Currency"] == "USD")
    
Parameters

Example

>>> df = pd.DataFrame(
...     columns=["Id", "City", "Value"],
...     data=[
...         (0, "Paris", 1.0),
...         (1, "Paris", 2.0),
...         (2, "London", 3.0),
...         (3, "London", 4.0),
...         (4, "Paris", 5.0),
...     ],
... )
>>> store = session.read_pandas(df, keys=["Id"], store_name="filter example")
>>> cube = session.create_cube(store)
>>> lvl, m = cube.levels, cube.measures
>>> m["Paris value"] = tt.where(lvl["City"] == "Paris", m["Value.SUM"], 0)
>>> cube.query(m["Paris value"], levels=lvl["City"])
       Paris value
City
London         .00
Paris         8.00
Return type

Measure