Skip to content

CellService

CellService(tm1_rest)

Bases: ObjectService

Service to handle Read and Write operations to TM1 cubes

Parameters:

Name Type Description Default
tm1_rest RestService

instance of RestService

required
Source code in TM1py/Services/CellService.py
def __init__(self, tm1_rest: RestService):
    """

    :param tm1_rest: instance of RestService
    """
    super().__init__(tm1_rest)

activate_transactionlog(*args, **kwargs)

Activate Transactionlog for one or many cubes

Parameters:

Name Type Description Default
args str

one or many cube names

()

Returns:

Type Description
Response
Source code in TM1py/Services/CellService.py
def activate_transactionlog(self, *args: str, **kwargs) -> Response:
    """Activate Transactionlog for one or many cubes

    :param args: one or many cube names
    :return:
    """

    value = "YES"
    element_tuple = (args[0], "Logging")
    return self.write_value(value=value, cube_name="}CubeProperties", element_tuple=element_tuple, **kwargs)

begin_changeset()

begin a change set

Returns:

Type Description
str

Change set ID

Source code in TM1py/Services/CellService.py
def begin_changeset(self) -> str:
    """begin a change set

    :return: Change set ID
    """

    url = "/BeginChangeSet"
    return self._rest.POST(url).json()["value"]

check_cell_feeders(cube_name, elements, dimensions=None, sandbox_name=None, element_separator=',', hierarchy_separator='&&', hierarchy_element_separator='::', **kwargs)

Check feeders

Parameters:

Name Type Description Default
cube_name str

name of the target cube

required
elements Union[Iterable, str]

string "Hierarchy1::Element1 && Hierarchy2::Element4, Element9, Element2" - Dimensions are not specified! They are derived from the position. - The , separates the element-selections - If more than one hierarchy is selected per dimension && splits the elementselections - If no Hierarchy is specified. Default Hierarchy will be addressed or Iterable [Element1, Element2, Element3]

required
dimensions Iterable[str]

optional. Dimension names in their natural order. Will speed up the execution!

None
sandbox_name str

str

None
element_separator str

Alternative separator for the elements, if elements are passed as string

','
hierarchy_separator str

Alternative separator for multiple hierarchies, if elements are passed as string

'&&'
hierarchy_element_separator str

Alternative separator between hierarchy name and element name, if elements are passed as string

'::'

Returns:

Type Description
Dict

fed cell descriptor

Source code in TM1py/Services/CellService.py
def check_cell_feeders(
    self,
    cube_name: str,
    elements: Union[Iterable, str],
    dimensions: Iterable[str] = None,
    sandbox_name: str = None,
    element_separator: str = ",",
    hierarchy_separator: str = "&&",
    hierarchy_element_separator: str = "::",
    **kwargs,
) -> Dict:
    """Check feeders

    :param cube_name: name of the target cube
    :param elements:
    string "Hierarchy1::Element1 && Hierarchy2::Element4, Element9, Element2"
        - Dimensions are not specified! They are derived from the position.
        - The , separates the element-selections
        - If more than one hierarchy is selected per dimension && splits the elementselections
        - If no Hierarchy is specified. Default Hierarchy will be addressed
    or
    Iterable [Element1, Element2, Element3]
    :param dimensions: optional. Dimension names in their natural order. Will speed up the execution!
    :param sandbox_name: str
    :param element_separator: Alternative separator for the elements, if elements are passed as string
    :param hierarchy_separator: Alternative separator for multiple hierarchies, if elements are passed as string
    :param hierarchy_element_separator: Alternative separator between hierarchy name and element name, if elements are passed as string
    :return: fed cell descriptor
    """

    url = format_url(
        "/Cubes('{}')/tm1.CheckFeeders"
        "?$select=Fed"
        "&$expand=Tuple($select=Name,UniqueName,Type),Cube($select=Name)",
        cube_name,
    )

    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    if isinstance(elements, str):
        body_as_dict = self._compose_odata_tuple_from_string(
            cube_name, elements, dimensions, element_separator, hierarchy_separator, hierarchy_element_separator
        )
    else:
        body_as_dict = self._compose_odata_tuple_from_iterable(cube_name, elements, dimensions)
    data = json.dumps(body_as_dict, ensure_ascii=False)

    return json.loads(self._rest.POST(url=url, data=data, **kwargs).content)

clear(cube, **kwargs)

Takes the cube name and keyword argument pairs of dimensions and MDX expressions:

tm1.cells.clear(
    cube="Sales",
    salesregion="{[Sales Region].[Australia],[Sales Region].[New Zealand]}",
    product="{[Product].[ABC]}",
    time="{[Time].[2022].Children}")

Make sure that the keyword argument names (e.g. product) map with the dimension names (e.g. Product) in the cube. Spaces in the dimension name (e.g., "Sales Region") must be omitted in the keyword (e.g. "salesregion")

Parameters:

Name Type Description Default
cube str

name of the cube

required
kwargs

keyword argument pairs of dimension names and mdx set expressions

{}

Returns:

Type Description
Source code in TM1py/Services/CellService.py
@require_data_admin
@require_ops_admin
@require_version(version="11.7")
def clear(self, cube: str, **kwargs):
    """
    Takes the cube name and keyword argument pairs of dimensions and MDX expressions:

    ```
    tm1.cells.clear(
        cube="Sales",
        salesregion="{[Sales Region].[Australia],[Sales Region].[New Zealand]}",
        product="{[Product].[ABC]}",
        time="{[Time].[2022].Children}")
    ```

    Make sure that the keyword argument names (e.g. product) map with the dimension names (e.g. Product) in the cube.
    Spaces in the dimension name (e.g., "Sales Region") must be omitted in the keyword (e.g. "salesregion")

    :param cube: name of the cube
    :param kwargs: keyword argument pairs of dimension names and mdx set expressions
    :return:
    """
    cube_service = self.get_cube_service()
    dimension_names = CaseAndSpaceInsensitiveSet(*cube_service.get_dimension_names(cube_name=cube))
    dimension_expression_pairs = CaseAndSpaceInsensitiveDict()

    for kwarg in kwargs:
        if kwarg in dimension_names:
            dimension_expression_pairs[kwarg] = wrap_in_curly_braces(kwargs[kwarg])

    for dimension_name in dimension_names:
        if dimension_name not in dimension_expression_pairs:
            expression = MdxHierarchySet.tm1_subset_all(dimension_name).filter_by_level(0).to_mdx()
            dimension_expression_pairs[dimension_name] = expression

    mdx_builder = MdxBuilder.from_cube(cube).columns_non_empty()
    for dimension, expression in dimension_expression_pairs.items():
        hierarchy_set = MdxHierarchySet.from_str(dimension=dimension, hierarchy=dimension, mdx=expression)
        mdx_builder.add_hierarchy_set_to_column_axis(hierarchy_set)

    return self.clear_with_mdx(cube=cube, mdx=mdx_builder.to_mdx(), **kwargs)

clear_spread(cube, unique_element_names, sandbox_name=None, **kwargs)

Execute clear spread

Parameters:

Name Type Description Default
cube str

name of the cube

required
unique_element_names Iterable[str]

target cell coordinates as unique element names (e.g. ["[d1].[c1]","[d2].[e3]"])

required
sandbox_name str

str

None

Returns:

Type Description
Response
Source code in TM1py/Services/CellService.py
def clear_spread(
    self, cube: str, unique_element_names: Iterable[str], sandbox_name: str = None, **kwargs
) -> Response:
    """Execute clear spread
    :param cube: name of the cube
    :param unique_element_names: target cell coordinates as unique element names (e.g. ["[d1].[c1]","[d2].[e3]"])
    :param sandbox_name: str
    :return:
    """
    mdx = """
    SELECT
    {{ {rows} }} ON 0
    FROM [{cube}]
    """.format(
        rows="}*{".join(unique_element_names), cube=cube
    )
    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name, **kwargs)

    payload = {"BeginOrdinal": 0, "Value": "C", "ReferenceCell@odata.bind": list()}
    for unique_element_name in unique_element_names:
        payload["ReferenceCell@odata.bind"].append(
            format_url(
                "Dimensions('{}')/Hierarchies('{}')/Elements('{}')",
                *Utils.dimension_hierarchy_element_tuple_from_unique_name(unique_element_name),
            )
        )

    return self._post_against_cellset(
        cellset_id=cellset_id, payload=payload, delete_cellset=True, sandbox_name=sandbox_name, **kwargs
    )

clear_with_dataframe(cube, df, dimension_mapping=None, **kwargs)

Clears data from a TM1 cube based on the distinct values in a DataFrame over cube dimensions. Note: This function is similar to tm1.cells.clear, but it is designed specifically for clearing data based on distinct values in a DataFrame over cube dimensions. The key difference is that this function interprets the DataFrame columns as dimensions and supports a mapping (dimension_mapping) for specifying hierarchies within those dimensions.

:example:

# Sample DataFrame with distinct values over cube dimensions
data = {
    "Year": ["2021", "2022"],
    "Organisation": ["some_company", "some_company"],
    "Location": ["Germany", "Albania"]
}

# Sample dimension mapping
dimensions_mapping = {
    "Organisation": "hierarchy_1",
    "Location": ["hierarchy_2", "hierarchy_3", "hierarchy_4"]
}

dataframe = pd.DataFrame(data)

with TM1Service(**tm1params) as tm1:
  tm1.cells.clear_with_dataframe(cube="Sales", df=dataframe)

Parameters:

Name Type Description Default
cube str

str The name of the TM1 cube.

required
df DataFrame

pd.DataFrame The DataFrame containing distinct values over cube dimensions. Columns in the DataFrame should correspond to cube dimensions.

required
dimension_mapping Dict

Dict, optional A dictionary mapping the DataFrame columns to one or many hierarchies within the given dimension. If not provided, assumes that the dimensions have just one hierarchy.

None

Returns:

Type Description

None The function clears data in the specified TM1 cube.

Raises:

Type Description
ValueError

If there are unmatched dimensions in the DataFrame or if specified dimensions do not exist in the TM1 cube.

Source code in TM1py/Services/CellService.py
@require_data_admin
@require_ops_admin
@require_version(version="11.7")
def clear_with_dataframe(self, cube: str, df: "pd.DataFrame", dimension_mapping: Dict = None, **kwargs):
    """Clears data from a TM1 cube based on the distinct values in a DataFrame over cube dimensions.
      Note:
          This function is similar to `tm1.cells.clear`, but it is designed specifically for clearing data
           based on distinct values in a DataFrame over cube dimensions. The key difference is that this
           function interprets the DataFrame columns as dimensions and supports a mapping (`dimension_mapping`)
           for specifying hierarchies within those dimensions.

    :param cube: str
        The name of the TM1 cube.
    :param df: pd.DataFrame
        The DataFrame containing distinct values over cube dimensions.
        Columns in the DataFrame should correspond to cube dimensions.
    :param dimension_mapping: Dict, optional
        A dictionary mapping the DataFrame columns to one or many hierarchies within the given dimension.
        If not provided, assumes that the dimensions have just one hierarchy.

    :return: None
        The function clears data in the specified TM1 cube.

    :raises ValueError:
        If there are unmatched dimensions in the DataFrame or if specified dimensions
        do not exist in the TM1 cube.

    :example:
        ```python

        # Sample DataFrame with distinct values over cube dimensions
        data = {
            "Year": ["2021", "2022"],
            "Organisation": ["some_company", "some_company"],
            "Location": ["Germany", "Albania"]
        }

        # Sample dimension mapping
        dimensions_mapping = {
            "Organisation": "hierarchy_1",
            "Location": ["hierarchy_2", "hierarchy_3", "hierarchy_4"]
        }

        dataframe = pd.DataFrame(data)

        with TM1Service(**tm1params) as tm1:
          tm1.cells.clear_with_dataframe(cube="Sales", df=dataframe)

        ```
    """
    if not dimension_mapping:
        dimension_mapping = {}

    if len(CaseAndSpaceInsensitiveSet(df.columns)) != len(df.columns):
        raise ValueError(f"Column names in DataFrame are not unique identifiers for TM1: {list(df.columns)}")

    cube_service = self.get_cube_service()
    dimension_names = CaseAndSpaceInsensitiveSet(*cube_service.get_dimension_names(cube_name=cube))

    df = df.astype(str)

    elements_by_column = {col_name: df[col_name].unique() for col_name in df.columns}

    mdx_selections = {}
    unmatched_dimension_names = []
    for column, elements in elements_by_column.items():
        members = []

        if column not in dimension_names:
            unmatched_dimension_names.append(column)

        for element in elements:
            if column in dimension_mapping:
                hierarchy = dimension_mapping.get(column)
                if not isinstance(hierarchy, str):
                    raise ValueError(f"Value for key '{column}' in dimension_mapping must be of type str")
                members.append(Member.of(column, hierarchy, element))

            else:
                members.append(Member.of(column, column, element))
        mdx_selections[column] = MdxHierarchySet.members(members)

    if dimension_mapping:
        for dimension, hierarchies in dimension_mapping.items():
            if dimension not in dimension_names:
                unmatched_dimension_names.append(dimension)

            elif isinstance(hierarchies, str):
                hierarchy = hierarchies
                mdx_selections[dimension] = MdxHierarchySet.tm1_subset_all(
                    dimension=dimension, hierarchy=hierarchy
                ).filter_by_level(0)

            elif isinstance(hierarchies, Iterable):
                for hierarchy in hierarchies:
                    mdx_selections[dimension] = MdxHierarchySet.tm1_subset_all(
                        dimension=dimension, hierarchy=hierarchy
                    ).filter_by_level(0)

            else:
                raise ValueError(f"Unexpected value type for key '{dimension}' in dimension_mapping")

    if unmatched_dimension_names:
        raise ValueError(
            f"Dimension(s) {unmatched_dimension_names} does not exist in cube {cube}."
            f"\nCheck the source of the dataframe to fix the problem"
        )

    for dimension_name in dimension_names:
        if dimension_name not in mdx_selections:
            mdx_selections[dimension_name] = MdxHierarchySet.tm1_subset_all(dimension_name).filter_by_level(0)

    mdx_builder = MdxBuilder.from_cube(cube).columns_non_empty()
    for dimension, expression in mdx_selections.items():
        mdx_builder.add_hierarchy_set_to_column_axis(expression)

    return self.clear_with_mdx(cube=cube, mdx=mdx_builder.to_mdx(), **kwargs)

clear_with_mdx(cube, mdx, sandbox_name=None, **kwargs)

clear a slice in a cube based on an MDX query. Function requires admin permissions, since TM1py uses an unbound TI with a ViewZeroOut statement.

Parameters:

Name Type Description Default
cube str

name of the cube

required
mdx str

a valid MDX query

required
sandbox_name str

a valid existing sandbox for the current user

None
kwargs
{}

Returns:

Type Description
Source code in TM1py/Services/CellService.py
@require_data_admin
@require_ops_admin
@require_version(version="11.7")
def clear_with_mdx(self, cube: str, mdx: str, sandbox_name: str = None, **kwargs):
    """clear a slice in a cube based on an MDX query.
    Function requires admin permissions, since TM1py uses an unbound TI with a `ViewZeroOut` statement.

    :param cube: name of the cube
    :param mdx: a valid MDX query
    :param sandbox_name: a valid existing sandbox for the current user
    :param kwargs:
    :return:
    """
    view_service = ViewService(self._rest)

    enable_sandbox = self.generate_enable_sandbox_ti(sandbox_name)

    view_name = "".join(["}TM1py", str(uuid.uuid4())])
    view_service.create(MDXView(cube_name=cube, view_name=view_name, MDX=mdx))

    try:
        code = f"ViewZeroOut('{cube}','{view_name}');"
        process = Process(name="")
        process.prolog_procedure = enable_sandbox
        process.epilog_procedure = code

        success, _, _ = self.execute_unbound_process(process, **kwargs)
        if not success:
            raise TM1pyException(f"Failed to clear cube: '{cube}' with mdx: '{abbreviate_mdx(mdx, 100)}'")
    finally:
        if view_service.exists(cube, view_name, private=False):
            view_service.delete(cube, view_name, private=False)

create_cellset(mdx, sandbox_name=None, **kwargs)

Execute MDX in order to create cellset at server. return the cellset-id

Parameters:

Name Type Description Default
mdx Union[str, MdxBuilder]

MDX Query, as string

required
sandbox_name str

str

None

Returns:

Type Description
str
Source code in TM1py/Services/CellService.py
def create_cellset(self, mdx: Union[str, MdxBuilder], sandbox_name: str = None, **kwargs) -> str:
    """Execute MDX in order to create cellset at server. return the cellset-id

    :param mdx: MDX Query, as string
    :param sandbox_name: str
    :return:
    """
    url = "/ExecuteMDX"
    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    data = {"MDX": mdx.to_mdx() if isinstance(mdx, MdxBuilder) else mdx}
    response = self._rest.POST(url=url, data=json.dumps(data, ensure_ascii=False), **kwargs)
    cellset_id = response.json()["ID"]
    return cellset_id

create_cellset_from_view(cube_name, view_name, private, sandbox_name=None, **kwargs)

create cellset from a cube view. return the cellset-id

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

required
kwargs
{}
sandbox_name str

str

None

Returns:

Type Description
str
Source code in TM1py/Services/CellService.py
def create_cellset_from_view(
    self, cube_name: str, view_name: str, private: bool, sandbox_name: str = None, **kwargs
) -> str:
    """create cellset from a cube view. return the cellset-id

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param kwargs:
    :param sandbox_name: str
    :return:
    """
    url = format_url(
        "/Cubes('{cube_name}')/{views}('{view_name}')/tm1.Execute",
        cube_name=cube_name,
        views="PrivateViews" if private else "Views",
        view_name=view_name,
    )
    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    return self._rest.POST(url=url, **kwargs).json()["ID"]

deactivate_transactionlog(*args, **kwargs)

Deactivate Transactionlog for one or many cubes

Parameters:

Name Type Description Default
args str

one or many cube names

()

Returns:

Type Description
Response
Source code in TM1py/Services/CellService.py
def deactivate_transactionlog(self, *args: str, **kwargs) -> Response:
    """Deactivate Transactionlog for one or many cubes

    :param args: one or many cube names
    :return:
    """
    value = "NO"
    element_tuple = (args[0], "Logging")
    return self.write_value(value=value, cube_name="}CubeProperties", element_tuple=element_tuple, **kwargs)

delete_cellset(cellset_id, sandbox_name=None, **kwargs)

Delete a cellset

Parameters:

Name Type Description Default
cellset_id str
required
sandbox_name str

str

None

Returns:

Type Description
Response
Source code in TM1py/Services/CellService.py
def delete_cellset(self, cellset_id: str, sandbox_name: str = None, **kwargs) -> Response:
    """Delete a cellset

    :param cellset_id:
    :param sandbox_name: str
    :return:
    """
    url = "/Cellsets('{}')".format(cellset_id)
    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    return self._rest.DELETE(url, **kwargs)

drop_non_updateable_cells(cells, cube_name, dimensions)

Source code in TM1py/Services/CellService.py
def drop_non_updateable_cells(self, cells: Dict, cube_name: str, dimensions: List[str]):
    mdx = build_mdx_from_cellset(cells, cube_name, dimensions)
    updateable_cells = CaseAndSpaceInsensitiveTuplesDict()

    cells_with_updateable_flag = self.execute_mdx(
        mdx,
        # Issue in TM1 Server 11.8: Updateable property is not correct if Value property is not retrieved
        cell_properties=["Updateable", "Value"],
        element_unique_names=False,
        skip_consolidated_cells=True,
        skip_rule_derived_cells=True,
    )

    for elements, cell in cells_with_updateable_flag.items():
        # skip sandbox element
        if len(elements) > len(dimensions):
            elements = elements[1:]

        if cell_is_updateable(cell):
            updateable_cells[elements] = cells[elements]
    return updateable_cells

end_changeset(change_set)

end a change set

Returns:

Type Description
Response

Change set ID

Source code in TM1py/Services/CellService.py
def end_changeset(self, change_set: str) -> Response:
    """end a change set

    :return: Change set ID
    """

    url = "/EndChangeSet"
    data = {"ChangeSetID": change_set}
    return self._rest.POST(url, data=json.dumps(data, ensure_ascii=False))

execute_mdx(mdx, cell_properties=None, top=None, skip_contexts=False, skip=None, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, element_unique_names=True, skip_cell_properties=False, use_compact_json=False, skip_sandbox_dimension=False, max_workers=1, async_axis=0, **kwargs)

Execute MDX and return the cells with their properties

:skip_sandbox_dimension: bool = False

Parameters:

Name Type Description Default
mdx str

MDX Query, as string

required
cell_properties List[str]

properties to be queried from the cell. E.g. Value, Ordinal, RuleDerived, ...

None
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_contexts bool

skip elements from titles / contexts in response

False
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
element_unique_names bool

'[d1].[h1].[e1]' or 'e1'

True
skip_cell_properties bool

cell values in result dictionary, instead of cell_properties dictionary

False
use_compact_json bool

bool

False

Returns:

Type Description
CaseAndSpaceInsensitiveTuplesDict

content in sweet concise structure.

Source code in TM1py/Services/CellService.py
def execute_mdx(
    self,
    mdx: str,
    cell_properties: List[str] = None,
    top: int = None,
    skip_contexts: bool = False,
    skip: int = None,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    element_unique_names: bool = True,
    skip_cell_properties: bool = False,
    use_compact_json: bool = False,
    skip_sandbox_dimension: bool = False,
    max_workers: int = 1,
    async_axis: int = 0,
    **kwargs,
) -> CaseAndSpaceInsensitiveTuplesDict:
    """Execute MDX and return the cells with their properties

    :param mdx: MDX Query, as string
    :param cell_properties: properties to be queried from the cell. E.g. Value, Ordinal, RuleDerived, ...
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_contexts: skip elements from titles / contexts in response
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param element_unique_names: '[d1].[h1].[e1]' or 'e1'
    :param skip_cell_properties: cell values in result dictionary, instead of cell_properties dictionary
    :param use_compact_json: bool
    :skip_sandbox_dimension: bool = False
    :return: content in sweet concise structure.
    """
    if max_workers > 1:
        return self.execute_mdx_async(
            mdx=mdx,
            cell_properties=cell_properties,
            top=top,
            skip=skip,
            skip_contexts=skip_contexts,
            skip_zeros=skip_zeros,
            skip_consolidated_cells=skip_consolidated_cells,
            skip_rule_derived_cells=skip_rule_derived_cells,
            sandbox_name=sandbox_name,
            element_unique_names=element_unique_names,
            skip_cell_properties=skip_cell_properties,
            use_compact_json=use_compact_json,
            skip_sandbox_dimension=skip_sandbox_dimension,
            max_workers=max_workers,
            async_axis=async_axis,
            **kwargs,
        )

    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name, **kwargs)
    return self.extract_cellset(
        cellset_id=cellset_id,
        cell_properties=cell_properties,
        top=top,
        skip=skip,
        skip_contexts=skip_contexts,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        element_unique_names=element_unique_names,
        skip_cell_properties=skip_cell_properties,
        use_compact_json=use_compact_json,
        skip_sandbox_dimension=skip_sandbox_dimension,
        **kwargs,
    )

execute_mdx_async(mdx, cell_properties=None, top=None, skip_contexts=False, skip=None, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, element_unique_names=True, skip_cell_properties=False, use_compact_json=False, skip_sandbox_dimension=False, max_workers=8, async_axis=0, **kwargs)

Execute MDX and return the cells with their properties

Parameters:

Name Type Description Default
mdx str

MDX Query, as string

required
cell_properties List[str]

properties to be queried from the cell. E.g. Value, Ordinal, RuleDerived, ...

None
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_contexts bool

skip elements from titles / contexts in response

False
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
element_unique_names bool

'[d1].[h1].[e1]' or 'e1'

True
skip_cell_properties bool

cell values in result dictionary, instead of cell_properties dictionary

False
use_compact_json bool

bool

False
skip_sandbox_dimension bool

bool = False

False
max_workers int

Int, number of threads to use in parallel

8
async_axis int

0 (columns) or 1 (rows). On which axis to parallelize retrieval

0

Returns:

Type Description
CaseAndSpaceInsensitiveTuplesDict

content in sweet concise structure.

Source code in TM1py/Services/CellService.py
def execute_mdx_async(
    self,
    mdx: str,
    cell_properties: List[str] = None,
    top: int = None,
    skip_contexts: bool = False,
    skip: int = None,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    element_unique_names: bool = True,
    skip_cell_properties: bool = False,
    use_compact_json: bool = False,
    skip_sandbox_dimension: bool = False,
    max_workers: int = 8,
    async_axis: int = 0,
    **kwargs,
) -> CaseAndSpaceInsensitiveTuplesDict:
    """Execute MDX and return the cells with their properties

    :param mdx: MDX Query, as string
    :param cell_properties: properties to be queried from the cell. E.g. Value, Ordinal, RuleDerived, ...
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_contexts: skip elements from titles / contexts in response
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param element_unique_names: '[d1].[h1].[e1]' or 'e1'
    :param skip_cell_properties: cell values in result dictionary, instead of cell_properties dictionary
    :param use_compact_json: bool
    :param skip_sandbox_dimension: bool = False
    :param max_workers: Int, number of threads to use in parallel
    :param async_axis: 0 (columns) or 1 (rows). On which axis to parallelize retrieval
    :return: content in sweet concise structure.
    """
    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name, **kwargs)

    return self.extract_cellset_async(
        cellset_id=cellset_id,
        cell_properties=cell_properties,
        top=top,
        skip=skip,
        skip_contexts=skip_contexts,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        element_unique_names=element_unique_names,
        skip_cell_properties=skip_cell_properties,
        use_compact_json=use_compact_json,
        skip_sandbox_dimension=skip_sandbox_dimension,
        max_workers=max_workers,
        async_axis=async_axis,
        **kwargs,
    )

execute_mdx_cellcount(mdx, sandbox_name=None, **kwargs)

Execute MDX in order to understand how many cells are in a cellset. Only return number of cells in the cellset. FAST!

Parameters:

Name Type Description Default
mdx str

MDX Query, as string

required
sandbox_name str

str

None

Returns:

Type Description
int

Number of Cells in the CellSet

Source code in TM1py/Services/CellService.py
def execute_mdx_cellcount(self, mdx: str, sandbox_name: str = None, **kwargs) -> int:
    """Execute MDX in order to understand how many cells are in a cellset.
    Only return number of cells in the cellset. FAST!

    :param mdx: MDX Query, as string
    :param sandbox_name: str
    :return: Number of Cells in the CellSet
    """
    cellset_id = self.create_cellset(mdx, sandbox_name=sandbox_name, **kwargs)
    return self.extract_cellset_cellcount(cellset_id, delete_cellset=True, sandbox_name=sandbox_name, **kwargs)

execute_mdx_csv(mdx, top=None, skip=None, skip_zeros=True, skip_consolidated_cells=False, skip_rule_derived_cells=False, csv_dialect=None, line_separator='\r\n', value_separator=',', sandbox_name=None, include_attributes=False, use_iterative_json=False, use_compact_json=False, use_blob=False, mdx_headers=False, **kwargs)

Optimized for performance. Get csv string of coordinates and values.

Parameters:

Name Type Description Default
mdx Union[str, MdxBuilder]

Valid MDX Query

required
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

True
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
csv_dialect Dialect

provide all csv output settings through standard library csv.Dialect If not provided dialect is created based on line_separator and value_separator arguments.

None
line_separator str
'\r\n'
value_separator str
','
sandbox_name str

str

None
include_attributes bool

include attribute columns

False
use_iterative_json bool

use iterative json parsing to reduce memory consumption significantly. Comes at a cost of 3-5% performance.

False
use_compact_json bool

bool

False
use_blob bool

Has better performance on datasets > 1M cells and lower memory footprint in any case.

False
mdx_headers bool

boolean, fully qualified hierarchy name as header instead of simple dimension name

False

Returns:

Type Description
str

String

Source code in TM1py/Services/CellService.py
def execute_mdx_csv(
    self,
    mdx: Union[str, MdxBuilder],
    top: int = None,
    skip: int = None,
    skip_zeros: bool = True,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    csv_dialect: "csv.Dialect" = None,
    line_separator: str = "\r\n",
    value_separator: str = ",",
    sandbox_name: str = None,
    include_attributes: bool = False,
    use_iterative_json: bool = False,
    use_compact_json: bool = False,
    use_blob: bool = False,
    mdx_headers: bool = False,
    **kwargs,
) -> str:
    """Optimized for performance. Get csv string of coordinates and values.

    :param mdx: Valid MDX Query
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param csv_dialect: provide all csv output settings through standard library csv.Dialect
        If not provided dialect is created based on line_separator and value_separator arguments.
    :param line_separator:
    :param value_separator:
    :param sandbox_name: str
    :param include_attributes: include attribute columns
    :param use_iterative_json: use iterative json parsing to reduce memory consumption significantly.
    Comes at a cost of 3-5% performance.
    :param use_compact_json: bool
    :param use_blob: Has better performance on datasets > 1M cells and lower memory footprint in any case.
    :param mdx_headers: boolean, fully qualified hierarchy name as header instead of simple dimension name
    :return: String
    """
    if use_blob:
        if include_attributes:
            raise ValueError("'include_attributes' must not be used in conjunction with 'use_blob'")
        if use_iterative_json:
            raise ValueError("'use_iterative_json' must not be used in conjunction with 'use_blob'")
        if use_compact_json:
            raise ValueError("'use_compact_json' must not be used in conjunction with 'use_blob'")
        if csv_dialect:
            raise ValueError("'csv_dialect' must not be used in conjunction with 'use_blob'")
        if line_separator != "\r\n":
            raise ValueError("'line_separator' must be '\r\n' to leverage 'use_blob' feature")

        return self._execute_mdx_csv_use_blob(
            mdx=mdx,
            top=top,
            skip=skip,
            skip_zeros=skip_zeros,
            skip_consolidated_cells=skip_consolidated_cells,
            skip_rule_derived_cells=skip_rule_derived_cells,
            value_separator=value_separator,
            sandbox_name=sandbox_name,
            mdx_headers=mdx_headers,
            **kwargs,
        )

    cellset_id = self.create_cellset(mdx, sandbox_name=sandbox_name, **kwargs)

    if use_iterative_json:
        return self.extract_cellset_csv_iter_json(
            cellset_id=cellset_id,
            top=top,
            skip=skip,
            skip_zeros=skip_zeros,
            skip_rule_derived_cells=skip_rule_derived_cells,
            skip_consolidated_cells=skip_consolidated_cells,
            csv_dialect=csv_dialect,
            line_separator=line_separator,
            value_separator=value_separator,
            sandbox_name=sandbox_name,
            include_attributes=include_attributes,
            mdx_headers=mdx_headers,
            **kwargs,
        )

    return self.extract_cellset_csv(
        cellset_id=cellset_id,
        top=top,
        skip=skip,
        skip_zeros=skip_zeros,
        skip_rule_derived_cells=skip_rule_derived_cells,
        skip_consolidated_cells=skip_consolidated_cells,
        csv_dialect=csv_dialect,
        line_separator=line_separator,
        value_separator=value_separator,
        sandbox_name=sandbox_name,
        include_attributes=include_attributes,
        use_compact_json=use_compact_json,
        mdx_headers=mdx_headers,
        **kwargs,
    )

execute_mdx_dataframe(mdx, top=None, skip=None, skip_zeros=True, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, include_attributes=False, use_iterative_json=False, use_compact_json=False, use_blob=False, shaped=False, mdx_headers=False, fillna_numeric_attributes=False, fillna_numeric_attributes_value=0, fillna_string_attributes=False, fillna_string_attributes_value='', **kwargs)

Optimized for performance. Get Pandas DataFrame from MDX Query.

Takes all arguments from the pandas.read_csv method: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

If 'use_blob' and 'shaped' are True, 'skip_zeros' will be overruled to False. This is necessary to assure column order is in line with cube view in TM1

Parameters:

Name Type Description Default
mdx Union[str, MdxBuilder]

Valid MDX Query

required
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

True
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
include_attributes bool

include attribute columns

False
use_iterative_json bool

use iterative json parsing to reduce memory consumption significantly. Comes at a cost of 3-5% performance.

False
use_compact_json bool

bool

False
use_blob bool

Has better performance on datasets > 1M cells and lower memory footprint in any case.

False
shaped bool

preserve shape of view/mdx in data frame

False
mdx_headers bool

boolean, fully qualified hierarchy name as header instead of simple dimension name

False
fillna_numeric_attributes bool

boolean, fills empty numerical attributes with fillna_numeric_attributes_value

False
fillna_string_attributes bool

boolean, fills empty string attributes with fillna_string_attributes_value

False
fillna_numeric_attributes_value Any

Any, value with which to replace na if fillna_numeric_attributes is True

0
fillna_string_attributes_value Any

Any, value with which to replace na if fillna_string_attributes is True

''

Returns:

Type Description
DataFrame

Pandas Dataframe

Source code in TM1py/Services/CellService.py
@require_pandas
def execute_mdx_dataframe(
    self,
    mdx: Union[str, MdxBuilder],
    top: int = None,
    skip: int = None,
    skip_zeros: bool = True,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    include_attributes: bool = False,
    use_iterative_json: bool = False,
    use_compact_json: bool = False,
    use_blob: bool = False,
    shaped: bool = False,
    mdx_headers: bool = False,
    fillna_numeric_attributes: bool = False,
    fillna_numeric_attributes_value: Any = 0,
    fillna_string_attributes: bool = False,
    fillna_string_attributes_value: Any = "",
    **kwargs,
) -> "pd.DataFrame":
    """Optimized for performance. Get Pandas DataFrame from MDX Query.

    Takes all arguments from the pandas.read_csv method:
    https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

    If 'use_blob' and 'shaped' are True, 'skip_zeros' will be overruled to False.
    This is necessary to assure column order is in line with cube view in TM1

    :param mdx: Valid MDX Query
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param include_attributes: include attribute columns
    :param use_iterative_json: use iterative json parsing to reduce memory consumption significantly.
    Comes at a cost of 3-5% performance.
    :param use_compact_json: bool
    :param use_blob: Has better performance on datasets > 1M cells and lower memory footprint in any case.
    :param shaped: preserve shape of view/mdx in data frame
    :param mdx_headers: boolean, fully qualified hierarchy name as header instead of simple dimension name
    :param fillna_numeric_attributes: boolean, fills empty numerical attributes with fillna_numeric_attributes_value
    :param fillna_string_attributes: boolean, fills empty string attributes with fillna_string_attributes_value
    :param fillna_numeric_attributes_value: Any, value with which to replace na if fillna_numeric_attributes is True
    :param fillna_string_attributes_value: Any, value with which to replace na if fillna_string_attributes is True
    :return: Pandas Dataframe
    """
    if (fillna_numeric_attributes or fillna_string_attributes) and not include_attributes:
        raise ValueError("Include attributes must be True if fillna_numeric or fillna_string is True.")

    # necessary to assure column order in line with cube view
    if shaped:
        skip_zeros = False

    if use_blob:
        if any(
            [
                fillna_numeric_attributes,
                fillna_numeric_attributes_value,
                fillna_string_attributes,
                fillna_string_attributes_value,
            ]
        ):
            raise ValueError("fillna attributes' feature must not be used with use_blob as True")

        raw_csv = self.execute_mdx_csv(
            mdx=mdx,
            top=top,
            skip=skip,
            skip_zeros=skip_zeros,
            skip_consolidated_cells=skip_consolidated_cells,
            skip_rule_derived_cells=skip_rule_derived_cells,
            sandbox_name=sandbox_name,
            include_attributes=include_attributes,
            line_separator="\r\n",
            value_separator="~",
            use_blob=use_blob,
            mdx_headers=mdx_headers,
        )

        return build_dataframe_from_csv(raw_csv, sep="~", shaped=shaped, **kwargs)

    cellset_id = self.create_cellset(mdx, sandbox_name=sandbox_name, **kwargs)
    return self.extract_cellset_dataframe(
        cellset_id,
        top=top,
        skip=skip,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        sandbox_name=sandbox_name,
        include_attributes=include_attributes,
        use_iterative_json=use_iterative_json,
        use_compact_json=use_compact_json,
        shaped=shaped,
        mdx_headers=mdx_headers,
        fillna_numeric_attributes=fillna_numeric_attributes,
        fillna_numeric_attributes_value=fillna_numeric_attributes_value,
        fillna_string_attributes=fillna_string_attributes,
        fillna_string_attributes_value=fillna_string_attributes_value,
        **kwargs,
    )

execute_mdx_dataframe_async(mdx_list, max_workers=8, top=None, skip=None, skip_zeros=True, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, include_attributes=False, use_iterative_json=False, use_compact_json=False, use_blob=False, shaped=False, mdx_headers=False, **kwargs)

Source code in TM1py/Services/CellService.py
@require_pandas
def execute_mdx_dataframe_async(
    self,
    mdx_list: List[Union[str, MdxBuilder]],
    max_workers: int = 8,
    top: int = None,
    skip: int = None,
    skip_zeros: bool = True,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    include_attributes: bool = False,
    use_iterative_json: bool = False,
    use_compact_json: bool = False,
    use_blob: bool = False,
    shaped: bool = False,
    mdx_headers: bool = False,
    **kwargs,
) -> "pd.DataFrame":

    def _execute_mdx_dataframe(mdx: Union[str, MdxBuilder]):
        return self.execute_mdx_dataframe(
            mdx=mdx,
            top=top,
            skip=skip,
            skip_zeros=skip_zeros,
            skip_consolidated_cells=skip_consolidated_cells,
            skip_rule_derived_cells=skip_rule_derived_cells,
            sandbox_name=sandbox_name,
            include_attributes=include_attributes,
            use_iterative_json=use_iterative_json,
            use_compact_json=use_compact_json,
            use_blob=use_blob,
            shaped=shaped,
            mdx_headers=mdx_headers,
            **kwargs,
        )

    async def _exec_mdx_dataframe_async():
        loop = asyncio.get_event_loop()
        result_list = []
        with ThreadPoolExecutor(max_workers) as executor:
            futures = [loop.run_in_executor(executor, _execute_mdx_dataframe, mdx) for mdx in mdx_list]
            for future in futures:
                result = await future
                result_list.append(result)
        return pd.concat(result_list, ignore_index=True)

    result_dataframe = asyncio.run(_exec_mdx_dataframe_async())

    return result_dataframe

execute_mdx_dataframe_pivot(mdx, dropna=False, fill_value=None, sandbox_name=None)

Execute MDX Query to get a pandas pivot data frame in the shape as specified in the Query

Parameters:

Name Type Description Default
mdx str
required
dropna bool
False
fill_value bool
None
sandbox_name str

str

None

Returns:

Type Description
DataFrame
Source code in TM1py/Services/CellService.py
@require_pandas
def execute_mdx_dataframe_pivot(
    self, mdx: str, dropna: bool = False, fill_value: bool = None, sandbox_name: str = None
) -> "pd.DataFrame":
    """Execute MDX Query to get a pandas pivot data frame in the shape as specified in the Query

    :param mdx:
    :param dropna:
    :param fill_value:
    :param sandbox_name: str
    :return:
    """
    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name)
    return self.extract_cellset_dataframe_pivot(
        cellset_id=cellset_id, dropna=dropna, fill_value=fill_value, sandbox_name=sandbox_name
    )

execute_mdx_dataframe_shaped(mdx, sandbox_name=None, display_attribute=False, use_iterative_json=False, use_blob=False, mdx_headers=False, **kwargs)

Retrieves data from cube in the shape of the query. Dimensions on rows can be stacked. One dimension must be placed on columns. Title selections are ignored.

Parameters:

Name Type Description Default
mdx str
required
sandbox_name str

str

None
use_blob bool
False
use_iterative_json bool
False
display_attribute bool

bool, show element name or first attribute from MDX PROPERTIES clause

False
kwargs
{}

Returns:

Type Description
DataFrame
Source code in TM1py/Services/CellService.py
@require_pandas
def execute_mdx_dataframe_shaped(
    self,
    mdx: str,
    sandbox_name: str = None,
    display_attribute: bool = False,
    use_iterative_json: bool = False,
    use_blob: bool = False,
    mdx_headers: bool = False,
    **kwargs,
) -> "pd.DataFrame":
    """Retrieves data from cube in the shape of the query.
    Dimensions on rows can be stacked. One dimension must be placed on columns. Title selections are ignored.

    :param mdx:
    :param sandbox_name: str
    :param use_blob:
    :param use_iterative_json:
    :param display_attribute: bool, show element name or first attribute from MDX PROPERTIES clause
    :param kwargs:
    :return:
    """
    if display_attribute and any([use_blob, use_iterative_json]):
        raise ValueError("When 'use_blob' or 'use_iterative_json' is True, 'display_attribute' must be False")

    # default case
    if not any([use_blob, use_iterative_json]):
        cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name)
        return self.extract_cellset_dataframe_shaped(
            cellset_id=cellset_id,
            delete_cellset=True,
            sandbox_name=sandbox_name,
            display_attribute=display_attribute,
            mdx_headers=mdx_headers,
            **kwargs,
        )

    if all([use_blob, use_iterative_json]):
        raise ValueError("'use_blob' and 'use_iterative_json' must not be used together")

    # ijson approach
    if use_iterative_json:
        return self.execute_mdx_dataframe(
            mdx=mdx,
            shaped=True,
            sandbox_name=sandbox_name,
            use_iterative_json=use_iterative_json,
            use_blob=False,
            mdx_headers=mdx_headers,
            **kwargs,
        )

    # blob approach
    return self.execute_mdx_dataframe(
        mdx=mdx, shaped=True, sandbox_name=sandbox_name, use_blob=True, mdx_headers=mdx_headers, **kwargs
    )

execute_mdx_elements_value_dict(mdx, top=None, skip=None, skip_zeros=True, skip_consolidated_cells=False, skip_rule_derived_cells=False, element_separator='|', sandbox_name=None, **kwargs)

Optimized for performance. Get Dict from MDX Query.

Parameters:

Name Type Description Default
mdx str

Valid MDX Query

required
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

True
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
element_separator str

separator for the dimension element combination

'|'
sandbox_name str

str

None

Returns:

Type Description
CaseAndSpaceInsensitiveDict

CaseAndSpaceInsensitiveDict {'2020|Jan|Sales': 2000, '2020|Feb|Sales': 3000}

Source code in TM1py/Services/CellService.py
def execute_mdx_elements_value_dict(
    self,
    mdx: str,
    top: int = None,
    skip: int = None,
    skip_zeros: bool = True,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    element_separator: str = "|",
    sandbox_name: str = None,
    **kwargs,
) -> CaseAndSpaceInsensitiveDict:
    """Optimized for performance. Get Dict from MDX Query.
    :param mdx: Valid MDX Query
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param element_separator: separator for the dimension element combination
    :param sandbox_name: str
    :return: CaseAndSpaceInsensitiveDict {'2020|Jan|Sales': 2000, '2020|Feb|Sales': 3000}
    """
    lines = self.execute_mdx_csv(
        mdx=mdx,
        top=top,
        skip=skip,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        value_separator=element_separator,
        sandbox_name=sandbox_name,
        **kwargs,
    )
    reader = csv.reader(StringIO(lines), delimiter=element_separator)

    # skip header
    next(reader, None)

    elements_value_dict = CaseAndSpaceInsensitiveDict()
    for row in reader:
        elements_value_dict[element_separator.join(row[:-1])] = row[-1]
    return elements_value_dict

execute_mdx_raw(mdx, cell_properties=None, elem_properties=None, member_properties=None, top=None, skip_contexts=False, skip=None, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, include_hierarchies=False, use_compact_json=False, **kwargs)

Execute MDX and return the raw data from TM1

Parameters:

Name Type Description Default
mdx str

String, a valid MDX Query

required
cell_properties Iterable[str]

List of properties to be queried from the cell. E.g. ['Value', 'RuleDerived', ...]

None
elem_properties Iterable[str]

List of properties to be queried from the elements. E.g. ['Name','Attributes', ...]

None
member_properties Iterable[str]

List of properties to be queried from the members. E.g. ['Name','Attributes', ...]

None
top int

Integer limiting the number of cells and the number or rows returned

None
skip int

Integer limiting the number of cells and the number or rows returned

None
skip_contexts bool

skip elements from titles / contexts in response

False
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
include_hierarchies bool

retrieve Hierarchies property on Axes

False
use_compact_json bool

bool

False

Returns:

Type Description
Dict

Raw format from TM1.

Source code in TM1py/Services/CellService.py
def execute_mdx_raw(
    self,
    mdx: str,
    cell_properties: Iterable[str] = None,
    elem_properties: Iterable[str] = None,
    member_properties: Iterable[str] = None,
    top: int = None,
    skip_contexts: bool = False,
    skip: int = None,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    include_hierarchies: bool = False,
    use_compact_json: bool = False,
    **kwargs,
) -> Dict:
    """Execute MDX and return the raw data from TM1

    :param mdx: String, a valid MDX Query
    :param cell_properties: List of properties to be queried from the cell. E.g. ['Value', 'RuleDerived', ...]
    :param elem_properties: List of properties to be queried from the elements. E.g. ['Name','Attributes', ...]
    :param member_properties: List of properties to be queried from the members. E.g. ['Name','Attributes', ...]
    :param top: Integer limiting the number of cells and the number or rows returned
    :param skip: Integer limiting the number of cells and the number or rows returned
    :param skip_contexts: skip elements from titles / contexts in response
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param include_hierarchies: retrieve Hierarchies property on Axes
    :param use_compact_json: bool
    :return: Raw format from TM1.
    """
    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name, **kwargs)
    return self.extract_cellset_raw(
        cellset_id=cellset_id,
        cell_properties=cell_properties,
        elem_properties=elem_properties,
        member_properties=member_properties,
        top=top,
        skip=skip,
        delete_cellset=True,
        skip_contexts=skip_contexts,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        sandbox_name=sandbox_name,
        include_hierarchies=include_hierarchies,
        use_compact_json=use_compact_json,
        **kwargs,
    )

execute_mdx_rows_and_values(mdx, element_unique_names=True, sandbox_name=None, **kwargs)

Execute MDX and retrieve row element names and values in a case and space insensitive dictionary

Parameters:

Name Type Description Default
mdx str
required
element_unique_names bool
True
sandbox_name str

str

None
kwargs
{}

Returns:

Type Description
CaseAndSpaceInsensitiveTuplesDict
Source code in TM1py/Services/CellService.py
def execute_mdx_rows_and_values(
    self, mdx: str, element_unique_names: bool = True, sandbox_name: str = None, **kwargs
) -> CaseAndSpaceInsensitiveTuplesDict:
    """Execute MDX and retrieve row element names and values in a case and space insensitive dictionary

    :param mdx:
    :param element_unique_names:
    :param sandbox_name: str
    :param kwargs:
    :return:
    """
    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name, **kwargs)
    return self.extract_cellset_rows_and_values(
        cellset_id, element_unique_names, delete_cellset=True, sandbox_name=sandbox_name, **kwargs
    )

execute_mdx_rows_and_values_string_set(mdx, exclude_empty_cells=True, sandbox_name=None, **kwargs)

Retrieve row element names and string cell values in a case and space insensitive set

Parameters:

Name Type Description Default
exclude_empty_cells bool
True
mdx str
required
sandbox_name str

str

None

Returns:

Type Description
CaseAndSpaceInsensitiveSet
Source code in TM1py/Services/CellService.py
def execute_mdx_rows_and_values_string_set(
    self, mdx: str, exclude_empty_cells: bool = True, sandbox_name: str = None, **kwargs
) -> CaseAndSpaceInsensitiveSet:
    """Retrieve row element names and **string** cell values in a case and space insensitive set

    :param exclude_empty_cells:
    :param mdx:
    :param sandbox_name: str
    :return:
    """
    rows_and_values = self.execute_mdx_rows_and_values(
        mdx, element_unique_names=False, sandbox_name=sandbox_name, **kwargs
    )
    return self._extract_string_set_from_rows_and_values(rows_and_values, exclude_empty_cells)

execute_mdx_ui_array(mdx, elem_properties=None, member_properties=None, value_precision=2, top=None, skip=None, sandbox_name=None, use_compact_json=False, **kwargs)

Useful for grids or charting libraries that want an array of cell values per row. Returns 3-dimensional cell structure for tabbed grids or multiple charts. Rows and pages are dicts, addressable by their name. Proper order of rows can be obtained in headers[1] Example 'cells' return format:

'cells': {
    '10100': {
        'Net Operating Income': [ 19832724.72429739,
                                    20365654.788303416,
                                    20729201.329183243,
                                    20480205.20121749],
        'Revenue': [ 28981046.50724231,
                        29512482.207418434,
                        29913730.038971487,
                        29563345.9542385]},
    '10200': {
        'Net Operating Income': [ 9853293.623709997,
                                    10277650.763958748,
                                    10466934.096533755,
                                    10333095.839474997],
        'Revenue': [ 13888143.710000003,
                        14300216.43,
                        14502421.63,
                        14321501.940000001]}
},

Parameters:

Name Type Description Default
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
mdx str

a valid MDX Query

required
elem_properties Iterable[str]

List of properties to be queried from the elements. E.g. ['UniqueName','Attributes']

None
member_properties Iterable[str]

List of properties to be queried from the members. E.g. ['UniqueName','Attributes']

None
value_precision int

Integer (optional) specifying number of decimal places to return

2
sandbox_name str

str

None
use_compact_json bool

bool

False

Returns:

Type Description

dict :{ titles: [], headers: [axis][], cells:{ Page0:{ Row0:{ [row values], Row1: [], ...}, ...}, ...}}

Source code in TM1py/Services/CellService.py
def execute_mdx_ui_array(
    self,
    mdx: str,
    elem_properties: Iterable[str] = None,
    member_properties: Iterable[str] = None,
    value_precision: int = 2,
    top: int = None,
    skip: int = None,
    sandbox_name: str = None,
    use_compact_json: bool = False,
    **kwargs,
):
    """
    Useful for grids or charting libraries that want an array of cell values per row.
    Returns 3-dimensional cell structure for tabbed grids or multiple charts.
    Rows and pages are dicts, addressable by their name. Proper order of rows can be obtained in headers[1]
    Example 'cells' return format:
    ```
    'cells': {
        '10100': {
            'Net Operating Income': [ 19832724.72429739,
                                        20365654.788303416,
                                        20729201.329183243,
                                        20480205.20121749],
            'Revenue': [ 28981046.50724231,
                            29512482.207418434,
                            29913730.038971487,
                            29563345.9542385]},
        '10200': {
            'Net Operating Income': [ 9853293.623709997,
                                        10277650.763958748,
                                        10466934.096533755,
                                        10333095.839474997],
            'Revenue': [ 13888143.710000003,
                            14300216.43,
                            14502421.63,
                            14321501.940000001]}
    },
    ```
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param mdx: a valid MDX Query
    :param elem_properties: List of properties to be queried from the elements. E.g. ['UniqueName','Attributes']
    :param member_properties: List of properties to be queried from the members. E.g. ['UniqueName','Attributes']
    :param value_precision: Integer (optional) specifying number of decimal places to return
    :param sandbox_name: str
    :param use_compact_json: bool
    :return: dict :`{ titles: [], headers: [axis][], cells:{ Page0:{ Row0:{ [row values], Row1: [], ...}, ...}, ...}}`
    """
    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name, **kwargs)
    data = self.extract_cellset_raw(
        cellset_id=cellset_id,
        cell_properties=["Value"],
        elem_properties=elem_properties,
        member_properties=list(set(member_properties or []) | {"Name"}),
        top=top,
        skip=skip,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        use_compact_json=use_compact_json,
        **kwargs,
    )
    return Utils.build_ui_arrays_from_cellset(raw_cellset_as_dict=data, value_precision=value_precision, top=top)

execute_mdx_ui_dygraph(mdx, elem_properties=None, member_properties=None, value_precision=2, top=None, skip=None, sandbox_name=None, use_compact_json=False, **kwargs)

Execute MDX get dygraph dictionary Useful for grids or charting libraries that want an array of cell values per column Returns 3-dimensional cell structure for tabbed grids or multiple charts Example 'cells' return format:

'cells': {
    '10100': [
        ['Q1-2004', 28981046.50724231, 19832724.72429739],
        ['Q2-2004', 29512482.207418434, 20365654.788303416],
        ['Q3-2004', 29913730.038971487, 20729201.329183243],
        ['Q4-2004', 29563345.9542385, 20480205.20121749]],
    '10200': [
        ['Q1-2004', 13888143.710000003, 9853293.623709997],
        ['Q2-2004', 14300216.43, 10277650.763958748],
        ['Q3-2004', 14502421.63, 10466934.096533755],
        ['Q4-2004', 14321501.940000001, 10333095.839474997]]
},

Parameters:

Name Type Description Default
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
mdx str

String, valid MDX Query

required
elem_properties Iterable[str]

List of properties to be queried from the elements. E.g. ['UniqueName','Attributes']

None
member_properties Iterable[str]

List of properties to be queried from the members. E.g. ['UniqueName','Attributes']

None
value_precision int

Integer (optional) specifying number of decimal places to return

2
sandbox_name str

str

None
use_compact_json bool

bool

False

Returns:

Type Description
Dict

dict: { titles: [], headers: [axis][], cells: { Page0: [ [column name, column values], [], ... ], ...}}

Source code in TM1py/Services/CellService.py
def execute_mdx_ui_dygraph(
    self,
    mdx: str,
    elem_properties: Iterable[str] = None,
    member_properties: Iterable[str] = None,
    value_precision: int = 2,
    top: int = None,
    skip: int = None,
    sandbox_name: str = None,
    use_compact_json: bool = False,
    **kwargs,
) -> Dict:
    """Execute MDX get dygraph dictionary
    Useful for grids or charting libraries that want an array of cell values per column
    Returns 3-dimensional cell structure for tabbed grids or multiple charts
    Example 'cells' return format:
    ```
    'cells': {
        '10100': [
            ['Q1-2004', 28981046.50724231, 19832724.72429739],
            ['Q2-2004', 29512482.207418434, 20365654.788303416],
            ['Q3-2004', 29913730.038971487, 20729201.329183243],
            ['Q4-2004', 29563345.9542385, 20480205.20121749]],
        '10200': [
            ['Q1-2004', 13888143.710000003, 9853293.623709997],
            ['Q2-2004', 14300216.43, 10277650.763958748],
            ['Q3-2004', 14502421.63, 10466934.096533755],
            ['Q4-2004', 14321501.940000001, 10333095.839474997]]
    },
    ```
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param mdx: String, valid MDX Query
    :param elem_properties: List of properties to be queried from the elements. E.g. ['UniqueName','Attributes']
    :param member_properties: List of properties to be queried from the members. E.g. ['UniqueName','Attributes']
    :param value_precision: Integer (optional) specifying number of decimal places to return
    :param sandbox_name: str
    :param use_compact_json: bool
    :return: dict: `{ titles: [], headers: [axis][], cells: { Page0: [ [column name, column values], [], ... ], ...}}`
    """
    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name)
    data = self.extract_cellset_raw(
        cellset_id=cellset_id,
        cell_properties=["Value"],
        elem_properties=elem_properties,
        member_properties=list(set(member_properties or []) | {"Name"}),
        top=top,
        skip=skip,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        use_compact_json=use_compact_json,
        **kwargs,
    )
    return Utils.build_ui_dygraph_arrays_from_cellset(raw_cellset_as_dict=data, value_precision=value_precision)

execute_mdx_values(mdx, sandbox_name=None, use_compact_json=False, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, **kwargs)

Optimized for performance. Query only raw cell values. Coordinates are omitted !

Parameters:

Name Type Description Default
mdx str

a valid MDX Query

required
sandbox_name str

str

None
use_compact_json bool

bool

False
skip_zeros bool

bool

False
skip_consolidated_cells bool

bool

False
skip_rule_derived_cells bool

bool

False

Returns:

Type Description
List[Union[str, float]]

List of cell values

Source code in TM1py/Services/CellService.py
def execute_mdx_values(
    self,
    mdx: str,
    sandbox_name: str = None,
    use_compact_json: bool = False,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    **kwargs,
) -> List[Union[str, float]]:
    """Optimized for performance. Query only raw cell values.
    Coordinates are omitted !

    :param mdx: a valid MDX Query
    :param sandbox_name: str
    :param use_compact_json: bool
    :param skip_zeros: bool
    :param skip_consolidated_cells: bool
    :param skip_rule_derived_cells: bool
    :return: List of cell values
    """
    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name, **kwargs)
    return self.extract_cellset_values(
        cellset_id,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        use_compact_json=use_compact_json,
        **kwargs,
    )

execute_unbound_process(process, **kwargs)

Source code in TM1py/Services/CellService.py
def execute_unbound_process(self, process: Process, **kwargs) -> Tuple[bool, str, str]:
    from TM1py import ProcessService

    process_service = ProcessService(self._rest)

    return process_service.execute_process_with_return(process, **kwargs)

execute_view(cube_name, view_name, private=False, cell_properties=None, top=None, skip_contexts=False, skip=None, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, element_unique_names=True, skip_cell_properties=False, use_compact_json=False, max_workers=1, async_axis=0, **kwargs)

get view content as dictionary with sweet and concise structure. Works on NativeView and MDXView !

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
cell_properties Iterable[str]

List, cell properties: [Values, Status, HasPicklist, etc.]

None
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_contexts bool

skip elements from titles / contexts in response

False
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
element_unique_names bool

'[d1].[h1].[e1]' or 'e1'

True
sandbox_name str

str

None
skip_cell_properties bool

cell values in result dictionary, instead of cell_properties dictionary

False
max_workers int

Int, number of threads to use in parallel

1
async_axis int

0 (columns) or 1 (rows). On which axis to parallelize retrieval

0
use_compact_json bool

bool

False

Returns:

Type Description
CaseAndSpaceInsensitiveTuplesDict

Dictionary : {([dim1].[elem1], [dim2][elem6]): {'Value':3127.312, 'Ordinal':12} .... }

Source code in TM1py/Services/CellService.py
def execute_view(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    cell_properties: Iterable[str] = None,
    top: int = None,
    skip_contexts: bool = False,
    skip: int = None,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    element_unique_names: bool = True,
    skip_cell_properties: bool = False,
    use_compact_json: bool = False,
    max_workers: int = 1,
    async_axis: int = 0,
    **kwargs,
) -> CaseAndSpaceInsensitiveTuplesDict:
    """get view content as dictionary with sweet and concise structure.
        Works on NativeView and MDXView !

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param cell_properties: List, cell properties: [Values, Status, HasPicklist, etc.]
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_contexts: skip elements from titles / contexts in response
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param element_unique_names: '[d1].[h1].[e1]' or 'e1'
    :param sandbox_name: str
    :param skip_cell_properties: cell values in result dictionary, instead of cell_properties dictionary
    :param max_workers: Int, number of threads to use in parallel
    :param async_axis: 0 (columns) or 1 (rows). On which axis to parallelize retrieval
    :param use_compact_json: bool
    :return: Dictionary : `{([dim1].[elem1], [dim2][elem6]): {'Value':3127.312, 'Ordinal':12}   ....  }`
    """
    if max_workers > 1:
        return self.execute_view_async(
            cube_name=cube_name,
            view_name=view_name,
            private=private,
            top=top,
            skip=skip,
            skip_contexts=skip_contexts,
            skip_zeros=skip_zeros,
            skip_consolidated_cells=skip_consolidated_cells,
            skip_rule_derived_cells=skip_rule_derived_cells,
            sandbox_name=sandbox_name,
            element_unique_names=element_unique_names,
            skip_cell_properties=skip_cell_properties,
            max_workers=max_workers,
            async_axis=async_axis,
        )
    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name, **kwargs
    )
    return self.extract_cellset(
        cellset_id=cellset_id,
        cell_properties=cell_properties,
        top=top,
        skip=skip,
        skip_contexts=skip_contexts,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        element_unique_names=element_unique_names,
        skip_cell_properties=skip_cell_properties,
        use_compact_json=use_compact_json,
        **kwargs,
    )

execute_view_async(cube_name, view_name, private=False, cell_properties=None, top=None, skip_contexts=False, skip=None, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, element_unique_names=True, skip_cell_properties=False, max_workers=8, async_axis=0, **kwargs)

get view content as dictionary with sweet and concise structure. Works on NativeView and MDXView !

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
cell_properties Iterable[str]

List, cell properties: [Values, Status, HasPicklist, etc.]

None
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_contexts bool

skip elements from titles / contexts in response

False
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
element_unique_names bool

'[d1].[h1].[e1]' or 'e1'

True
sandbox_name str

str

None
skip_cell_properties bool

cell values in result dictionary, instead of cell_properties dictionary

False
max_workers int

Int, number of threads to use in parallel

8
async_axis int

0 (columns) or 1 (rows). On which axis to parallelize retrieval

0

Returns:

Type Description
CaseAndSpaceInsensitiveTuplesDict

Dictionary : {([dim1].[elem1], [dim2][elem6]): {'Value':3127.312, 'Ordinal':12} .... }

Source code in TM1py/Services/CellService.py
def execute_view_async(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    cell_properties: Iterable[str] = None,
    top: int = None,
    skip_contexts: bool = False,
    skip: int = None,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    element_unique_names: bool = True,
    skip_cell_properties: bool = False,
    max_workers: int = 8,
    async_axis: int = 0,
    **kwargs,
) -> CaseAndSpaceInsensitiveTuplesDict:
    """get view content as dictionary with sweet and concise structure.
        Works on NativeView and MDXView !

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param cell_properties: List, cell properties: [Values, Status, HasPicklist, etc.]
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_contexts: skip elements from titles / contexts in response
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param element_unique_names: '[d1].[h1].[e1]' or 'e1'
    :param sandbox_name: str
    :param skip_cell_properties: cell values in result dictionary, instead of cell_properties dictionary
    :param max_workers: Int, number of threads to use in parallel
    :param async_axis: 0 (columns) or 1 (rows). On which axis to parallelize retrieval
    :return: Dictionary : `{([dim1].[elem1], [dim2][elem6]): {'Value':3127.312, 'Ordinal':12}   ....  }`
    """
    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name, **kwargs
    )
    return self.extract_cellset_async(
        cellset_id=cellset_id,
        cell_properties=cell_properties,
        top=top,
        skip=skip,
        skip_contexts=skip_contexts,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        element_unique_names=element_unique_names,
        skip_cell_properties=skip_cell_properties,
        max_workers=max_workers,
        async_axis=async_axis,
        **kwargs,
    )

execute_view_cellcount(cube_name, view_name, private=False, sandbox_name=None, **kwargs)

Execute cube view in order to understand how many cells are in a cellset. Only return number of cells in the cellset. FAST!

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
sandbox_name str

str

None

Returns:

Type Description
int
Source code in TM1py/Services/CellService.py
def execute_view_cellcount(
    self, cube_name: str, view_name: str, private: bool = False, sandbox_name: str = None, **kwargs
) -> int:
    """Execute cube view in order to understand how many cells are in a cellset.
    Only return number of cells in the cellset. FAST!

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param sandbox_name: str
    :return:
    """
    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name, **kwargs
    )
    return self.extract_cellset_cellcount(cellset_id, delete_cellset=True, sandbox_name=sandbox_name, **kwargs)

execute_view_csv(cube_name, view_name, private=False, top=None, skip=None, skip_zeros=True, skip_consolidated_cells=False, skip_rule_derived_cells=False, csv_dialect=None, line_separator='\r\n', value_separator=',', sandbox_name=None, use_iterative_json=False, use_compact_json=False, use_blob=False, arranged_axes=None, mdx_headers=False, **kwargs)

Optimized for performance. Get csv string of coordinates and values.

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

True
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
csv_dialect Dialect

provide all csv output settings through standard library csv.Dialect If not provided dialect is created based on line_separator and value_separator arguments.

None
line_separator str
'\r\n'
value_separator str
','
sandbox_name str

str

None
use_iterative_json bool

use iterative json parsing to reduce memory consumption significantly. Comes at a cost of 3-5% performance.

False
use_compact_json bool

bool

False
use_blob bool

Has 40% better performance and lower memory footprint in any case. Requires admin permissions.

False
arranged_axes Tuple[List, List, List]

Tuple of dimension names on all axes as 3 lists: Titles, Rows, Columns. Allows function to skip retrieval of cellset composition. E.g.: arranged_axes=(["Year"], ["Region","Product"], ["Period", "Version"])

None
mdx_headers bool

boolean, fully qualified hierarchy name as header instead of simple dimension name

False

Returns:

Type Description
str

dict, String

Source code in TM1py/Services/CellService.py
def execute_view_csv(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    top: int = None,
    skip: int = None,
    skip_zeros: bool = True,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    csv_dialect: "csv.Dialect" = None,
    line_separator: str = "\r\n",
    value_separator: str = ",",
    sandbox_name: str = None,
    use_iterative_json: bool = False,
    use_compact_json: bool = False,
    use_blob: bool = False,
    arranged_axes: Tuple[List, List, List] = None,
    mdx_headers: bool = False,
    **kwargs,
) -> str:
    """Optimized for performance. Get csv string of coordinates and values.

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param csv_dialect: provide all csv output settings through standard library csv.Dialect
        If not provided dialect is created based on line_separator and value_separator arguments.
    :param line_separator:
    :param value_separator:
    :param sandbox_name: str
    :param use_iterative_json: use iterative json parsing to reduce memory consumption significantly.
    Comes at a cost of 3-5% performance.
    :param use_compact_json: bool
    :param use_blob: Has 40% better performance and lower memory footprint in any case. Requires admin permissions.
    :param arranged_axes: Tuple of dimension names on all axes as 3 lists: Titles, Rows, Columns.
     Allows function to skip retrieval of cellset composition.
     E.g.: arranged_axes=(["Year"], ["Region","Product"], ["Period", "Version"])
    :param mdx_headers: boolean, fully qualified hierarchy name as header instead of simple dimension name
    :return: dict, String
    """
    if use_blob:
        if use_iterative_json:
            raise ValueError("'use_iterative_json' must not be used in conjunction with 'use_blob'")
        if use_compact_json:
            raise ValueError("'use_compact_json' must not be used in conjunction with 'use_blob'")
        if csv_dialect:
            raise ValueError("'csv_dialect' must not be used in conjunction with 'use_blob'")
        if line_separator != "\r\n":
            raise ValueError("'line_separator' must be '\r\n' to leverage 'use_blob' feature")
        if private:
            raise ValueError("'private' must be False to leverage 'use_blob' feature")

        return self._execute_view_csv_use_blob(
            cube_name=cube_name,
            view_name=view_name,
            top=top,
            skip=skip,
            skip_zeros=skip_zeros,
            skip_consolidated_cells=skip_consolidated_cells,
            skip_rule_derived_cells=skip_rule_derived_cells,
            value_separator=value_separator,
            sandbox_name=sandbox_name,
            arranged_axes=arranged_axes,
            mdx_headers=mdx_headers,
            **kwargs,
        )

    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name
    )
    if use_iterative_json:
        return self.extract_cellset_csv_iter_json(
            cellset_id=cellset_id,
            skip_zeros=skip_zeros,
            top=top,
            skip=skip,
            skip_consolidated_cells=skip_consolidated_cells,
            skip_rule_derived_cells=skip_rule_derived_cells,
            csv_dialect=csv_dialect,
            line_separator=line_separator,
            value_separator=value_separator,
            sandbox_name=sandbox_name,
            mdx_headers=mdx_headers,
            **kwargs,
        )

    return self.extract_cellset_csv(
        cellset_id=cellset_id,
        skip_zeros=skip_zeros,
        top=top,
        skip=skip,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        csv_dialect=csv_dialect,
        line_separator=line_separator,
        value_separator=value_separator,
        sandbox_name=sandbox_name,
        use_compact_json=use_compact_json,
        mdx_headers=mdx_headers,
        **kwargs,
    )

execute_view_dataframe(cube_name, view_name, private=False, top=None, skip=None, skip_zeros=True, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, use_iterative_json=False, use_blob=False, shaped=False, arranged_axes=None, mdx_headers=False, **kwargs)

Optimized for performance. Get Pandas DataFrame from an existing Cube View Context dimensions are omitted in the resulting Dataframe ! Cells with Zero/null are omitted !

If 'use_blob' and 'shaped' are True, 'skip_zeros' will be overruled to False. This is necessary to assure column order is in line with cube view in TM1

Takes all arguments from the pandas.read_csv method: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

True
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
use_iterative_json bool

use iterative json parsing to reduce memory consumption significantly. Comes at a cost of 3-5% performance.

False
use_blob bool

Has 40% better performance and lower memory footprint in any case. Requires admin permissions.

False
shaped bool

Shape rows and columns of data frame as specified in cube view / MDX

False
arranged_axes Tuple[List, List, List]

Tuple of dimension names on all axes as 3 lists: Titles, Rows, Columns. Allows function to skip retrieval of cellset composition in use_blob mode. E.g.: axes=(["Year"], ["Region","Product"], ["Period", "Version"]) :param mdx_headers: boolean, fully qualified hierarchy name as header instead of simple dimension name

None

Returns:

Type Description
DataFrame

Pandas Dataframe

Source code in TM1py/Services/CellService.py
@require_pandas
def execute_view_dataframe(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    top: int = None,
    skip: int = None,
    skip_zeros: bool = True,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    use_iterative_json: bool = False,
    use_blob: bool = False,
    shaped: bool = False,
    arranged_axes: Tuple[List, List, List] = None,
    mdx_headers: bool = False,
    **kwargs,
) -> "pd.DataFrame":
    """Optimized for performance. Get Pandas DataFrame from an existing Cube View
    Context dimensions are omitted in the resulting Dataframe !
    Cells with Zero/null are omitted !

    If 'use_blob' and 'shaped' are True, 'skip_zeros' will be overruled to False.
    This is necessary to assure column order is in line with cube view in TM1

    Takes all arguments from the pandas.read_csv method:
    https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param use_iterative_json: use iterative json parsing to reduce memory consumption significantly.
    Comes at a cost of 3-5% performance.
    :param use_blob: Has 40% better performance and lower memory footprint in any case. Requires admin permissions.
    :param shaped: Shape rows and columns of data frame as specified in cube view / MDX
    :param arranged_axes: Tuple of dimension names on all axes as 3 lists: Titles, Rows, Columns.
     Allows function to skip retrieval of cellset composition in use_blob mode.
     E.g.: axes=(["Year"], ["Region","Product"], ["Period", "Version"])
     :param mdx_headers: boolean, fully qualified hierarchy name as header instead of simple dimension name
    :return: Pandas Dataframe
    """
    # necessary to assure column order in line with cube view
    if shaped:
        skip_zeros = False

    if use_blob:
        raw_csv = self.execute_view_csv(
            cube_name=cube_name,
            view_name=view_name,
            top=top,
            skip=skip,
            skip_zeros=skip_zeros,
            skip_consolidated_cells=skip_consolidated_cells,
            skip_rule_derived_cells=skip_rule_derived_cells,
            sandbox_name=sandbox_name,
            use_iterative_json=use_iterative_json,
            line_separator="\r\n",
            value_separator="~",
            use_blob=True,
            arranged_axes=arranged_axes,
            mdx_headers=mdx_headers,
            **kwargs,
        )
        return build_dataframe_from_csv(raw_csv, sep="~", shaped=shaped, **kwargs)

    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name, **kwargs
    )
    return self.extract_cellset_dataframe(
        cellset_id,
        top=top,
        skip=skip,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        sandbox_name=sandbox_name,
        use_iterative_json=use_iterative_json,
        shaped=shaped,
        mdx_headers=mdx_headers,
        **kwargs,
    )

execute_view_dataframe_pivot(cube_name, view_name, private=False, dropna=False, fill_value=None, sandbox_name=None, **kwargs)

Execute a cube view to get a pandas pivot dataframe, in the shape of the cube view

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
dropna bool
False
fill_value bool
None
sandbox_name str

str

None

Returns:

Type Description
DataFrame
Source code in TM1py/Services/CellService.py
@require_pandas
def execute_view_dataframe_pivot(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    dropna: bool = False,
    fill_value: bool = None,
    sandbox_name: str = None,
    **kwargs,
) -> "pd.DataFrame":
    """Execute a cube view to get a pandas pivot dataframe, in the shape of the cube view

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param dropna:
    :param fill_value:
    :param sandbox_name: str
    :return:
    """
    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name, **kwargs
    )
    return self.extract_cellset_dataframe_pivot(
        cellset_id=cellset_id, dropna=dropna, fill_value=fill_value, sandbox_name=sandbox_name, **kwargs
    )

execute_view_dataframe_shaped(cube_name, view_name, private=False, sandbox_name=None, use_iterative_json=False, use_blob=False, mdx_headers=False, **kwargs)

Retrieves data from cube in the shape of the query. Dimensions on rows can be stacked. One dimension must be placed on columns. Title selections are ignored.

Parameters:

Name Type Description Default
cube_name str
required
view_name str
required
private bool
False
sandbox_name str

str

None
use_blob bool
False
use_iterative_json bool
False
kwargs
{}

Returns:

Type Description
DataFrame
Source code in TM1py/Services/CellService.py
@require_pandas
def execute_view_dataframe_shaped(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    sandbox_name: str = None,
    use_iterative_json: bool = False,
    use_blob: bool = False,
    mdx_headers: bool = False,
    **kwargs,
) -> "pd.DataFrame":
    """Retrieves data from cube in the shape of the query.
    Dimensions on rows can be stacked. One dimension must be placed on columns. Title selections are ignored.

    :param cube_name:
    :param view_name:
    :param private:
    :param sandbox_name: str
    :param use_blob:
    :param use_iterative_json:
    :param kwargs:
    :return:
    """

    # default approach
    if not any([use_blob, use_iterative_json]):
        cellset_id = self.create_cellset_from_view(
            cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name
        )
        return self.extract_cellset_dataframe_shaped(
            cellset_id=cellset_id, delete_cellset=True, sandbox_name=sandbox_name, mdx_headers=mdx_headers, **kwargs
        )

    if all([use_blob, use_iterative_json]):
        raise ValueError("'use_blob' and 'use_iterative_json' must not be used together")

    # ijson approach
    if use_iterative_json:
        return self.execute_view_dataframe(
            cube_name=cube_name,
            view_name=view_name,
            private=private,
            shaped=True,
            sandbox_name=sandbox_name,
            use_iterative_json=use_iterative_json,
            mdx_headers=mdx_headers,
            use_blob=False,
            **kwargs,
        )

    # blob approach
    if private:
        raise ValueError("view must be public when 'use_blob' argument is True")

    return self.execute_view_dataframe(
        cube_name=cube_name,
        view_name=view_name,
        private=private,
        shaped=True,
        sandbox_name=sandbox_name,
        mdx_headers=mdx_headers,
        use_blob=True,
        **kwargs,
    )

execute_view_elements_value_dict(cube_name, view_name, private=False, top=None, skip=None, skip_zeros=True, skip_consolidated_cells=False, skip_rule_derived_cells=False, element_separator='|', sandbox_name=None, **kwargs)

Optimized for performance. Get a Dict(tuple, value) from an existing Cube View Context dimensions are omitted in the resulting Dataframe ! Cells with Zero/null are omitted by default, but still configurable!

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

True
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
element_separator str

separator for the dimension element combination

'|'
sandbox_name str

str

None

Returns:

Type Description
CaseAndSpaceInsensitiveDict

CaseAndSpaceInsensitiveDict {'2020|Jan|Sales': 2000, '2020|Feb|Sales': 3000}

Source code in TM1py/Services/CellService.py
def execute_view_elements_value_dict(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    top: int = None,
    skip: int = None,
    skip_zeros: bool = True,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    element_separator: str = "|",
    sandbox_name: str = None,
    **kwargs,
) -> CaseAndSpaceInsensitiveDict:
    """Optimized for performance. Get a Dict(tuple, value) from an existing Cube View
    Context dimensions are omitted in the resulting Dataframe !
    Cells with Zero/null are omitted by default, but still configurable!

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param element_separator: separator for the dimension element combination
    :param sandbox_name: str
    :return: CaseAndSpaceInsensitiveDict {'2020|Jan|Sales': 2000, '2020|Feb|Sales': 3000}
    """
    lines = self.execute_view_csv(
        cube_name=cube_name,
        view_name=view_name,
        private=private,
        top=top,
        skip=skip,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        value_separator=element_separator,
        sandbox_name=sandbox_name,
        **kwargs,
    )
    elements_value_dict = CaseAndSpaceInsensitiveDict()
    for entries in lines.split("\r\n")[1:]:
        elements_value_dict[element_separator.join(entries.split(element_separator)[:-1])] = entries.split(
            element_separator
        )[-1]
    return elements_value_dict

execute_view_raw(cube_name, view_name, private=False, cell_properties=None, elem_properties=None, member_properties=None, top=None, skip_contexts=False, skip=None, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, use_compact_json=False, **kwargs)

Execute a cube view and return the raw data from TM1

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
cell_properties Iterable[str]

List of properties to be queried from the cell. E.g. ['Value', 'RuleDerived', ...]

None
elem_properties Iterable[str]

List of properties to be queried from the elements. E.g. ['Name','Attributes', ...]

None
member_properties Iterable[str]

List of properties to be queried from the members. E.g. ['Name','Attributes', ...]

None
top int

Integer limiting the number of cells and the number or rows returned

None
skip_contexts bool

skip elements from titles / contexts in response

False
skip int

Integer limiting the number of cells and the number or rows returned

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
use_compact_json bool

bool

False

Returns:

Type Description
Dict

Raw format from TM1.

Source code in TM1py/Services/CellService.py
def execute_view_raw(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    cell_properties: Iterable[str] = None,
    elem_properties: Iterable[str] = None,
    member_properties: Iterable[str] = None,
    top: int = None,
    skip_contexts: bool = False,
    skip: int = None,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    use_compact_json: bool = False,
    **kwargs,
) -> Dict:
    """Execute a cube view and return the raw data from TM1


    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param cell_properties: List of properties to be queried from the cell. E.g. ['Value', 'RuleDerived', ...]
    :param elem_properties: List of properties to be queried from the elements. E.g. ['Name','Attributes', ...]
    :param member_properties: List of properties to be queried from the members. E.g. ['Name','Attributes', ...]
    :param top: Integer limiting the number of cells and the number or rows returned
    :param skip_contexts: skip elements from titles / contexts in response
    :param skip: Integer limiting the number of cells and the number or rows returned
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param use_compact_json: bool
    :return: Raw format from TM1.
    """
    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name, **kwargs
    )
    return self.extract_cellset_raw(
        cellset_id=cellset_id,
        cell_properties=cell_properties,
        elem_properties=elem_properties,
        member_properties=member_properties,
        top=top,
        skip=skip,
        skip_contexts=skip_contexts,
        skip_zeros=skip_zeros,
        skip_rule_derived_cells=skip_rule_derived_cells,
        skip_consolidated_cells=skip_consolidated_cells,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        use_compact_json=use_compact_json,
        **kwargs,
    )

execute_view_rows_and_values(cube_name, view_name, private=False, element_unique_names=True, sandbox_name=None, **kwargs)

Execute cube view and retrieve row element names and values in a case and space insensitive dictionary

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
element_unique_names bool
True
sandbox_name str

str

None
kwargs
{}

Returns:

Type Description
CaseAndSpaceInsensitiveTuplesDict
Source code in TM1py/Services/CellService.py
def execute_view_rows_and_values(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    element_unique_names: bool = True,
    sandbox_name: str = None,
    **kwargs,
) -> CaseAndSpaceInsensitiveTuplesDict:
    """Execute cube view and retrieve row element names and values in a case and space insensitive dictionary

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param element_unique_names:
    :param sandbox_name: str
    :param kwargs:
    :return:
    """
    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name, **kwargs
    )
    return self.extract_cellset_rows_and_values(
        cellset_id, element_unique_names, delete_cellset=True, sandbox_name=sandbox_name, **kwargs
    )

execute_view_rows_and_values_string_set(cube_name, view_name, private=False, exclude_empty_cells=True, sandbox_name=None, **kwargs)

Retrieve row element names and string cell values in a case and space insensitive set

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
exclude_empty_cells bool
True
sandbox_name str

str

None

Returns:

Type Description
CaseAndSpaceInsensitiveSet
Source code in TM1py/Services/CellService.py
def execute_view_rows_and_values_string_set(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    exclude_empty_cells: bool = True,
    sandbox_name: str = None,
    **kwargs,
) -> CaseAndSpaceInsensitiveSet:
    """Retrieve row element names and **string** cell values in a case and space insensitive set

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param exclude_empty_cells:
    :param sandbox_name: str
    :return:
    """
    rows_and_values = self.execute_view_rows_and_values(
        cube_name, view_name, private, False, sandbox_name=sandbox_name, **kwargs
    )
    return self._extract_string_set_from_rows_and_values(rows_and_values, exclude_empty_cells)

execute_view_ui_array(cube_name, view_name, private=False, elem_properties=None, member_properties=None, value_precision=2, top=None, skip=None, sandbox_name=None, use_compact_json=False, **kwargs)

Useful for grids or charting libraries that want an array of cell values per row. Returns 3-dimensional cell structure for tabbed grids or multiple charts. Rows and pages are dicts, addressable by their name. Proper order of rows can be obtained in headers[1] Example 'cells' return format:

'cells': {
    '10100': {
        'Net Operating Income': [ 19832724.72429739,
                                    20365654.788303416,
                                    20729201.329183243,
                                    20480205.20121749],
        'Revenue': [ 28981046.50724231,
                        29512482.207418434,
                        29913730.038971487,
                        29563345.9542385]},
    '10200': {
        'Net Operating Income': [ 9853293.623709997,
                                    10277650.763958748,
                                    10466934.096533755,
                                    10333095.839474997],
        'Revenue': [ 13888143.710000003,
                        14300216.43,
                        14502421.63,
                        14321501.940000001]}
},

Parameters:

Name Type Description Default
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
elem_properties Iterable[str]

List of properties to be queried from the elements. E.g. ['UniqueName','Attributes']

None
member_properties Iterable[str]

List properties to be queried from the member. E.g. ['Name', 'UniqueName']

None
value_precision int

Integer (optional) specifying number of decimal places to return

2
sandbox_name str

str

None
use_compact_json bool

bool

False

Returns:

Type Description

dict :{ titles: [], headers: [axis][], cells:{ Page0:{ Row0: {[row values], Row1: [], ...}, ...}, ...}}

Source code in TM1py/Services/CellService.py
def execute_view_ui_array(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    elem_properties: Iterable[str] = None,
    member_properties: Iterable[str] = None,
    value_precision: int = 2,
    top: int = None,
    skip: int = None,
    sandbox_name: str = None,
    use_compact_json: bool = False,
    **kwargs,
):
    """
    Useful for grids or charting libraries that want an array of cell values per row.
    Returns 3-dimensional cell structure for tabbed grids or multiple charts.
    Rows and pages are dicts, addressable by their name. Proper order of rows can be obtained in headers[1]
    Example 'cells' return format:
    ```
    'cells': {
        '10100': {
            'Net Operating Income': [ 19832724.72429739,
                                        20365654.788303416,
                                        20729201.329183243,
                                        20480205.20121749],
            'Revenue': [ 28981046.50724231,
                            29512482.207418434,
                            29913730.038971487,
                            29563345.9542385]},
        '10200': {
            'Net Operating Income': [ 9853293.623709997,
                                        10277650.763958748,
                                        10466934.096533755,
                                        10333095.839474997],
            'Revenue': [ 13888143.710000003,
                            14300216.43,
                            14502421.63,
                            14321501.940000001]}
    },
    ```
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param elem_properties: List of properties to be queried from the elements. E.g. ['UniqueName','Attributes']
    :param member_properties: List properties to be queried from the member. E.g. ['Name', 'UniqueName']
    :param value_precision: Integer (optional) specifying number of decimal places to return
    :param sandbox_name: str
    :param use_compact_json: bool
    :return: dict :`{ titles: [], headers: [axis][], cells:{ Page0:{ Row0: {[row values], Row1: [], ...}, ...}, ...}}`
    """
    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name, **kwargs
    )
    data = self.extract_cellset_raw(
        cellset_id=cellset_id,
        cell_properties=["Value"],
        elem_properties=elem_properties,
        member_properties=list(set(member_properties or []) | {"Name"}),
        top=top,
        skip=skip,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        use_compact_json=use_compact_json,
        **kwargs,
    )
    return Utils.build_ui_arrays_from_cellset(raw_cellset_as_dict=data, value_precision=value_precision)

execute_view_ui_dygraph(cube_name, view_name, private=False, elem_properties=None, member_properties=None, value_precision=2, top=None, skip=None, sandbox_name=None, use_compact_json=False, **kwargs)

Useful for grids or charting libraries that want an array of cell values per row. Returns 3-dimensional cell structure for tabbed grids or multiple charts. Rows and pages are dicts, addressable by their name. Proper order of rows can be obtained in headers[1] Example 'cells' return format: 'cells': { '10100': { 'Net Operating Income': [ 19832724.72429739, 20365654.788303416, 20729201.329183243, 20480205.20121749], 'Revenue': [ 28981046.50724231, 29512482.207418434, 29913730.038971487, 29563345.9542385]}, '10200': { 'Net Operating Income': [ 9853293.623709997, 10277650.763958748, 10466934.096533755, 10333095.839474997], 'Revenue': [ 13888143.710000003, 14300216.43, 14502421.63, 14321501.940000001]} },

Parameters:

Name Type Description Default
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
cube_name str

cube name

required
view_name str

view name

required
private bool

True (private) or False (public)

False
elem_properties Iterable[str]

List of properties to be queried from the elements. E.g. ['UniqueName','Attributes']

None
member_properties Iterable[str]

List of properties to be queried from the members. E.g. ['UniqueName','Attributes']

None
value_precision int

Integer (optional) specifying number of decimal places to return

2
sandbox_name str

str

None
use_compact_json bool

bool

False

Returns:

Type Description
Source code in TM1py/Services/CellService.py
def execute_view_ui_dygraph(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    elem_properties: Iterable[str] = None,
    member_properties: Iterable[str] = None,
    value_precision: int = 2,
    top: int = None,
    skip: int = None,
    sandbox_name: str = None,
    use_compact_json: bool = False,
    **kwargs,
):
    """
    Useful for grids or charting libraries that want an array of cell values per row.
    Returns 3-dimensional cell structure for tabbed grids or multiple charts.
    Rows and pages are dicts, addressable by their name. Proper order of rows can be obtained in headers[1]
    Example 'cells' return format:
        'cells': {
            '10100': {
                'Net Operating Income': [ 19832724.72429739,
                                          20365654.788303416,
                                          20729201.329183243,
                                          20480205.20121749],
                'Revenue': [ 28981046.50724231,
                             29512482.207418434,
                             29913730.038971487,
                             29563345.9542385]},
            '10200': {
                'Net Operating Income': [ 9853293.623709997,
                                           10277650.763958748,
                                           10466934.096533755,
                                           10333095.839474997],
                'Revenue': [ 13888143.710000003,
                             14300216.43,
                             14502421.63,
                             14321501.940000001]}
        },

    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param cube_name: cube name
    :param view_name: view name
    :param private: True (private) or False (public)
    :param elem_properties: List of properties to be queried from the elements. E.g. ['UniqueName','Attributes']
    :param member_properties: List of properties to be queried from the members. E.g. ['UniqueName','Attributes']
    :param value_precision: Integer (optional) specifying number of decimal places to return
    :param sandbox_name: str
    :param use_compact_json: bool
    :return:
    """
    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name, **kwargs
    )
    data = self.extract_cellset_raw(
        cellset_id=cellset_id,
        cell_properties=["Value"],
        elem_properties=elem_properties,
        member_properties=list(set(member_properties or []) | {"Name"}),
        top=top,
        skip=skip,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        use_compact_json=use_compact_json,
        **kwargs,
    )
    return Utils.build_ui_dygraph_arrays_from_cellset(raw_cellset_as_dict=data, value_precision=value_precision)

execute_view_values(cube_name, view_name, private=False, sandbox_name=None, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, use_compact_json=False, **kwargs)

Execute view and retrieve only the cell values

Parameters:

Name Type Description Default
cube_name str

String, name of the cube

required
view_name str

String, name of the view

required
private bool

True (private) or False (public)

False
sandbox_name str

str

None
use_compact_json bool

bool

False
skip_zeros bool

bool

False
skip_consolidated_cells bool

bool

False
skip_rule_derived_cells bool

bool

False
kwargs
{}

Returns:

Type Description
List[Union[str, float]]
Source code in TM1py/Services/CellService.py
def execute_view_values(
    self,
    cube_name: str,
    view_name: str,
    private: bool = False,
    sandbox_name: str = None,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    use_compact_json: bool = False,
    **kwargs,
) -> List[Union[str, float]]:
    """Execute view and retrieve only the cell values

    :param cube_name: String, name of the cube
    :param view_name: String, name of the view
    :param private: True (private) or False (public)
    :param sandbox_name: str
    :param use_compact_json: bool
    :param skip_zeros: bool
    :param skip_consolidated_cells: bool
    :param skip_rule_derived_cells: bool
    :param kwargs:
    :return:
    """
    cellset_id = self.create_cellset_from_view(
        cube_name=cube_name, view_name=view_name, private=private, sandbox_name=sandbox_name, **kwargs
    )
    return self.extract_cellset_values(
        cellset_id,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        use_compact_json=use_compact_json,
        skip_zeros=skip_zeros,
        skip_rule_derived_cells=skip_rule_derived_cells,
        skip_consolidated_cells=skip_consolidated_cells,
        **kwargs,
    )

extract_cellset(cellset_id, cell_properties=None, top=None, skip=None, delete_cellset=True, skip_contexts=False, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, element_unique_names=True, skip_cell_properties=False, use_compact_json=False, skip_sandbox_dimension=False, **kwargs)

Execute cellset and return the cells with their properties

Parameters:

Name Type Description Default
skip_contexts bool
False
delete_cellset bool
True
cellset_id str
required
cell_properties Iterable[str]

properties to be queried from the cell. E.g. Value, Ordinal, RuleDerived, ...

None
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
element_unique_names bool

'[d1].[h1].[e1]' or 'e1'

True
skip_cell_properties bool

cell values in result dictionary, instead of cell_properties dictionary

False
use_compact_json bool

bool

False
skip_sandbox_dimension bool

skip sandbox dimension

False

Returns:

Type Description
CaseAndSpaceInsensitiveTuplesDict

Content in sweet concise structure.

Source code in TM1py/Services/CellService.py
def extract_cellset(
    self,
    cellset_id: str,
    cell_properties: Iterable[str] = None,
    top: int = None,
    skip: int = None,
    delete_cellset: bool = True,
    skip_contexts: bool = False,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    element_unique_names: bool = True,
    skip_cell_properties: bool = False,
    use_compact_json: bool = False,
    skip_sandbox_dimension: bool = False,
    **kwargs,
) -> CaseAndSpaceInsensitiveTuplesDict:
    """Execute cellset and return the cells with their properties

    :param skip_contexts:
    :param delete_cellset:
    :param cellset_id:
    :param cell_properties: properties to be queried from the cell. E.g. Value, Ordinal, RuleDerived, ...
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param element_unique_names: '[d1].[h1].[e1]' or 'e1'
    :param skip_cell_properties: cell values in result dictionary, instead of cell_properties dictionary
    :param use_compact_json: bool
    :param skip_sandbox_dimension: skip sandbox dimension
    :return: Content in sweet concise structure.
    """
    if not cell_properties:
        cell_properties = ["Value"]

    raw_cellset = self.extract_cellset_raw(
        cellset_id,
        cell_properties=cell_properties,
        elem_properties=["UniqueName"],
        member_properties=["UniqueName"],
        top=top,
        skip=skip,
        skip_contexts=skip_contexts,
        delete_cellset=delete_cellset,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        sandbox_name=sandbox_name,
        include_hierarchies=False,
        use_compact_json=use_compact_json,
        **kwargs,
    )

    return Utils.build_content_from_cellset_dict(
        raw_cellset_as_dict=raw_cellset,
        top=top,
        element_unique_names=element_unique_names,
        skip_cell_properties=skip_cell_properties,
        skip_sandbox_dimension=skip_sandbox_dimension,
    )

extract_cellset_async(cellset_id, cell_properties=None, top=None, skip=None, delete_cellset=True, skip_contexts=False, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, element_unique_names=True, skip_cell_properties=False, skip_sandbox_dimension=False, max_workers=8, async_axis=1, **kwargs)

Execute cellset and return the cells with their properties

Parameters:

Name Type Description Default
skip_contexts bool
False
delete_cellset bool
True
cellset_id str
required
cell_properties Iterable[str]

properties to be queried from the cell. E.g. Value, Ordinal, RuleDerived, ...

None
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
element_unique_names bool

'[d1].[h1].[e1]' or 'e1'

True
skip_cell_properties bool

cell values in result dictionary, instead of cell_properties dictionary

False
skip_sandbox_dimension bool

skip sandbox dimension

False
max_workers int

Int, number of threads to use in parallel

8
async_axis int

0 (columns) or 1 (rows). On which axis to parallelize retrieval

1

Returns:

Type Description
CaseAndSpaceInsensitiveTuplesDict

Content in sweet concise structure.

Source code in TM1py/Services/CellService.py
def extract_cellset_async(
    self,
    cellset_id: str,
    cell_properties: Iterable[str] = None,
    top: int = None,
    skip: int = None,
    delete_cellset: bool = True,
    skip_contexts: bool = False,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    element_unique_names: bool = True,
    skip_cell_properties: bool = False,
    skip_sandbox_dimension: bool = False,
    max_workers: int = 8,
    async_axis: int = 1,
    **kwargs,
) -> CaseAndSpaceInsensitiveTuplesDict:
    """Execute cellset and return the cells with their properties

    :param skip_contexts:
    :param delete_cellset:
    :param cellset_id:
    :param cell_properties: properties to be queried from the cell. E.g. Value, Ordinal, RuleDerived, ...
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param element_unique_names: '[d1].[h1].[e1]' or 'e1'
    :param skip_cell_properties: cell values in result dictionary, instead of cell_properties dictionary
    :param skip_sandbox_dimension: skip sandbox dimension
    :param max_workers: Int, number of threads to use in parallel
    :param async_axis: 0 (columns) or 1 (rows). On which axis to parallelize retrieval
    :return: Content in sweet concise structure.
    """
    if not cell_properties:
        cell_properties = ["Value"]

    axes = self.extract_cellset_axes_raw_async(
        cellset_id=cellset_id,
        async_axis=async_axis,
        max_workers=max_workers,
        elem_properties=["UniqueName"],
        member_properties=["UniqueName"],
        top=top,
        skip=skip,
        skip_contexts=skip_contexts,
        sandbox_name=sandbox_name,
        **kwargs,
    )

    cells = self.extract_cellset_cells_raw_async(
        cellset_id=cellset_id,
        max_workers=max_workers,
        cell_properties=cell_properties,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        sandbox_name=sandbox_name,
        **kwargs,
    )

    # cube with dimension names is required from transformation later on
    cube_dimensions = self.extract_cellset_cube_with_dimensions(
        cellset_id=cellset_id, delete_cellset=delete_cellset
    )

    raw_cellset = {**cube_dimensions, **axes, **cells}

    return Utils.build_content_from_cellset_dict(
        raw_cellset_as_dict=raw_cellset,
        top=top,
        element_unique_names=element_unique_names,
        skip_cell_properties=skip_cell_properties,
        skip_sandbox_dimension=skip_sandbox_dimension,
    )

extract_cellset_axes_cardinality(cellset_id)

Source code in TM1py/Services/CellService.py
def extract_cellset_axes_cardinality(self, cellset_id: str):
    url = "/Cellsets('{cellset_id}')?$expand=Axes($select=Cardinality)".format(cellset_id=cellset_id)
    response = self._rest.GET(url=url)
    return response.json()

extract_cellset_axes_raw_async(cellset_id, async_axis=1, max_workers=8, elem_properties=None, member_properties=None, skip_contexts=False, include_hierarchies=False, sandbox_name=None, **kwargs)

Extract cellset axes asynchronously

Parameters:

Name Type Description Default
cellset_id str

String; ID of existing cellset

required
async_axis int

determines which axis will be extracted asynchronously

1
max_workers int

Max number of threads, e.g. 14

8
elem_properties Iterable[str]

List of properties to be queried from elements. E.g. ['UniqueName','Attributes', ...]

None
member_properties Iterable[str]

List properties to be queried from the member. E.g. ['Name', 'UniqueName']

None
skip_contexts bool

skip elements from titles / contexts in response

False
sandbox_name str

str

None
include_hierarchies bool

retrieve Hierarchies property on Axes

False

Returns:

Type Description

Raw format from TM1.

Source code in TM1py/Services/CellService.py
def extract_cellset_axes_raw_async(
    self,
    cellset_id: str,
    async_axis: int = 1,
    max_workers: int = 8,
    elem_properties: Iterable[str] = None,
    member_properties: Iterable[str] = None,
    skip_contexts: bool = False,
    include_hierarchies: bool = False,
    sandbox_name: str = None,
    **kwargs,
):
    """Extract cellset axes asynchronously

    :param cellset_id: String; ID of existing cellset
    :param async_axis: determines which axis will be extracted asynchronously
    :param max_workers: Max number of threads, e.g. 14
    :param elem_properties: List of properties to be queried from elements. E.g. ['UniqueName','Attributes', ...]
    :param member_properties: List properties to be queried from the member. E.g. ['Name', 'UniqueName']
    :param skip_contexts: skip elements from titles / contexts in response
    :param sandbox_name: str
    :param include_hierarchies: retrieve Hierarchies property on Axes
    :return: Raw format from TM1.
    """

    axes_cardinality = self.extract_cellset_axes_cardinality(cellset_id=cellset_id)

    if async_axis >= len(axes_cardinality["Axes"]):
        raise ValueError("Argument 'async_axis' must be less than axes cardinality")

    # select Name property if member_properties is None or empty.
    # Necessary, as tm1 default behaviour is to return all properties if no $select is specified in the request.
    if member_properties is None or len(list(member_properties)) == 0:
        member_properties = ["Name"]
    select_member_properties = "$select={}".format(",".join(member_properties))

    expand_elem_properties = (
        ";$expand=Element($select={elem_properties})".format(elem_properties=",".join(elem_properties))
        if elem_properties is not None and len(list(elem_properties)) > 0
        else ""
    )

    if include_hierarchies:
        expand_hierarchies = "Hierarchies($select=Name;$expand=Dimension($select=Name)),"
    else:
        expand_hierarchies = ""

    def _extract_cellset_axis_raw(axis: int = async_axis, partition: int = 0, partition_size: int = 0):
        top = partition_size
        skip = partition * partition_size
        filter_axis = "$filter=Ordinal eq {axis};".format(axis=axis)
        url = (
            "/Cellsets('{cellset_id}')?$expand="
            "Axes({filter_axis}$expand={hierarchies}Tuples($expand=Members({select_member_properties}"
            "{expand_elem_properties}){partition}))".format(
                cellset_id=cellset_id,
                partition=f";$top={top};$skip={skip}" if partition_size > 0 else "",
                filter_axis=filter_axis,
                hierarchies=expand_hierarchies,
                select_member_properties=select_member_properties,
                expand_elem_properties=expand_elem_properties,
            )
        )
        url = add_url_parameters(url, **{"!sandbox": sandbox_name})
        response = self._rest.GET(url=url, **kwargs)

        return response.json()

    async def _extract_cellset_axes_raw_async():
        partition_size = math.ceil(axes_cardinality["Axes"][async_axis]["Cardinality"] / max_workers)
        loop = asyncio.get_event_loop()
        result_list = []
        with ThreadPoolExecutor(max_workers) as executor:
            futures = [
                loop.run_in_executor(executor, _extract_cellset_axis_raw, async_axis, partition, partition_size)
                for partition in range(max_workers)
            ]

            for future in futures:
                result = await future
                result_list = result_list + result["Axes"][0]["Tuples"]
        return result_list

    # Extract non-asynchronous axis
    axes = _extract_cellset_axis_raw(axis=1 - async_axis)
    # Extract tuples for asynchronous axis
    async_axis_tuples = asyncio.run(_extract_cellset_axes_raw_async())
    # Combine results
    axes["Axes"].insert(
        async_axis,
        {
            "Ordinal": async_axis,
            "Cardinality": axes_cardinality["Axes"][async_axis]["Cardinality"],
            "Tuples": async_axis_tuples,
        },
    )

    if not skip_contexts:
        context = _extract_cellset_axis_raw(axis=2)
        if len(context["Axes"]) > 0:
            axes["Axes"].append(context["Axes"][0])

    return axes

extract_cellset_cellcount(cellset_id, sandbox_name=None, **kwargs)

Retrieve number of cells in the cellset

Parameters:

Name Type Description Default
cellset_id str
required
sandbox_name str

str

None
kwargs
{}

Returns:

Type Description
int
Source code in TM1py/Services/CellService.py
@tidy_cellset
def extract_cellset_cellcount(self, cellset_id: str, sandbox_name: str = None, **kwargs) -> int:
    """Retrieve number of cells in the cellset

    :param cellset_id:
    :param sandbox_name: str
    :param kwargs:
    :return:
    """
    url = "/Cellsets('{}')/Cells/$count".format(cellset_id)
    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    response = self._rest.GET(url, **kwargs)
    return int(response.content)

extract_cellset_cells_raw(cellset_id, cell_properties=None, top=None, skip=None, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, **kwargs)

Source code in TM1py/Services/CellService.py
@odata_compact_json(return_as_dict=True)
def extract_cellset_cells_raw(
    self,
    cellset_id: str,
    cell_properties: Iterable[str] = None,
    top: int = None,
    skip: int = None,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    **kwargs,
):

    if not cell_properties:
        cell_properties = ["Value"]

    if skip_rule_derived_cells:
        cell_properties.append("RuleDerived")
        # necessary due to bug in TM1 11.8: If only RuleDerived is retrieved it occasionally produces wrong results
        cell_properties.append("Updateable")

    if skip_consolidated_cells:
        cell_properties.append("Consolidated")

    if skip or skip_zeros or skip_rule_derived_cells or skip_consolidated_cells:
        if "Ordinal" not in cell_properties:
            cell_properties.append("Ordinal")

    filter_cells = ""
    if skip_zeros or skip_consolidated_cells or skip_rule_derived_cells:
        filters = []
        if skip_zeros:
            filters.append("Value ne 0 and Value ne null and Value ne ''")
        if skip_consolidated_cells:
            filters.append("Consolidated eq false")
        if skip_rule_derived_cells:
            filters.append("RuleDerived eq false")

        filter_cells = " and ".join(filters)

    url = (
        "/Cellsets('{cellset_id}')?$expand="
        "Cells($select={cell_properties}{top_cells}{skip_cells}{filter_cells})".format(
            cellset_id=cellset_id,
            cell_properties=",".join(cell_properties),
            top_cells=f";$top={top}" if top else "",
            skip_cells=f";$skip={skip}" if skip else "",
            filter_cells=f";$filter={filter_cells}" if filter_cells else "",
        )
    )

    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    response = self._rest.GET(url=url, **kwargs)
    return response.json()

extract_cellset_cells_raw_async(cellset_id, max_workers=8, cell_properties=None, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, **kwargs)

Source code in TM1py/Services/CellService.py
def extract_cellset_cells_raw_async(
    self,
    cellset_id: str,
    max_workers: int = 8,
    cell_properties: Iterable[str] = None,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    **kwargs,
):

    if not cell_properties:
        cell_properties = ["Value"]

    if skip_rule_derived_cells:
        cell_properties.append("RuleDerived")
        # necessary due to bug in TM1 11.8: If only RuleDerived is retrieved it occasionally produces wrong results
        cell_properties.append("Updateable")

    if skip_consolidated_cells:
        cell_properties.append("Consolidated")

    if skip_zeros or skip_rule_derived_cells or skip_consolidated_cells:
        if "Ordinal" not in cell_properties:
            cell_properties.append("Ordinal")

    filter_cells = ""
    if skip_zeros or skip_consolidated_cells or skip_rule_derived_cells:
        filters = []
        if skip_zeros:
            filters.append("Value ne 0 and Value ne null and Value ne ''")
        if skip_consolidated_cells:
            filters.append("Consolidated eq false")
        if skip_rule_derived_cells:
            filters.append("RuleDerived eq false")

        filter_cells = " and ".join(filters)

    def _extract_cellset_cells_raw(partition: int = 0, partition_size: int = 0):
        top = partition_size
        skip = partition * partition_size

        url = (
            "/Cellsets('{cellset_id}')?$expand="
            "Cells($select={cell_properties}{top_cells}{skip_cells}{filter_cells})".format(
                cellset_id=cellset_id,
                cell_properties=",".join(cell_properties),
                top_cells=f";$top={top}" if top else "",
                skip_cells=f";$skip={skip}" if skip else "",
                filter_cells=f";$filter={filter_cells}" if filter_cells else "",
            )
        )

        url = add_url_parameters(url, **{"!sandbox": sandbox_name})
        response = self._rest.GET(url=url, **kwargs)

        return response.json()

    async def _extract_cellset_cells_raw_async():
        cellcount = self.extract_cellset_cellcount(
            cellset_id=cellset_id, sandbox_name=sandbox_name, delete_cellset=False
        )
        partition_size = math.ceil(cellcount / max_workers)
        loop = asyncio.get_event_loop()
        result_list = []
        with ThreadPoolExecutor(max_workers) as executor:
            futures = [
                loop.run_in_executor(executor, _extract_cellset_cells_raw, partition, partition_size)
                for partition in range(max_workers)
            ]
            for future in futures:
                result = await future
                result_list = result_list + result["Cells"]
            cells = {"@odata.context": result["@odata.context"], "ID": result["ID"], "Cells": result_list}
        return cells

    cells = asyncio.run(_extract_cellset_cells_raw_async())

    return cells

extract_cellset_composition(cellset_id, sandbox_name=None, **kwargs)

Retrieve composition of dimensions on the axes in the cellset

Parameters:

Name Type Description Default
cellset_id str
required
kwargs
{}
sandbox_name str

str

None

Returns:

Type Description
Tuple[str, List[str], List[str], List[str]]
Source code in TM1py/Services/CellService.py
@tidy_cellset
def extract_cellset_composition(
    self, cellset_id: str, sandbox_name: str = None, **kwargs
) -> Tuple[str, List[str], List[str], List[str]]:
    """Retrieve composition of dimensions on the axes in the cellset

    :param cellset_id:
    :param kwargs:
    :param sandbox_name: str
    :return:
    """
    url = (
        "/Cellsets('{}')?$expand="
        "Cube($select=Name),"
        "Axes($expand=Hierarchies($select=UniqueName))".format(cellset_id)
    )

    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    response = self._rest.GET(url=url, **kwargs)
    response_json = response.json()
    cube = response_json["Cube"]["Name"]

    rows, titles, columns = [], [], []
    if len(response_json["Axes"]) == 1:
        if response_json["Axes"][0]["Hierarchies"]:
            columns = [hierarchy["UniqueName"] for hierarchy in response_json["Axes"][0]["Hierarchies"]]
    else:
        if response_json["Axes"][0]["Hierarchies"]:
            columns = [hierarchy["UniqueName"] for hierarchy in response_json["Axes"][0]["Hierarchies"]]
        if response_json["Axes"][1]["Hierarchies"]:
            rows = [hierarchy["UniqueName"] for hierarchy in response_json["Axes"][1]["Hierarchies"]]
    if len(response_json["Axes"]) > 2:
        titles = [hierarchy["UniqueName"] for hierarchy in response_json["Axes"][2]["Hierarchies"]]
    return cube, titles, rows, columns

extract_cellset_csv(cellset_id, top=None, skip=None, skip_zeros=True, skip_consolidated_cells=False, skip_rule_derived_cells=False, csv_dialect=None, line_separator='\r\n', value_separator=',', sandbox_name=None, include_attributes=False, use_compact_json=False, include_headers=True, mdx_headers=False, **kwargs)

Execute cellset and return only the 'Content', in csv format

Parameters:

Name Type Description Default
cellset_id str

String; ID of existing cellset

required
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

True
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
csv_dialect Dialect

provide all csv output settings through standard library csv.Dialect If not provided dialect is created based on line_separator and value_separator arguments.

None
line_separator str
'\r\n'
value_separator str
','
sandbox_name str

str

None
include_attributes bool

include attribute columns

False
use_compact_json bool

boolean

False
include_headers bool

boolean

True
mdx_headers bool

boolean. Fully qualified hierarchy name as header instead of simple dimension name

False

Returns:

Type Description
str

Raw format from TM1.

Source code in TM1py/Services/CellService.py
def extract_cellset_csv(
    self,
    cellset_id: str,
    top: int = None,
    skip: int = None,
    skip_zeros: bool = True,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    csv_dialect: "csv.Dialect" = None,
    line_separator: str = "\r\n",
    value_separator: str = ",",
    sandbox_name: str = None,
    include_attributes: bool = False,
    use_compact_json: bool = False,
    include_headers: bool = True,
    mdx_headers: bool = False,
    **kwargs,
) -> str:
    """Execute cellset and return only the 'Content', in csv format

    :param cellset_id: String; ID of existing cellset
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param csv_dialect: provide all csv output settings through standard library csv.Dialect
        If not provided dialect is created based on line_separator and value_separator arguments.
    :param line_separator:
    :param value_separator:
    :param sandbox_name: str
    :param include_attributes: include attribute columns
    :param use_compact_json: boolean
    :param include_headers: boolean
    :param mdx_headers: boolean. Fully qualified hierarchy name as header instead of simple dimension name
    :return: Raw format from TM1.
    """
    delete_cellset = kwargs.pop("delete_cellset", True)

    cube, _, rows, columns = self.extract_cellset_composition(
        cellset_id, delete_cellset=False, sandbox_name=sandbox_name, **kwargs
    )

    cellset_dict = self.extract_cellset_raw(
        cellset_id,
        cell_properties=["Value"],
        top=top,
        skip=skip,
        skip_contexts=True,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        delete_cellset=delete_cellset,
        sandbox_name=sandbox_name,
        elem_properties=["Name"],
        member_properties=["Name", "Attributes"] if include_attributes else None,
        use_compact_json=use_compact_json,
        **kwargs,
    )

    return build_csv_from_cellset_dict(
        row_dimensions=rows,
        column_dimensions=columns,
        raw_cellset_as_dict=cellset_dict,
        csv_dialect=csv_dialect,
        line_separator=line_separator,
        value_separator=value_separator,
        top=top,
        include_attributes=include_attributes,
        include_headers=include_headers,
        mdx_headers=mdx_headers,
    )

extract_cellset_csv_iter_json(cellset_id, top=None, skip=None, skip_zeros=True, skip_consolidated_cells=False, skip_rule_derived_cells=False, csv_dialect=None, line_separator='\r\n', value_separator=',', sandbox_name=None, include_attributes=False, mdx_headers=False, **kwargs)

Execute cellset and return only the 'Content', in csv format

Parameters:

Name Type Description Default
cellset_id str

String; ID of existing cellset

required
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

True
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
csv_dialect Dialect

provide all csv output settings through standard library csv.Dialect If not provided dialect is created based on line_separator and value_separator arguments.

None
line_separator str
'\r\n'
value_separator str
','
sandbox_name str

str

None
include_attributes bool

boolean

False
mdx_headers bool

boolean. Fully qualified hierarchy name as header instead of simple dimension name

False

Returns:

Type Description
str

Raw format from TM1.

Source code in TM1py/Services/CellService.py
def extract_cellset_csv_iter_json(
    self,
    cellset_id: str,
    top: int = None,
    skip: int = None,
    skip_zeros: bool = True,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    csv_dialect: "csv.Dialect" = None,
    line_separator: str = "\r\n",
    value_separator: str = ",",
    sandbox_name: str = None,
    include_attributes: bool = False,
    mdx_headers: bool = False,
    **kwargs,
) -> str:
    """Execute cellset and return only the 'Content', in csv format

    :param cellset_id: String; ID of existing cellset
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param csv_dialect: provide all csv output settings through standard library csv.Dialect
        If not provided dialect is created based on line_separator and value_separator arguments.
    :param line_separator:
    :param value_separator:
    :param sandbox_name: str
    :param include_attributes: boolean
    :param mdx_headers: boolean. Fully qualified hierarchy name as header instead of simple dimension name
    :return: Raw format from TM1.
    """
    cube, _, rows, columns = self.extract_cellset_composition(
        cellset_id, delete_cellset=False, sandbox_name=sandbox_name, **kwargs
    )

    cellset_response = self.extract_cellset_raw_response(
        cellset_id,
        cell_properties=["Value", "Ordinal"],
        top=top,
        skip=skip,
        skip_contexts=True,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        delete_cellset=True,
        sandbox_name=sandbox_name,
        member_properties=["Name", "Attributes"] if include_attributes else ["Name"],
        **kwargs,
    )

    if not mdx_headers:
        row_headers = list(dimension_names_from_element_unique_names(rows))
        column_headers = list(dimension_names_from_element_unique_names(columns))
    else:
        row_headers = rows
        column_headers = columns

    if csv_dialect is None:
        csv.register_dialect("TM1py", delimiter=value_separator, lineterminator=line_separator)
        csv_dialect = csv.get_dialect("TM1py")

    # start parsing of JSON directly into CSV
    axes0_list = []
    axes1_list = []
    current_axes = 0
    current_tuple = 0
    current_cell_ordinal = 0
    csv_body = StringIO()
    csv_writer = csv.writer(csv_body, dialect=csv_dialect)
    # handle potential imbalance between number of headers and entries in row
    max_entries_per_row = 0
    least_entries_per_row = 1_000

    parser = ijson.parse(cellset_response.content)
    prefixes_of_interest = [
        "Cells.item.Value",
        "Axes.item.Tuples.item.Members.item.Name",
        "Cells.item.Ordinal",
        "Axes.item.Tuples.item.Ordinal",
        "Cube.Dimensions.item.Name",
        "Axes.item.Ordinal",
    ]

    attributes_prefixes = set()
    attributes_by_dimension = None
    if include_attributes:
        attributes_by_dimension = self._get_attributes_by_dimension(cube)
        for _, attributes in attributes_by_dimension.items():
            for attribute in attributes:
                prefix = f"Axes.item.Tuples.item.Members.item.Attributes.{attribute}"
                prefixes_of_interest.append(prefix)
                attributes_prefixes.add(prefix)

    gen = ((prefix, event, value) for prefix, event, value in parser if prefix in prefixes_of_interest)
    for prefix, event, value in gen:
        if prefix == "Cells.item.Value":
            q, r = divmod(current_cell_ordinal, len(axes0_list))
            axes0_index = r
            axes1_index = q
            if len(axes0_list) == 1 and len(axes0_list[0]) == 0:
                row = axes1_list[axes1_index] + [str(value)]
            # case of no row selection
            elif len(axes1_list) == 0:
                row = axes0_list[axes0_index] + [str(value)]
            else:
                row = axes1_list[axes1_index] + axes0_list[axes0_index] + [str(value)]

            if len(row) > max_entries_per_row:
                max_entries_per_row = len(row)
            if len(row) < least_entries_per_row:
                least_entries_per_row = len(row)

            csv_writer.writerow(row)

        elif (prefix, event) == ("Axes.item.Tuples.item.Members.item.Name", "string"):
            if current_axes == 0:
                axes0_list[current_tuple].append(value)
            else:
                axes1_list[current_tuple].append(value)

        if prefix in attributes_prefixes:
            if event not in ("string", "number"):
                continue

            attribute_name = prefix.split(".")[-1]
            value = str(value)

            if current_axes == 0:
                axes0_list[current_tuple].append(value)
            else:
                axes1_list[current_tuple].append(value)

            # Add header entry for attribute if necessary
            if current_tuple == 0:
                if current_axes == 0:
                    column_headers.insert(len(axes0_list[current_tuple]) - 1, attribute_name)
                else:
                    row_headers.insert(len(axes1_list[current_tuple]) - 1, attribute_name)

        elif (prefix, event) == ("Cells.item.Ordinal", "number"):
            current_cell_ordinal = value

        elif (prefix, event) == ("Axes.item.Tuples.item.Ordinal", "number"):
            current_tuple = value
            if current_axes == 0:
                axes0_list.append(list())
            else:
                axes1_list.append(list())

        elif (prefix, event) == ("Axes.item.Ordinal", "number"):
            current_axes = value

    # comply with prior implementations: return empty string when cellset is empty
    if csv_body.getvalue() == "":
        return ""

    # prepare header
    if include_attributes:
        if not least_entries_per_row == max_entries_per_row == len(row_headers) + len(column_headers) + 1:
            raise ValueError(
                "Invalid response. With 'include_attributes' as True,"
                " Attributes must be requested explicitly as PROPERTIES in the MDX"
            )

    csv_header = StringIO()
    csv_header_writer = csv.writer(csv_header, dialect=csv_dialect)
    csv_header_writer.writerow(row_headers + column_headers + ["Value"])

    cellset_response.close()
    return csv_header.getvalue() + csv_body.getvalue().strip()

extract_cellset_cube_with_dimensions(cellset_id, **kwargs)

Source code in TM1py/Services/CellService.py
@tidy_cellset
def extract_cellset_cube_with_dimensions(self, cellset_id: str, **kwargs):
    url = format_url(
        "/Cellsets('{}')?$expand=Cube($select=Dimensions;$expand=Dimensions($select=Name))", cellset_id
    )

    response = self._rest.GET(url=url, **kwargs)

    return response.json()

extract_cellset_dataframe(cellset_id, top=None, skip=None, skip_zeros=True, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, include_attributes=False, use_iterative_json=False, use_compact_json=False, shaped=False, mdx_headers=False, fillna_numeric_attributes=False, fillna_numeric_attributes_value=0, fillna_string_attributes=False, fillna_string_attributes_value='', **kwargs)

Build pandas data frame from cellset_id

Parameters:

Name Type Description Default
cellset_id str
required
top int

Int, number of cells to return (counting from top)

None
skip int

Int, number of cells to skip (counting from top)

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

True
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
include_attributes bool

include attribute columns

False
use_iterative_json bool

use iterative json parsing to reduce memory consumption significantly. Comes at a cost of 3-5% performance.

False
use_compact_json bool

bool

False
kwargs
{}

Returns:

Type Description
DataFrame
Source code in TM1py/Services/CellService.py
@require_pandas
def extract_cellset_dataframe(
    self,
    cellset_id: str,
    top: int = None,
    skip: int = None,
    skip_zeros: bool = True,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    include_attributes: bool = False,
    use_iterative_json: bool = False,
    use_compact_json: bool = False,
    shaped: bool = False,
    mdx_headers: bool = False,
    fillna_numeric_attributes: bool = False,
    fillna_numeric_attributes_value: Any = 0,
    fillna_string_attributes: bool = False,
    fillna_string_attributes_value: Any = "",
    **kwargs,
) -> "pd.DataFrame":
    """Build pandas data frame from cellset_id

    :param cellset_id:
    :param top: Int, number of cells to return (counting from top)
    :param skip: Int, number of cells to skip (counting from top)
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param include_attributes: include attribute columns
    :param use_iterative_json: use iterative json parsing to reduce memory consumption significantly.
    Comes at a cost of 3-5% performance.
    :param use_compact_json: bool
    :param kwargs:
    :return:
    """
    if use_iterative_json and use_compact_json:
        raise ValueError("Iterative JSON parsing must not be used together with compact JSON")

    if use_iterative_json:
        raw_csv = self.extract_cellset_csv_iter_json(
            cellset_id=cellset_id,
            top=top,
            skip=skip,
            skip_zeros=skip_zeros,
            skip_rule_derived_cells=skip_rule_derived_cells,
            skip_consolidated_cells=skip_consolidated_cells,
            value_separator="~",
            sandbox_name=sandbox_name,
            include_attributes=include_attributes,
            mdx_headers=mdx_headers,
            **kwargs,
        )
    else:
        raw_csv = self.extract_cellset_csv(
            cellset_id=cellset_id,
            top=top,
            skip=skip,
            skip_zeros=skip_zeros,
            skip_rule_derived_cells=skip_rule_derived_cells,
            skip_consolidated_cells=skip_consolidated_cells,
            value_separator="~",
            sandbox_name=sandbox_name,
            include_attributes=include_attributes,
            use_compact_json=use_compact_json,
            mdx_headers=mdx_headers,
            # dont delete cellset if attribute types must be retrieved later
            delete_cellset=not any([fillna_string_attributes, fillna_string_attributes]),
            **kwargs,
        )

    attribute_types_by_dimension = None
    if fillna_string_attributes or fillna_string_attributes:
        attribute_types_by_dimension = self._extract_attribute_types_by_dimension(
            cellset_id=cellset_id, sandbox_name=sandbox_name, delete_cellset=True, **kwargs
        )

    return build_dataframe_from_csv(
        raw_csv,
        sep="~",
        shaped=shaped,
        fillna_numeric_attributes=fillna_numeric_attributes,
        fillna_string_attributes=fillna_string_attributes,
        fillna_numeric_attributes_value=fillna_numeric_attributes_value,
        fillna_string_attributes_value=fillna_string_attributes_value,
        attribute_types_by_dimension=attribute_types_by_dimension,
        **kwargs,
    )

extract_cellset_dataframe_pivot(cellset_id, dropna=False, fill_value=False, sandbox_name=None, use_compact_json=False, **kwargs)

Extract a pivot table (pandas dataframe) from a cellset in TM1

Parameters:

Name Type Description Default
cellset_id str
required
dropna bool
False
fill_value bool
False
kwargs
{}
sandbox_name str

str

None
use_compact_json bool

bool

False

Returns:

Type Description
DataFrame
Source code in TM1py/Services/CellService.py
@require_pandas
def extract_cellset_dataframe_pivot(
    self,
    cellset_id: str,
    dropna: bool = False,
    fill_value: bool = False,
    sandbox_name: str = None,
    use_compact_json: bool = False,
    **kwargs,
) -> "pd.DataFrame":
    """Extract a pivot table (pandas dataframe) from a cellset in TM1

    :param cellset_id:
    :param dropna:
    :param fill_value:
    :param kwargs:
    :param sandbox_name: str
    :param use_compact_json: bool
    :return:
    """

    data = self.extract_cellset(
        cellset_id=cellset_id,
        delete_cellset=False,
        sandbox_name=sandbox_name,
        use_compact_json=use_compact_json,
        **kwargs,
    )

    cube, titles, rows, columns = self.extract_cellset_composition(
        cellset_id=cellset_id, delete_cellset=True, sandbox_name=sandbox_name, **kwargs
    )

    df = build_pandas_dataframe_from_cellset(data, multiindex=False)
    return pd.pivot_table(
        data=df,
        index=[dimension_name_from_element_unique_name(hierarchy_unique_name) for hierarchy_unique_name in rows],
        columns=[
            dimension_name_from_element_unique_name(hierarchy_unique_name) for hierarchy_unique_name in columns
        ],
        values=["Values"],
        dropna=dropna,
        fill_value=fill_value,
        aggfunc="sum",
    )

extract_cellset_dataframe_shaped(cellset_id, sandbox_name=None, display_attribute=False, infer_dtype=False, mdx_headers=False, **kwargs)

Retrieves data from cellset in the shape of the query. Dimensions on rows can be stacked. One dimension must be placed on columns. Title selections are ignored.

Parameters:

Name Type Description Default
cellset_id str

cellset_id

required
sandbox_name str

str

None
display_attribute bool

bool, show element name or first attribute from MDX PROPERTIES clause

False
infer_dtype bool

bool, if True, lets pandas infer dtypes, otherwise all columns will be of type str.

False
Source code in TM1py/Services/CellService.py
@tidy_cellset
@require_pandas
def extract_cellset_dataframe_shaped(
    self,
    cellset_id: str,
    sandbox_name: str = None,
    display_attribute: bool = False,
    infer_dtype: bool = False,
    mdx_headers: bool = False,
    **kwargs,
) -> "pd.DataFrame":
    """Retrieves data from cellset in the shape of the query.
    Dimensions on rows can be stacked. One dimension must be placed on columns. Title selections are ignored.

    :param cellset_id: cellset_id
    :param sandbox_name: str
    :param display_attribute: bool, show element name or first attribute from MDX PROPERTIES clause
    :param infer_dtype: bool, if True, lets pandas infer dtypes, otherwise all columns will be of type str.

    """
    url = (
        "/Cellsets('{}')?$expand="
        "Axes($filter=Ordinal eq 0 or Ordinal eq 1;$expand=Tuples("
        "$expand=Members($select=Name{})),Hierarchies($select=Name,Dimension;$expand=Dimension($select=Name))),"
        "Cells($select=Value)".format(cellset_id, ",Attributes" if display_attribute else "")
    )

    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    response = self._rest.GET(url=url, **kwargs)
    response_json = response.json()

    column_headers = list()
    for column_tuple in response_json["Axes"][0]["Tuples"]:
        member = column_tuple["Members"][0]
        if display_attribute and member["Attributes"]:
            attribute_values = list(member["Attributes"].values())
            column_headers.append(attribute_values[0])
        else:
            column_headers.append(member["Name"])

    rows = response_json["Axes"][1]["Tuples"]
    if mdx_headers:
        row_headers = [
            f"[{hierarchy['Dimension']['Name']}].[{hierarchy['Name']}]"
            for hierarchy in response_json["Axes"][1]["Hierarchies"]
        ]
    else:
        row_headers = [hierarchy["Dimension"]["Name"] for hierarchy in response_json["Axes"][1]["Hierarchies"]]
    cell_values = [cell["Value"] for cell in response_json["Cells"]]

    headers = row_headers + column_headers
    body = []

    number_rows = len(rows)
    # avoid division by zero
    if not number_rows:
        return pd.DataFrame(body, columns=headers)

    number_cells = len(cell_values)
    number_columns = int(number_cells / number_rows)

    element_names_by_row = list()
    for row_tuple in rows:
        row = list()
        for member in row_tuple["Members"]:
            if display_attribute and member["Attributes"]:
                attribute_values = list(member["Attributes"].values())
                row.append(attribute_values[0])
            else:
                row.append(member["Name"])

        element_names_by_row.append(tuple(row))

    if not number_columns:
        return pd.DataFrame(data=element_names_by_row, columns=headers)

    cell_values_by_row = [
        cell_values[cell_counter : cell_counter + number_columns]
        for cell_counter in range(0, number_cells, number_columns)
    ]

    for element_tuple, cells in zip(element_names_by_row, cell_values_by_row):
        body.append(list(element_tuple) + cells)
    if infer_dtype:
        return pd.DataFrame(body, columns=headers)
    else:
        return pd.DataFrame(body, columns=headers, dtype=str)

extract_cellset_metadata_raw(cellset_id, elem_properties=None, member_properties=None, top=None, skip=None, skip_contexts=False, include_hierarchies=False, sandbox_name=None, delete_cellset=False, **kwargs)

Source code in TM1py/Services/CellService.py
@tidy_cellset
def extract_cellset_metadata_raw(
    self,
    cellset_id: str,
    elem_properties: Iterable[str] = None,
    member_properties: Iterable[str] = None,
    top: int = None,
    skip: int = None,
    skip_contexts: bool = False,
    include_hierarchies: bool = False,
    sandbox_name: str = None,
    delete_cellset: bool = False,
    **kwargs,
):

    # select Name property if member_properties is None or empty.
    # Necessary, as tm1 default behaviour is to return all properties if no $select is specified in the request.
    if member_properties is None or len(list(member_properties)) == 0:
        member_properties = ["Name"]
    select_member_properties = "$select={}".format(",".join(member_properties))

    expand_elem_properties = (
        ";$expand=Element($select={elem_properties})".format(elem_properties=",".join(elem_properties))
        if elem_properties is not None and len(list(elem_properties)) > 0
        else ""
    )

    if include_hierarchies:
        expand_hierarchies = "Hierarchies($select=Name;$expand=Dimension($select=Name)),"
    else:
        expand_hierarchies = ""

    filter_axis = "$filter=Ordinal ne 2;" if skip_contexts else ""

    # top_tuples parameter is used as an optimization trick:
    # if top_cells is set to N => it will be sufficient to get only the first N tuples in Axes, top_tuples does this
    # if skip_cells is used => trick not applicable, all tuples must be extracted

    url = (
        "/Cellsets('{cellset_id}')?$expand="
        "Cube($select=Name;$expand=Dimensions($select=Name)),"
        "Axes({filter_axis}$expand={hierarchies}Tuples($expand=Members({select_member_properties}"
        "{expand_elem_properties}){top_tuples}))".format(
            cellset_id=cellset_id,
            top_tuples=f";$top={top}" if top and not skip else "",
            filter_axis=filter_axis,
            hierarchies=expand_hierarchies,
            select_member_properties=select_member_properties,
            expand_elem_properties=expand_elem_properties,
        )
    )

    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    response = self._rest.GET(url=url, **kwargs)
    return response.json()

extract_cellset_partition(cellset_id, partition_start_ordinal, partition_end_ordinal, cell_properties=None, top=None, skip=None, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None)

Method to extract a cellset partition. Cellset partitions are a collection of cellset cells where they have a defined top left boundary, and bottom right boundary. Read More: https://www.ibm.com/docs/en/planning-analytics/2.0.0?topic=data-cellsets#dg_tm1_odata_get_cells__title__1

Parameters:

Name Type Description Default
partition_start_ordinal int

top left cell boundary

required
partition_end_ordinal int

bottom right cell boundary

required
cell_properties Iterable[str]

cell properties to include, default: Orginal, Value

None
top int

Integer limiting the number of cells and the number or rows returned

None
skip int

Integer limiting the number of cells and the number or rows returned

None
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None

Returns:

Type Description
Dict

CellSet Dictionary

Source code in TM1py/Services/CellService.py
def extract_cellset_partition(
    self,
    cellset_id: str,
    partition_start_ordinal: int,
    partition_end_ordinal: int,
    cell_properties: Iterable[str] = None,
    top: int = None,
    skip: int = None,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
) -> Dict:
    """
    Method to extract a cellset partition. Cellset partitions are a collection of cellset cells where they have
    a defined top left boundary, and bottom right boundary.
    Read More: https://www.ibm.com/docs/en/planning-analytics/2.0.0?topic=data-cellsets#dg_tm1_odata_get_cells__title__1
    :param partition_start_ordinal: top left cell boundary
    :param partition_end_ordinal: bottom right cell boundary
    :param cell_properties: cell properties to include, default: Orginal, Value
    :param top: Integer limiting the number of cells and the number or rows returned
    :param skip: Integer limiting the number of cells and the number or rows returned
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :return: CellSet Dictionary
    """

    if not cell_properties:
        cell_properties = ["Value", "Ordinal"]

    if skip_rule_derived_cells:
        cell_properties.append("RuleDerived")
        # necessary due to bug in TM1 11.8: If only RuleDerived is retrieved it occasionally produces wrong results
        cell_properties.append("Updateable")

    if skip_consolidated_cells:
        cell_properties.append("Consolidated")

    filter_cells = ""
    if skip_zeros or skip_consolidated_cells or skip_rule_derived_cells:
        filters = []
        if skip_zeros:
            filters.append("Value ne 0 and Value ne null and Value ne ''")
        if skip_consolidated_cells:
            filters.append("Consolidated eq false")
        if skip_rule_derived_cells:
            filters.append("RuleDerived eq false")

        filter_cells = " and ".join(filters)

    url = (
        "/Cellsets('{cellset_id}')/tm1.GetPartition{cell_partition}?$select={cell_properties}{"
        "top_cells}{skip_cells}{filter_cells}"
    ).format(
        cellset_id=cellset_id,
        cell_partition=f"(Begin={partition_start_ordinal}, End={partition_end_ordinal})",
        cell_properties=",".join(cell_properties),
        top_cells=f"&$top={top}" if top else "",
        skip_cells=f"&$skip={skip}" if skip else "",
        filter_cells=f"&$filter={filter_cells}" if filter_cells else "",
    )

    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    response = self._rest.GET(url=url)
    return response.json()["value"]

extract_cellset_raw(cellset_id, cell_properties=None, elem_properties=None, member_properties=None, top=None, skip=None, skip_contexts=False, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, include_hierarchies=False, use_compact_json=False, **kwargs)

Extract full cellset data and return the raw data from TM1

Parameters:

Name Type Description Default
cellset_id str

String; ID of existing cellset

required
cell_properties Iterable[str]

List of properties to be queried from cells. E.g. ['Value', 'RuleDerived', ...]

None
elem_properties Iterable[str]

List of properties to be queried from elements. E.g. ['UniqueName','Attributes', ...]

None
member_properties Iterable[str]

List properties to be queried from the member. E.g. ['Name', 'UniqueName']

None
top int

Integer limiting the number of cells and the number or rows returned

None
skip int

Integer limiting the number of cells and the number or rows returned

None
skip_contexts bool
False
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
include_hierarchies bool

retrieve Hierarchies property on Axes

False
use_compact_json bool

bool

False

Returns:

Type Description
Dict

Raw format from TM1.

Source code in TM1py/Services/CellService.py
@tidy_cellset
def extract_cellset_raw(
    self,
    cellset_id: str,
    cell_properties: Iterable[str] = None,
    elem_properties: Iterable[str] = None,
    member_properties: Iterable[str] = None,
    top: int = None,
    skip: int = None,
    skip_contexts: bool = False,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    include_hierarchies: bool = False,
    use_compact_json: bool = False,
    **kwargs,
) -> Dict:
    """Extract full cellset data and return the raw data from TM1

    :param cellset_id: String; ID of existing cellset
    :param cell_properties: List of properties to be queried from cells. E.g. ['Value', 'RuleDerived', ...]
    :param elem_properties: List of properties to be queried from elements. E.g. ['UniqueName','Attributes', ...]
    :param member_properties: List properties to be queried from the member. E.g. ['Name', 'UniqueName']
    :param top: Integer limiting the number of cells and the number or rows returned
    :param skip: Integer limiting the number of cells and the number or rows returned
    :param skip_contexts:
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param include_hierarchies: retrieve Hierarchies property on Axes
    :param use_compact_json: bool
    :return: Raw format from TM1.
    """
    if not use_compact_json:
        cellset_response = self.extract_cellset_raw_response(
            cellset_id,
            cell_properties,
            elem_properties,
            member_properties,
            top,
            skip,
            skip_contexts,
            skip_zeros,
            skip_consolidated_cells,
            skip_rule_derived_cells,
            sandbox_name,
            include_hierarchies,
            **kwargs,
        )

        return cellset_response.json()

    metadata = self.extract_cellset_metadata_raw(
        cellset_id=cellset_id,
        elem_properties=elem_properties,
        member_properties=member_properties,
        top=top,
        skip=skip,
        skip_contexts=skip_contexts,
        include_hierarchies=include_hierarchies,
        sandbox_name=sandbox_name,
        **{**kwargs, "delete_cellset": False},
    )
    cells = self.extract_cellset_cells_raw(
        cellset_id=cellset_id,
        cell_properties=cell_properties,
        top=top,
        skip=skip,
        skip_zeros=skip_zeros,
        skip_consolidated_cells=skip_consolidated_cells,
        skip_rule_derived_cells=skip_rule_derived_cells,
        sandbox_name=sandbox_name,
        use_compact_json=use_compact_json,
        **kwargs,
    )

    # Combine metadata and cells back into a single object
    return {**metadata, **cells}

extract_cellset_raw_response(cellset_id, cell_properties=None, elem_properties=None, member_properties=None, top=None, skip=None, skip_contexts=False, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, sandbox_name=None, include_hierarchies=False, **kwargs)

Extract full cellset data and return the raw data from TM1

Parameters:

Name Type Description Default
cellset_id str

String; ID of existing cellset

required
cell_properties Iterable[str]

List of properties to be queried from cells. E.g. ['Value', 'RuleDerived', ...]

None
elem_properties Iterable[str]

List of properties to be queried from elements. E.g. ['UniqueName','Attributes', ...]

None
member_properties Iterable[str]

List properties to be queried from the member. E.g. ['Name', 'UniqueName']

None
top int

Integer limiting the number of cells and the number or rows returned

None
skip int

Integer limiting the number of cells and the number or rows returned

None
skip_contexts bool
False
skip_zeros bool

skip zeros in cellset (irrespective of zero suppression in MDX / view)

False
skip_consolidated_cells bool

skip consolidated cells in cellset

False
skip_rule_derived_cells bool

skip rule derived cells in cellset

False
sandbox_name str

str

None
include_hierarchies bool

retrieve Hierarchies property on Axes

False

Returns:

Type Description
Response

Raw format from TM1.

Source code in TM1py/Services/CellService.py
def extract_cellset_raw_response(
    self,
    cellset_id: str,
    cell_properties: Iterable[str] = None,
    elem_properties: Iterable[str] = None,
    member_properties: Iterable[str] = None,
    top: int = None,
    skip: int = None,
    skip_contexts: bool = False,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    sandbox_name: str = None,
    include_hierarchies: bool = False,
    **kwargs,
) -> Response:
    """Extract full cellset data and return the raw data from TM1

    :param cellset_id: String; ID of existing cellset
    :param cell_properties: List of properties to be queried from cells. E.g. ['Value', 'RuleDerived', ...]
    :param elem_properties: List of properties to be queried from elements. E.g. ['UniqueName','Attributes', ...]
    :param member_properties: List properties to be queried from the member. E.g. ['Name', 'UniqueName']
    :param top: Integer limiting the number of cells and the number or rows returned
    :param skip: Integer limiting the number of cells and the number or rows returned
    :param skip_contexts:
    :param skip_zeros: skip zeros in cellset (irrespective of zero suppression in MDX / view)
    :param skip_consolidated_cells: skip consolidated cells in cellset
    :param skip_rule_derived_cells: skip rule derived cells in cellset
    :param sandbox_name: str
    :param include_hierarchies: retrieve Hierarchies property on Axes
    :return: Raw format from TM1.
    """
    if not cell_properties:
        cell_properties = ["Value"]

    if skip_rule_derived_cells:
        cell_properties.append("RuleDerived")
        # necessary due to bug in TM1 11.8: If only RuleDerived is retrieved it occasionally produces wrong results
        cell_properties.append("Updateable")

    if skip_consolidated_cells:
        cell_properties.append("Consolidated")

    if skip or skip_zeros or skip_rule_derived_cells or skip_consolidated_cells:
        if "Ordinal" not in cell_properties:
            cell_properties.append("Ordinal")

    # select Name property if member_properties is None or empty.
    # Necessary, as tm1 default behaviour is to return all properties if no $select is specified in the request.
    if member_properties is None or len(list(member_properties)) == 0:
        member_properties = ["Name"]
    select_member_properties = "$select={}".format(",".join(member_properties))

    expand_elem_properties = (
        ";$expand=Element($select={elem_properties})".format(elem_properties=",".join(elem_properties))
        if elem_properties is not None and len(list(elem_properties)) > 0
        else ""
    )

    filter_axis = "$filter=Ordinal ne 2;" if skip_contexts else ""

    filter_cells = ""
    if skip_zeros or skip_consolidated_cells or skip_rule_derived_cells:
        filters = []
        if skip_zeros:
            filters.append("Value ne 0 and Value ne null and Value ne ''")
        if skip_consolidated_cells:
            filters.append("Consolidated eq false")
        if skip_rule_derived_cells:
            filters.append("RuleDerived eq false")

        filter_cells = " and ".join(filters)

    if include_hierarchies:
        expand_hierarchies = "Hierarchies($select=Name;$expand=Dimension($select=Name)),"
    else:
        expand_hierarchies = ""

    # top_tuples parameter is used as an optimization trick:
    # if top_cells is set to N => it will be sufficient to get only the first N tuples in Axes, top_tuples does this
    # if skip_cells is used => trick not applicable, all tuples must be extracted

    url = (
        "/Cellsets('{cellset_id}')?$expand="
        "Cube($select=Name;$expand=Dimensions($select=Name)),"
        "Axes({filter_axis}$expand={hierarchies}Tuples($expand=Members({select_member_properties}"
        "{expand_elem_properties}){top_tuples})),"
        "Cells($select={cell_properties}{top_cells}{skip_cells}{filter_cells})".format(
            cellset_id=cellset_id,
            top_tuples=f";$top={top}" if top and not skip else "",
            cell_properties=",".join(cell_properties),
            filter_axis=filter_axis,
            hierarchies=expand_hierarchies,
            select_member_properties=select_member_properties,
            expand_elem_properties=expand_elem_properties,
            top_cells=f";$top={top}" if top else "",
            skip_cells=f";$skip={skip}" if skip else "",
            filter_cells=f";$filter={filter_cells}" if filter_cells else "",
        )
    )
    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    response = self._rest.GET(url=url, **kwargs)
    return response

extract_cellset_rows_and_values(cellset_id, element_unique_names=True, sandbox_name=None, **kwargs)

Retrieve row element names and values in a case and space insensitive dictionary

Parameters:

Name Type Description Default
cellset_id str
required
element_unique_names bool
True
kwargs
{}
sandbox_name str

str

None

Returns:

Type Description
CaseAndSpaceInsensitiveTuplesDict
Source code in TM1py/Services/CellService.py
@tidy_cellset
def extract_cellset_rows_and_values(
    self, cellset_id: str, element_unique_names: bool = True, sandbox_name: str = None, **kwargs
) -> CaseAndSpaceInsensitiveTuplesDict:
    """Retrieve row element names and values in a case and space insensitive dictionary

    :param cellset_id:
    :param element_unique_names:
    :param kwargs:
    :param sandbox_name: str
    :return:
    """
    url = (
        "/Cellsets('{}')?$expand="
        "Axes($filter=Ordinal eq 1;$expand=Tuples("
        "$expand=Members($select=Element;$expand=Element($select={})))),"
        "Cells($select=Value)".format(cellset_id, "UniqueName" if element_unique_names else "Name")
    )
    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    response = self._rest.GET(url=url, **kwargs)
    response_json = response.json()
    rows = response_json["Axes"][0]["Tuples"]
    cell_values = [cell["Value"] for cell in response_json["Cells"]]

    result = CaseAndSpaceInsensitiveTuplesDict()

    number_rows = len(rows)
    # avoid division by zero
    if not number_rows:
        return result
    number_cells = len(cell_values)
    number_columns = int(number_cells / number_rows)

    cell_values_by_row = [
        cell_values[cell_counter : cell_counter + number_columns]
        for cell_counter in range(0, number_cells, number_columns)
    ]
    element_names_by_row = [
        tuple(member["Element"]["UniqueName" if element_unique_names else "Name"] for member in tupl["Members"])
        for tupl in rows
    ]
    for element_tuple, cells in zip(element_names_by_row, cell_values_by_row):
        result[element_tuple] = cells
    return result

extract_cellset_values(cellset_id, sandbox_name=None, use_compact_json=False, skip_zeros=False, skip_consolidated_cells=False, skip_rule_derived_cells=False, **kwargs)

Extract cellset data and return only the cells and values

Parameters:

Name Type Description Default
cellset_id str

String; ID of existing cellset

required
sandbox_name str

str

None
use_compact_json bool

bool

False
skip_zeros bool

bool

False
skip_consolidated_cells bool

bool

False
skip_rule_derived_cells bool

bool

False

Returns:

Type Description
List[Union[str, float]]

Raw format from TM1.

Source code in TM1py/Services/CellService.py
@tidy_cellset
@odata_compact_json(return_as_dict=False)
def extract_cellset_values(
    self,
    cellset_id: str,
    sandbox_name: str = None,
    use_compact_json: bool = False,
    skip_zeros: bool = False,
    skip_consolidated_cells: bool = False,
    skip_rule_derived_cells: bool = False,
    **kwargs,
) -> List[Union[str, float]]:
    """Extract cellset data and return only the cells and values

    :param cellset_id: String; ID of existing cellset
    :param sandbox_name: str
    :param use_compact_json: bool
    :param skip_zeros: bool
    :param skip_consolidated_cells: bool
    :param skip_rule_derived_cells: bool
    :return: Raw format from TM1.
    """

    filter_cells = ""
    if skip_zeros or skip_consolidated_cells or skip_rule_derived_cells:
        filters = []
        if skip_zeros:
            filters.append("Value ne 0 and Value ne null and Value ne ''")
        if skip_consolidated_cells:
            filters.append("Consolidated eq false")
        if skip_rule_derived_cells:
            filters.append("RuleDerived eq false")

        filter_cells = " and ".join(filters)

    url = format_url(
        "/Cellsets('{}')?$expand=Cells($select=Value{})",
        cellset_id,
        f";$filter={filter_cells}" if filter_cells else "",
    )
    if sandbox_name:
        url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    response = self._rest.GET(url=url, **kwargs)

    if not use_compact_json:
        return [cell["Value"] for cell in response.json()["Cells"]]

    return response.json()

generate_enable_sandbox_ti(sandbox_name)

Source code in TM1py/Services/CellService.py
def generate_enable_sandbox_ti(self, sandbox_name):
    if self._rest.sandboxing_disabled:
        enable_sandbox = ""

    elif sandbox_name:
        if not self.sandbox_exists(sandbox_name):
            raise ValueError(f"Sandbox '{sandbox_name}' does not exist")

        enable_sandbox = f"ServerActiveSandboxSet('{sandbox_name}');SetUseActiveSandboxProperty(1);"

    else:
        enable_sandbox = "ServerActiveSandboxSet('');SetUseActiveSandboxProperty(0);"
    return enable_sandbox

get_cellset_cells_count(mdx)

Execute MDX in order to understand how many cells are in a cellset

Parameters:

Name Type Description Default
mdx str

MDX Query, as string

required

Returns:

Type Description
int

Number of Cells in the CellSet

Source code in TM1py/Services/CellService.py
def get_cellset_cells_count(self, mdx: str) -> int:
    """Execute MDX in order to understand how many cells are in a cellset

    :param mdx: MDX Query, as string
    :return: Number of Cells in the CellSet
    """
    warnings.simplefilter("always", PendingDeprecationWarning)
    warnings.warn("Function deprecated. Use execute_mdx_cellcount(self, mdx) instead.", PendingDeprecationWarning)
    warnings.simplefilter("default", PendingDeprecationWarning)
    return self.execute_mdx_cellcount(mdx)

get_cube_service()

Source code in TM1py/Services/CellService.py
def get_cube_service(self):
    from TM1py import CubeService

    return CubeService(self._rest)

get_dimension_names_for_writing(cube_name, **kwargs)

Get dimensions of a cube. Skip sandbox dimension

Parameters:

Name Type Description Default
cube_name str
required
kwargs
{}

Returns:

Type Description
List[str]
Source code in TM1py/Services/CellService.py
def get_dimension_names_for_writing(self, cube_name: str, **kwargs) -> List[str]:
    """Get dimensions of a cube. Skip sandbox dimension

    :param cube_name:
    :param kwargs:
    :return:
    """
    from TM1py.Services import CubeService

    cube_service = CubeService(self._rest)
    dimensions = cube_service.get_dimension_names(cube_name, True, **kwargs)
    return dimensions

get_element_service()

Source code in TM1py/Services/CellService.py
def get_element_service(self):
    from TM1py import ElementService

    return ElementService(self._rest)

get_elements_from_all_measure_hierarchies(cube_name)

Source code in TM1py/Services/CellService.py
def get_elements_from_all_measure_hierarchies(self, cube_name: str) -> Dict[str, str]:
    from TM1py.Services.CubeService import CubeService
    from TM1py.Services.ElementService import ElementService

    cube_service = CubeService(self._rest)
    element_service = ElementService(self._rest)

    measure_dimension = cube_service.get_measure_dimension(cube_name=cube_name)
    return element_service.get_element_types_from_all_hierarchies(dimension_name=measure_dimension)

get_error_log_file_content(file_name, **kwargs)

Source code in TM1py/Services/CellService.py
def get_error_log_file_content(self, file_name: str, **kwargs) -> str:
    from TM1py import ProcessService

    process_service = ProcessService(self._rest)

    return process_service.get_error_log_file_content(file_name, **kwargs)

get_value(cube_name, elements=None, dimensions=None, sandbox_name=None, element_separator=',', hierarchy_separator='&&', hierarchy_element_separator='::', **kwargs)

Returns cube value from specified coordinates

Parameters:

Name Type Description Default
cube_name str

Name of the cube

required
elements Union[str, Iterable]

Describes the Dimension-Hierarchy-Element arrangement - Example: "Hierarchy1::Element1 && Hierarchy2::Element4, Element9, Element2" - Dimensions are not specified! They are derived from the position. - The , separates the element-selections - If more than one hierarchy is selected per dimension && splits the elementselections - If no Hierarchy is specified. Default Hierarchy will be addressed or Iterable of type mdxpy.Member or similar - Dimension names must be provided in this case! Example: [(Dimension1, Element1), (Dimension2, Element2), (Dimension3, Element3)] - Hierarchys can be included. Example: [(Dimension1, Hierarchy1, Element1), (Dimension1, Hierarchy2, Element2), (Dimension2, Element3)]

None
dimensions List[str]

List of dimension names in correct order

None
sandbox_name str

str

None
element_separator str

Alternative separator for the element selections

','
hierarchy_separator str

Alternative separator for multiple hierarchies

'&&'
hierarchy_element_separator str

Alternative separator between hierarchy name and element name

'::'

Returns:

Type Description
Union[str, float]
Source code in TM1py/Services/CellService.py
def get_value(
    self,
    cube_name: str,
    elements: Union[str, Iterable] = None,
    dimensions: List[str] = None,
    sandbox_name: str = None,
    element_separator: str = ",",
    hierarchy_separator: str = "&&",
    hierarchy_element_separator: str = "::",
    **kwargs,
) -> Union[str, float]:
    """Returns cube value from specified coordinates

    :param cube_name: Name of the cube
    :param elements: Describes the Dimension-Hierarchy-Element arrangement
        - Example: "Hierarchy1::Element1 && Hierarchy2::Element4, Element9, Element2"
        - Dimensions are not specified! They are derived from the position.
        - The , separates the element-selections
        - If more than one hierarchy is selected per dimension && splits the elementselections
        - If no Hierarchy is specified. Default Hierarchy will be addressed
    or
    Iterable of type mdxpy.Member or similar
        - Dimension names must be provided in this case! Example: [(Dimension1, Element1), (Dimension2, Element2), (Dimension3, Element3)]
        - Hierarchys can be included. Example: [(Dimension1, Hierarchy1, Element1), (Dimension1, Hierarchy2, Element2), (Dimension2, Element3)]
    :param dimensions: List of dimension names in correct order
    :param sandbox_name: str
    :param element_separator: Alternative separator for the element selections
    :param hierarchy_separator: Alternative separator for multiple hierarchies
    :param hierarchy_element_separator: Alternative separator between hierarchy name and element name
    :return:
    """
    mdx_template = "SELECT {} ON ROWS, {} ON COLUMNS FROM [{}]"
    mdx_strings_list = []

    # Keep backward compatibility with the earlier used "element_string" parameter
    if elements is None and "element_string" in kwargs:
        elements = kwargs.pop("element_string")

    if not dimensions:
        dimensions = self.get_dimension_names_for_writing(cube_name=cube_name)

    # Create MDXpy Member from the element string and get the unique name
    # The unique name can be used to build the MDX query directly
    if isinstance(elements, str):
        element_selections = elements.split(element_separator)
        for dimension_name, element_selection in zip(dimensions, element_selections):
            if hierarchy_separator not in element_selection:
                if hierarchy_element_separator in element_selection:
                    hierarchy_name, element_name = element_selection.split(hierarchy_element_separator)
                else:
                    hierarchy_name = dimension_name
                    element_name = element_selection

                element_definition = Member.of(dimension_name, hierarchy_name, element_name)
                mdx_strings_list.append("{" + element_definition.unique_name + "}")

            else:
                for element_selection_part in element_selection.split(hierarchy_separator):
                    hierarchy_name, element_name = element_selection_part.split(hierarchy_element_separator)
                    element_definition = Member.of(dimension_name, hierarchy_name, element_name)
                    mdx_strings_list.append("{" + element_definition.unique_name + "}")

    else:
        # Create MDXpy Member from the Iterator entries
        for element_definition in elements:
            if not isinstance(element_definition, Member):
                element_definition = Member.of(*element_definition)
            mdx_strings_list.append("{" + element_definition.unique_name + "}")

    # Build the MDX query
    # Only the last element is used as the MDX ON COLUMN statement
    mdx_rows = "*".join(mdx_strings_list[:-1])
    mdx_columns = mdx_strings_list[-1]
    mdx = mdx_template.format(mdx_rows, mdx_columns, cube_name)

    # Execute MDX
    cellset = dict(self.execute_mdx(mdx=mdx, sandbox_name=sandbox_name, **kwargs))
    return next(iter(cellset.values()))["Value"]

get_values(cube_name, element_sets=None, dimensions=None, sandbox_name=None, element_separator=',', hierarchy_separator='&&', hierarchy_element_separator='::', **kwargs)

Returns list of cube values from specified coordinates list. will be in same order as original list

Parameters:

Name Type Description Default
cube_name str

Name of the cube

required
element_sets Iterable[Iterable[str]]

Set of coordinates where each element is provided in the correct dimension order. [('2024', 'Actual', 'London', 'P02), ('2024', 'Forecast', 'Berlin', 'P03)]

None
dimensions List[str]

Dimension names in correct order

None
sandbox_name str

str

None
element_separator str

Alternative separator for the element selections

','
hierarchy_separator str

Alternative separator for multiple hierarchies

'&&'
hierarchy_element_separator str

Alternative separator between hierarchy name and element name

'::'

Returns:

Type Description
List
Source code in TM1py/Services/CellService.py
def get_values(
    self,
    cube_name: str,
    element_sets: Iterable[Iterable[str]] = None,
    dimensions: List[str] = None,
    sandbox_name: str = None,
    element_separator: str = ",",
    hierarchy_separator: str = "&&",
    hierarchy_element_separator: str = "::",
    **kwargs,
) -> List:
    """Returns list of cube values from specified coordinates list.  will be in same order as original list

    :param cube_name: Name of the cube
    :param element_sets: Set of coordinates where each element is provided in the correct dimension order.
    [('2024', 'Actual', 'London', 'P02), ('2024', 'Forecast', 'Berlin', 'P03)]
    :param dimensions: Dimension names in correct order
    :param sandbox_name: str
    :param element_separator: Alternative separator for the element selections
    :param hierarchy_separator: Alternative separator for multiple hierarchies
    :param hierarchy_element_separator: Alternative separator between hierarchy name and element name
    :return:
    """

    if not dimensions:
        dimensions = self.get_dimension_names_for_writing(cube_name=cube_name)

    q = MdxBuilder.from_cube(cube_name)

    for elements in element_sets:
        members = []
        element_selections = elements.split(element_separator)
        for dimension_name, element_selection in zip(dimensions, element_selections):
            if hierarchy_separator not in element_selection:
                if hierarchy_element_separator in element_selection:
                    hierarchy_name, element_name = element_selection.split(hierarchy_element_separator)
                else:
                    hierarchy_name = dimension_name
                    element_name = element_selection

                member = Member.of(dimension_name, hierarchy_name, element_name)
                members.append(member)
            else:
                for element_selection_part in element_selection.split(hierarchy_separator):
                    hierarchy_name, element_name = element_selection_part.split(hierarchy_element_separator)
                    member = Member.of(dimension_name, hierarchy_name, element_name)
                    members.append(member)

        q.add_member_tuple_to_columns(MdxTuple(members))

    # Execute MDX
    return self.execute_mdx_values(mdx=q.to_mdx(), sandbox_name=sandbox_name, **kwargs)

get_view_content(cube_name, view_name, cell_properties=None, private=False, top=None)

Source code in TM1py/Services/CellService.py
def get_view_content(
    self,
    cube_name: str,
    view_name: str,
    cell_properties: Iterable[str] = None,
    private: bool = False,
    top: int = None,
):
    warnings.simplefilter("always", PendingDeprecationWarning)
    warnings.warn("Function deprecated. Use execute_view instead.", PendingDeprecationWarning)
    warnings.simplefilter("default", PendingDeprecationWarning)
    return self.execute_view(cube_name, view_name, private, cell_properties, top)

relative_proportional_spread(value, cube, unique_element_names, reference_unique_element_names, reference_cube=None, sandbox_name=None, **kwargs)

Execute relative proportional spread

Parameters:

Name Type Description Default
value float

value to be spread

required
cube str

name of the cube

required
unique_element_names Iterable[str]

target cell coordinates as unique element names (e.g. ["[d1].[c1]","[d2].[e3]"])

required
reference_cube str

name of the reference cube. Can be None

None
reference_unique_element_names Iterable[str]

reference cell coordinates as unique element names

required
sandbox_name str

str

None

Returns:

Type Description
Response
Source code in TM1py/Services/CellService.py
def relative_proportional_spread(
    self,
    value: float,
    cube: str,
    unique_element_names: Iterable[str],
    reference_unique_element_names: Iterable[str],
    reference_cube: str = None,
    sandbox_name: str = None,
    **kwargs,
) -> Response:
    """Execute relative proportional spread

    :param value: value to be spread
    :param cube: name of the cube
    :param unique_element_names: target cell coordinates as unique element names (e.g. ["[d1].[c1]","[d2].[e3]"])
    :param reference_cube: name of the reference cube. Can be None
    :param reference_unique_element_names: reference cell coordinates as unique element names
    :param sandbox_name: str
    :return:
    """
    mdx = """
    SELECT
    {{ {rows} }} ON 0
    FROM [{cube}]
    """.format(
        rows="}*{".join(unique_element_names), cube=cube
    )
    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name, **kwargs)

    payload = {
        "BeginOrdinal": 0,
        "Value": "RP" + str(value),
        "ReferenceCell@odata.bind": list(),
        "ReferenceCube@odata.bind": format_url("Cubes('{}')", reference_cube if reference_cube else cube),
    }
    for unique_element_name in reference_unique_element_names:
        payload["ReferenceCell@odata.bind"].append(
            format_url(
                "Dimensions('{}')/Hierarchies('{}')/Elements('{}')",
                *Utils.dimension_hierarchy_element_tuple_from_unique_name(unique_element_name),
            )
        )

    return self._post_against_cellset(
        cellset_id=cellset_id, payload=payload, delete_cellset=True, sandbox_name=sandbox_name, **kwargs
    )

sandbox_exists(sandbox_name)

Source code in TM1py/Services/CellService.py
def sandbox_exists(self, sandbox_name) -> bool:
    sandbox_service = SandboxService(self._rest)
    return sandbox_service.exists(sandbox_name)

trace_cell_calculation(cube_name, elements, dimensions=None, sandbox_name=None, depth=1, element_separator=',', hierarchy_separator='&&', hierarchy_element_separator='::', **kwargs)

Trace cell calculation at specified coordinates

Parameters:

Name Type Description Default
cube_name str

name of the target cube

required
elements Union[Iterable, str]

string "Hierarchy1::Element1 && Hierarchy2::Element4, Element9, Element2" - Dimensions are not specified! They are derived from the position. - The , separates the element-selections - If more than one hierarchy is selected per dimension && splits the elementselections - If no Hierarchy is specified. Default Hierarchy will be addressed or Iterable [Element1, Element2, Element3]

required
dimensions Iterable[str]

optional. Dimension names in their natural order. Will speed up the execution!

None
sandbox_name str

str

None
depth int

optional. Depth of the component trace that will be returned. Deeper traces take longer

1
element_separator str

Alternative separator for the elements, if elements are passed as string

','
hierarchy_separator str

Alternative separator for multiple hierarchies, if elements are passed as string

'&&'
hierarchy_element_separator str

Alternative separator between hierarchy name and element name, if elements are passed as string

'::'

Returns:

Type Description
Dict

trace json string

Source code in TM1py/Services/CellService.py
def trace_cell_calculation(
    self,
    cube_name: str,
    elements: Union[Iterable, str],
    dimensions: Iterable[str] = None,
    sandbox_name: str = None,
    depth: int = 1,
    element_separator: str = ",",
    hierarchy_separator: str = "&&",
    hierarchy_element_separator: str = "::",
    **kwargs,
) -> Dict:
    """Trace cell calculation at specified coordinates

    :param cube_name: name of the target cube
    :param elements:
    string "Hierarchy1::Element1 && Hierarchy2::Element4, Element9, Element2"
        - Dimensions are not specified! They are derived from the position.
        - The , separates the element-selections
        - If more than one hierarchy is selected per dimension && splits the elementselections
        - If no Hierarchy is specified. Default Hierarchy will be addressed
    or
    Iterable [Element1, Element2, Element3]
    :param dimensions: optional. Dimension names in their natural order. Will speed up the execution!
    :param sandbox_name: str
    :param depth: optional. Depth of the component trace that will be returned. Deeper traces take longer
    :param element_separator: Alternative separator for the elements, if elements are passed as string
    :param hierarchy_separator: Alternative separator for multiple hierarchies, if elements are passed as string
    :param hierarchy_element_separator: Alternative separator between hierarchy name and element name, if elements are passed as string
    :return: trace json string
    """

    expand_query = ""
    select_query = ""
    if depth:
        for x in range(1, depth + 1):
            component_depth = "/".join(["Components"] * x)
            components_tuple_cube = (
                f"{component_depth}/Tuple($select=Name, UniqueName, Type), {component_depth}/Cube($select=Name)"
            )
            expand_query = ",".join([expand_query, components_tuple_cube])

            component_fields = f"{component_depth}/Type, {component_depth}/Value, {component_depth}/Statements"
            select_query = ",".join([select_query, component_fields])

    url = format_url(
        "/Cubes('{}')/tm1.TraceCellCalculation?$select=Type,Value,Statements"
        "{}&$expand=Tuple($select=Name, UniqueName, Type) {}",
        cube_name,
        select_query,
        expand_query,
    )

    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    if isinstance(elements, str):
        body_as_dict = self._compose_odata_tuple_from_string(
            cube_name, elements, dimensions, element_separator, hierarchy_separator, hierarchy_element_separator
        )
    else:
        body_as_dict = self._compose_odata_tuple_from_iterable(cube_name, elements, dimensions)
    data = json.dumps(body_as_dict, ensure_ascii=False)

    return json.loads(self._rest.POST(url=url, data=data, **kwargs).content)

trace_cell_feeders(cube_name, elements, dimensions=None, sandbox_name=None, element_separator=',', hierarchy_separator='&&', hierarchy_element_separator='::', **kwargs)

Trace feeders from a cell

Parameters:

Name Type Description Default
cube_name str

name of the target cube

required
elements Union[Iterable, str]

string "Hierarchy1::Element1 && Hierarchy2::Element4, Element9, Element2" - Dimensions are not specified! They are derived from the position. - The , separates the element-selections - If more than one hierarchy is selected per dimension && splits the elementselections - If no Hierarchy is specified. Default Hierarchy will be addressed or Iterable [Element1, Element2, Element3]

required
dimensions Iterable[str]

optional. Dimension names in their natural order. Will speed up the execution!

None
sandbox_name str

str

None
element_separator str

Alternative separator for the elements, if elements are passed as string

','
hierarchy_separator str

Alternative separator for multiple hierarchies, if elements are passed as string

'&&'
hierarchy_element_separator str

Alternative separator between hierarchy name and element name, if elements are passed as string

'::'

Returns:

Type Description
Dict

feeder trace

Source code in TM1py/Services/CellService.py
def trace_cell_feeders(
    self,
    cube_name: str,
    elements: Union[Iterable, str],
    dimensions: Iterable[str] = None,
    sandbox_name: str = None,
    element_separator: str = ",",
    hierarchy_separator: str = "&&",
    hierarchy_element_separator: str = "::",
    **kwargs,
) -> Dict:
    """Trace feeders from a cell

    :param cube_name: name of the target cube
    :param elements:
    string "Hierarchy1::Element1 && Hierarchy2::Element4, Element9, Element2"
        - Dimensions are not specified! They are derived from the position.
        - The , separates the element-selections
        - If more than one hierarchy is selected per dimension && splits the elementselections
        - If no Hierarchy is specified. Default Hierarchy will be addressed
    or
    Iterable [Element1, Element2, Element3]
    :param dimensions: optional. Dimension names in their natural order. Will speed up the execution!
    :param sandbox_name: str
    :param element_separator: Alternative separator for the elements, if elements are passed as string
    :param hierarchy_separator: Alternative separator for multiple hierarchies, if elements are passed as string
    :param hierarchy_element_separator: Alternative separator between hierarchy name and element name, if elements are passed as string
    :return: feeder trace
    """

    url = format_url(
        "/Cubes('{}')/tm1.TraceFeeders?$select=Statements,FedCells"
        "&$expand=FedCells/Tuple($select=Name,UniqueName,Type), "
        "FedCells/Cube($select=Name)",
        cube_name,
    )

    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    if isinstance(elements, str):
        body_as_dict = self._compose_odata_tuple_from_string(
            cube_name, elements, dimensions, element_separator, hierarchy_separator, hierarchy_element_separator
        )
    else:
        body_as_dict = self._compose_odata_tuple_from_iterable(cube_name, elements, dimensions)
    data = json.dumps(body_as_dict, ensure_ascii=False)

    return json.loads(self._rest.POST(url=url, data=data, **kwargs).content)

transaction_log_is_active(cube_name)

Source code in TM1py/Services/CellService.py
def transaction_log_is_active(self, cube_name: str) -> bool:
    mdx = f"""
    SELECT {{[}}Cubes].[{cube_name}]}} ON 0, {{[}}CubeProperties].[LOGGING]}} ON 1 FROM [}}CubeProperties]
    """
    values = self.execute_mdx_values(mdx)
    return case_and_space_insensitive_equals(values[0], "YES")

undo_changeset(changeset)

undo a changeset. Similar to rolling back transactions.

Returns:

Type Description
Response

Change set ID

Source code in TM1py/Services/CellService.py
def undo_changeset(self, changeset: str) -> Response:
    """undo a changeset. Similar to rolling back transactions.

    :return: Change set ID
    """

    url = "/UndoChangeSet"
    data = {"ChangeSetID": changeset}
    return self._rest.POST(url, data=json.dumps(data, ensure_ascii=False))

update_cellset(cellset_id, values, sandbox_name=None, changeset=None, **kwargs)

Write values into cellset

Number of values must match the number of cells in the cellset

Parameters:

Name Type Description Default
cellset_id str
required
values Iterable

iterable with Numeric and String values

required
sandbox_name str

str

None
changeset str
None

Returns:

Type Description
Response
Source code in TM1py/Services/CellService.py
@tidy_cellset
def update_cellset(
    self, cellset_id: str, values: Iterable, sandbox_name: str = None, changeset: str = None, **kwargs
) -> Response:
    """Write values into cellset

    Number of values must match the number of cells in the cellset

    :param cellset_id:
    :param values: iterable with Numeric and String values
    :param sandbox_name: str
    :param changeset:
    :return:
    """

    url = format_url("/Cellsets('{}')/Cells", cellset_id)
    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    url = add_url_parameters(url, **{"!ChangeSet": changeset})
    data = []
    for o, value in enumerate(values):
        data.append({"Ordinal": o, "Value": value})

    return self._rest.PATCH(url, json.dumps(data, ensure_ascii=False), **kwargs)

write(cube_name, cellset_as_dict, dimensions=None, increment=False, deactivate_transaction_log=False, reactivate_transaction_log=False, sandbox_name=None, use_ti=False, use_blob=False, use_changeset=False, precision=None, skip_non_updateable=False, measure_dimension_elements=None, remove_blob=True, allow_spread=False, clear_view=None, **kwargs)

Write values to a cube

Same signature as write_values method, but faster since it uses write_values_through_cellset behind the scenes.

Supports incrementing cell values through optional increment argument Spreading through spreading shortcuts is not supported!

Parameters:

Name Type Description Default
cube_name str

name of the cube

required
cellset_as_dict Dict

{(elem_a, elem_b, elem_c): 243, (elem_d, elem_e, elem_f) : 109}

required
dimensions Iterable[str]

optional. Dimension names in their natural order. Will speed up the execution!

None
increment bool

increment or update cell values

False
deactivate_transaction_log bool

deactivate before writing

False
reactivate_transaction_log bool

reactivate after writing

False
sandbox_name str

str

None
use_ti bool

Use unbound process to write. Requires admin permissions. causes massive performance improvement.

False
use_blob bool

Uses blob to write. Requires admin permissions. 10x faster compared to use_ti

False
use_changeset bool

Enable ChangesetID: True or False

False
precision int

max precision when writhing through unbound process. Necessary when dealing with large numbers to avoid "number too long" TI syntax error.

None
skip_non_updateable bool

skip cells that are not updateable (e.g. rule derived or consolidated)

False
measure_dimension_elements Dict

dictionary of measure elements and their types to improve performance when use_ti is True. When all written values are numeric you can pass a default dict with default key 'Numeric'

None
remove_blob bool

remove blob file after writing with use_blob=True

True
allow_spread bool

allow TI process in use_blob or use_ti to use CellPutProportionalSpread on C elements

False
clear_view str

name of cube view to clear before writing

None

Returns:

Type Description
Optional[str]

changeset or None

Source code in TM1py/Services/CellService.py
def write(
    self,
    cube_name: str,
    cellset_as_dict: Dict,
    dimensions: Iterable[str] = None,
    increment: bool = False,
    deactivate_transaction_log: bool = False,
    reactivate_transaction_log: bool = False,
    sandbox_name: str = None,
    use_ti: bool = False,
    use_blob: bool = False,
    use_changeset: bool = False,
    precision: int = None,
    skip_non_updateable: bool = False,
    measure_dimension_elements: Dict = None,
    remove_blob: bool = True,
    allow_spread: bool = False,
    clear_view: str = None,
    **kwargs,
) -> Optional[str]:
    """Write values to a cube

    Same signature as `write_values` method, but faster since it uses `write_values_through_cellset`
    behind the scenes.

    Supports incrementing cell values through optional `increment` argument
    Spreading through spreading shortcuts is not supported!

    :param cube_name: name of the cube
    :param cellset_as_dict: {(elem_a, elem_b, elem_c): 243, (elem_d, elem_e, elem_f) : 109}
    :param dimensions: optional. Dimension names in their natural order. Will speed up the execution!
    :param increment: increment or update cell values
    :param deactivate_transaction_log: deactivate before writing
    :param reactivate_transaction_log: reactivate after writing
    :param sandbox_name: str
    :param use_ti: Use unbound process to write. Requires admin permissions. causes massive performance improvement.
    :param use_blob: Uses blob to write. Requires admin permissions. 10x faster compared to use_ti
    :param use_changeset: Enable ChangesetID: True or False
    :param precision: max precision when writhing through unbound process.
    Necessary when dealing with large numbers to avoid "number too long" TI syntax error.
    :param skip_non_updateable: skip cells that are not updateable (e.g. rule derived or consolidated)
    :param measure_dimension_elements: dictionary of measure elements and their types to improve
    performance when `use_ti` is `True`.
    When all written values are numeric you can pass a default dict with default key 'Numeric'
    :param remove_blob: remove blob file after writing with use_blob=True
    :param allow_spread: allow TI process in use_blob or use_ti to use CellPutProportionalSpread on C elements
    :param clear_view: name of cube view to clear before writing
    :return: changeset or None
    """

    if clear_view and not use_blob:
        raise ValueError("'clear_view' can only be used in conjunction with 'use_blob'")

    if use_ti:
        return self.write_through_unbound_process(
            cube_name=cube_name,
            cellset_as_dict=cellset_as_dict,
            increment=increment,
            sandbox_name=sandbox_name,
            deactivate_transaction_log=deactivate_transaction_log,
            reactivate_transaction_log=reactivate_transaction_log,
            precision=precision,
            skip_non_updateable=skip_non_updateable,
            measure_dimension_elements=measure_dimension_elements,
            dimensions=dimensions,
            allow_spread=allow_spread,
            **kwargs,
        )

    if use_blob:
        return self.write_through_blob(
            cube_name=cube_name,
            cellset_as_dict=cellset_as_dict,
            increment=increment,
            sandbox_name=sandbox_name,
            deactivate_transaction_log=deactivate_transaction_log,
            reactivate_transaction_log=reactivate_transaction_log,
            skip_non_updateable=skip_non_updateable,
            dimensions=dimensions,
            remove_blob=remove_blob,
            allow_spread=allow_spread,
            clear_view=clear_view,
            **kwargs,
        )

    return self.write_through_cellset(
        cube_name,
        cellset_as_dict,
        dimensions,
        increment,
        deactivate_transaction_log,
        reactivate_transaction_log,
        sandbox_name,
        use_changeset,
        skip_non_updateable,
        **kwargs,
    )

write_async(cube_name, cells, slice_size=250000, max_workers=8, dimensions=None, increment=False, deactivate_transaction_log=False, reactivate_transaction_log=False, sandbox_name=None, precision=None, measure_dimension_elements=None, **kwargs)

Write asynchronously

Parameters:

Name Type Description Default
cube_name str
required
cells Dict
required
slice_size int
250000
max_workers int
8
dimensions Iterable[str]
None
increment bool
False
deactivate_transaction_log bool
False
reactivate_transaction_log bool
False
sandbox_name str
None
precision int

max precision when writhing through unbound process. Necessary to decrease when dealing with large numbers to avoid "number too long" TI syntax error.

None
measure_dimension_elements Dict

dictionary of measure elements and their types to improve performance when use_ti is True.

None
kwargs
{}

Returns:

Type Description
Optional[str]
Source code in TM1py/Services/CellService.py
@manage_transaction_log
def write_async(
    self,
    cube_name: str,
    cells: Dict,
    slice_size: int = 250_000,
    max_workers: int = 8,
    dimensions: Iterable[str] = None,
    increment: bool = False,
    deactivate_transaction_log: bool = False,
    reactivate_transaction_log: bool = False,
    sandbox_name: str = None,
    precision: int = None,
    measure_dimension_elements: Dict = None,
    **kwargs,
) -> Optional[str]:
    """Write asynchronously

    :param cube_name:
    :param cells:
    :param slice_size:
    :param max_workers:
    :param dimensions:
    :param increment:
    :param deactivate_transaction_log:
    :param reactivate_transaction_log:
    :param sandbox_name:
    :param precision: max precision when writhing through unbound process.
    Necessary to decrease when dealing with large numbers to avoid "number too long" TI syntax error.
    :param measure_dimension_elements: dictionary of measure elements and their types to improve
    performance when `use_ti` is `True`.
    :param kwargs:
    :return:
    """

    if not dimensions:
        dimensions = self.get_dimension_names_for_writing(cube_name=cube_name)

    if not measure_dimension_elements:
        measure_dimension_elements = self.get_elements_from_all_measure_hierarchies(cube_name=cube_name)

    def _chunks(data: Dict):
        it = iter(data)
        for _ in range(0, len(data), slice_size):
            yield {k: data[k] for k in itertools.islice(it, slice_size)}

    def _write(chunk: Dict):
        return self.write(
            cube_name=cube_name,
            cellset_as_dict=chunk,
            dimensions=dimensions,
            increment=increment,
            use_blob=True,
            sandbox_name=sandbox_name,
            precision=precision,
            measure_dimension_elements=measure_dimension_elements,
            **kwargs,
        )

    async def _write_async(data: Dict):
        loop = asyncio.get_event_loop()
        failures = []

        with ThreadPoolExecutor(max_workers) as executor:
            futures = [loop.run_in_executor(executor, _write, chunk) for chunk in _chunks(data)]

            for future in futures:
                try:
                    await future
                except (TM1pyWritePartialFailureException, TM1pyWriteFailureException) as exception:
                    failures.append(exception)

        return failures

    exceptions = asyncio.run(_write_async(cells))
    if not exceptions:
        return

    # merge all failures into one combined Exception
    raise TM1pyWritePartialFailureException(
        statuses=list(itertools.chain(*[exception.statuses for exception in exceptions])),
        error_log_files=list(itertools.chain(*[exception.error_log_files for exception in exceptions])),
        attempts=sum(
            [
                exception.attempts if isinstance(exception, TM1pyWritePartialFailureException) else 1
                for exception in exceptions
            ]
        ),
    )

write_dataframe(cube_name, data, dimensions=None, increment=False, deactivate_transaction_log=False, reactivate_transaction_log=False, sandbox_name=None, use_ti=False, use_blob=False, use_changeset=False, precision=None, skip_non_updateable=False, measure_dimension_elements=None, sum_numeric_duplicates=True, remove_blob=True, allow_spread=False, clear_view=None, static_dimension_elements=None, infer_column_order=False, **kwargs)

Function expects same shape as execute_mdx_dataframe returns. Column order must match dimensions in the target cube with an additional column for the values. Column names are not relevant.

Parameters:

Name Type Description Default
cube_name str
required
data DataFrame

Pandas Data Frame

required
dimensions Iterable[str]
None
increment bool
False
deactivate_transaction_log bool
False
reactivate_transaction_log bool
False
sandbox_name str
None
use_ti bool
False
use_blob bool

Uses blob to write. Requires admin permissions. 10x faster compared to use_ti

False
use_changeset bool

Enable ChangesetID: True or False

False
precision int

max precision when writhing through unbound process. Necessary when dealing with large numbers to avoid "number too long" TI syntax error

None
skip_non_updateable bool

skip cells that are not updateable (e.g. rule derived or consolidated)

False
measure_dimension_elements Dict

dictionary of measure elements and their types to improve performance when use_ti is True. When all written values are numeric you can pass a default dict with default key 'Numeric'

None
sum_numeric_duplicates bool

Aggregate numerical values for duplicated intersections

True
remove_blob bool

remove blob file after writing with use_blob=True

True
allow_spread bool

allow TI process in use_blob or use_ti to use CellPutProportionalSpread on C elements

False
clear_view str

name of cube view to clear before writing

None
static_dimension_elements Dict

Dict of fixed dimension element pairs. Column is created for you.

None
infer_column_order bool

bool indicating whether the column order of the dataframe should automatically be inferred and mapped to the dimension order in the cube.

False

Returns:

Type Description
str

changeset or None

Source code in TM1py/Services/CellService.py
@require_pandas
def write_dataframe(
    self,
    cube_name: str,
    data: "pd.DataFrame",
    dimensions: Iterable[str] = None,
    increment: bool = False,
    deactivate_transaction_log: bool = False,
    reactivate_transaction_log: bool = False,
    sandbox_name: str = None,
    use_ti: bool = False,
    use_blob: bool = False,
    use_changeset: bool = False,
    precision: int = None,
    skip_non_updateable: bool = False,
    measure_dimension_elements: Dict = None,
    sum_numeric_duplicates: bool = True,
    remove_blob: bool = True,
    allow_spread: bool = False,
    clear_view: str = None,
    static_dimension_elements: Dict = None,
    infer_column_order: bool = False,
    **kwargs,
) -> str:
    """
    Function expects same shape as `execute_mdx_dataframe` returns.
    Column order must match dimensions in the target cube with an additional column for the values.
    Column names are not relevant.
    :param cube_name:
    :param data: Pandas Data Frame
    :param dimensions:
    :param increment:
    :param deactivate_transaction_log:
    :param reactivate_transaction_log:
    :param sandbox_name:
    :param use_ti:
    :param use_blob: Uses blob to write. Requires admin permissions. 10x faster compared to use_ti
    :param use_changeset: Enable ChangesetID: True or False
    :param precision: max precision when writhing through unbound process.
        Necessary when dealing with large numbers to avoid "number too long" TI syntax error
    :param skip_non_updateable: skip cells that are not updateable (e.g. rule derived or consolidated)
    :param measure_dimension_elements: dictionary of measure elements and their types to improve
        performance when `use_ti` is `True`.
        When all written values are numeric you can pass a default dict with default key 'Numeric'
    :param sum_numeric_duplicates: Aggregate numerical values for duplicated intersections
    :param remove_blob: remove blob file after writing with use_blob=True
    :param allow_spread: allow TI process in use_blob or use_ti to use CellPutProportionalSpread on C elements
    :param clear_view: name of cube view to clear before writing
    :param static_dimension_elements: Dict of fixed dimension element pairs. Column is created for you.
    :param infer_column_order: bool indicating whether the column order of the dataframe should automatically be
        inferred and mapped to the dimension order in the cube.
    :return: changeset or None
    """
    if not isinstance(data, pd.DataFrame):
        raise ValueError("argument 'data' must of type DataFrame")

    # don't mutate passed data frame. Work on a copy instead
    data = data.copy()

    if not dimensions:
        dimensions = self.get_dimension_names_for_writing(cube_name=cube_name)

    infer_column_order = True if static_dimension_elements else infer_column_order

    # reorder columns in df to align with dimensions; CaseAndSpaceInsensitiveDict is a OrderedDict
    if static_dimension_elements:
        for dimension, element in static_dimension_elements.items():
            if dimension in CaseAndSpaceInsensitiveSet(data.columns):
                raise ValueError(
                    "one or more of the fixed_dimension_elements are passed as a dataframe column. "
                    f"{dimension}: {element} is passed in fixed_dimension_elements. "
                    "Either remove the key value pair from the fixed_dimension_elements dict or "
                    f"avoid passing the {dimension} column in the dataframe."
                )
            data[dimension] = element

    if infer_column_order:
        data.columns = data.columns.map(lower_and_drop_spaces)

        ordered_columns = list(map(lower_and_drop_spaces, dimensions))

        columns_not_in_dimensions = data.columns.difference(ordered_columns).tolist()

        data = data[ordered_columns + columns_not_in_dimensions]

    if not len(data.columns) == len(dimensions) + 1:
        raise ValueError("Number of columns in 'data' DataFrame must be number of dimensions in cube + 1")

    cells = build_cellset_from_pandas_dataframe(data, sum_numeric_duplicates=sum_numeric_duplicates)

    return self.write(
        cube_name=cube_name,
        cellset_as_dict=cells,
        dimensions=dimensions,
        increment=increment,
        deactivate_transaction_log=deactivate_transaction_log,
        reactivate_transaction_log=reactivate_transaction_log,
        sandbox_name=sandbox_name,
        use_ti=use_ti,
        use_blob=use_blob,
        remove_blob=remove_blob,
        use_changeset=use_changeset,
        precision=precision,
        skip_non_updateable=skip_non_updateable,
        measure_dimension_elements=measure_dimension_elements,
        allow_spread=allow_spread,
        clear_view=clear_view,
        **kwargs,
    )

write_dataframe_async(cube_name, data, slice_size_of_dataframe=250000, max_workers=8, dimensions=None, increment=True, sandbox_name=None, deactivate_transaction_log=False, reactivate_transaction_log=False, **kwargs)

Write DataFrame into a cube using unbound TI processes in a multi-threading way. Requires admin permissions. For a DataFrame with > 1,000,000 rows, this function will at least save half of runtime compared with write_dataframe function. Column order must match dimensions in the target cube with an additional column for the values. Column names are not relevant.

Parameters:

Name Type Description Default
cube_name str
required
data DataFrame

Pandas Data Frame

required
slice_size_of_dataframe int

Number of rows for each DataFrame slice, e.g. 10000

250000
max_workers int

Max number of threads, e.g. 14

8
dimensions Iterable[str]
None
increment bool

increment or update cell values. Defaults to True.

True
sandbox_name str

name of the sandbox or None

None
deactivate_transaction_log bool
False
reactivate_transaction_log bool
False

Returns:

Type Description

the Future’s result or raise exception.

Source code in TM1py/Services/CellService.py
@require_pandas
@manage_transaction_log
def write_dataframe_async(
    self,
    cube_name: str,
    data: "pd.DataFrame",
    slice_size_of_dataframe: int = 250_000,
    max_workers: int = 8,
    dimensions: Iterable[str] = None,
    increment: bool = True,
    sandbox_name: str = None,
    deactivate_transaction_log: bool = False,
    reactivate_transaction_log: bool = False,
    **kwargs,
):
    """Write DataFrame into a cube using unbound TI processes in a multi-threading way. Requires admin permissions.
    For a DataFrame with > 1,000,000 rows, this function will at least save half of runtime compared with `write_dataframe` function.
    Column order must match dimensions in the target cube with an additional column for the values.
    Column names are not relevant.
    :param cube_name:
    :param data: Pandas Data Frame
    :param slice_size_of_dataframe: Number of rows for each DataFrame slice, e.g. 10000
    :param max_workers: Max number of threads, e.g. 14
    :param dimensions:
    :param increment: increment or update cell values. Defaults to True.
    :param sandbox_name: name of the sandbox or None
    :param deactivate_transaction_log:
    :param reactivate_transaction_log:
    :return: the Future’s result or raise exception.
    """
    if not isinstance(data, pd.DataFrame):
        raise ValueError("argument 'data' must of type DataFrame")

    if not dimensions:
        dimensions = self.get_dimension_names_for_writing(cube_name=cube_name)

    if not len(data.columns) == len(dimensions) + 1:
        raise ValueError("Number of columns in 'data' DataFrame must be number of dimensions in cube + 1")

    def _chunks(df: "pd.DataFrame"):
        return [df.iloc[i : i + slice_size_of_dataframe] for i in range(0, df.shape[0], slice_size_of_dataframe)]

    def _write(chunk: "pd.DataFrame"):
        return self.write_dataframe(
            cube_name=cube_name,
            data=chunk,
            dimensions=dimensions,
            increment=increment,
            use_blob=True,
            sandbox_name=sandbox_name,
            **kwargs,
        )

    async def _write_async(df: "pd.DataFrame"):
        loop = asyncio.get_event_loop()
        failures = []

        with ThreadPoolExecutor(max_workers) as executor:
            futures = [loop.run_in_executor(executor, _write, chunk) for chunk in _chunks(df)]

            for future in futures:
                try:
                    await future
                except (TM1pyWritePartialFailureException, TM1pyWriteFailureException) as exception:
                    failures.append(exception)

        return failures

    if increment:
        data = build_dataframe_aggregate_intersections(data, sum_numeric_duplicates=True)

    exceptions = asyncio.run(_write_async(data))
    if not exceptions:
        return

    # merge all failures into one combined Exception
    raise TM1pyWritePartialFailureException(
        statuses=list(itertools.chain(*[exception.statuses for exception in exceptions])),
        error_log_files=list(itertools.chain(*[exception.error_log_files for exception in exceptions])),
        attempts=sum([exception.attempts if hasattr(exception, "attempts") else 1 for exception in exceptions]),
    )

write_through_blob(cube_name, cellset_as_dict, increment=False, sandbox_name=None, skip_non_updateable=False, remove_blob=True, dimensions=None, allow_spread=False, clear_view=None, **kwargs)

Writes data back to TM1 via an unbound TI process having an uploaded CSV as data source

Parameters:

Name Type Description Default
cube_name str

str

required
cellset_as_dict dict
required
increment bool

increment or update cell values

False
sandbox_name str

str

None
skip_non_updateable bool

skip cells that are not updateable (e.g. rule derived or consolidated)

False
remove_blob

choose False to persist blob after write. Can be helpful for troubleshooting.

True
dimensions str

optional. Dimension names in their natural order. Will speed up the execution!

None
allow_spread bool

allow TI process in use_blob or use_ti to use CellPutProportionalSpread on C elements.

False
clear_view str

name of cube view to clear before writing

None
kwargs

Additional arguments for the REST request

{}

Returns:

Type Description

Success: bool, Messages: list, ChangeSet: None

Source code in TM1py/Services/CellService.py
@require_data_admin
@require_ops_admin
@manage_transaction_log
@require_pandas
def write_through_blob(
    self,
    cube_name: str,
    cellset_as_dict: dict,
    increment: bool = False,
    sandbox_name: str = None,
    skip_non_updateable: bool = False,
    remove_blob=True,
    dimensions: str = None,
    allow_spread: bool = False,
    clear_view: str = None,
    **kwargs,
):
    """
    Writes data back to TM1 via an unbound TI process having an uploaded CSV as data source
    :param cube_name: str
    :param cellset_as_dict:
    :param increment: increment or update cell values
    :param sandbox_name: str
    :param skip_non_updateable: skip cells that are not updateable (e.g. rule derived or consolidated)
    :param remove_blob: choose False to persist blob after write. Can be helpful for troubleshooting.
    :param dimensions: optional. Dimension names in their natural order. Will speed up the execution!
    :param allow_spread: allow TI process in use_blob or use_ti to use CellPutProportionalSpread on C elements.
    :param clear_view: name of cube view to clear before writing
    :param kwargs: Additional arguments for the REST request
    :return: Success: bool, Messages: list, ChangeSet: None
    """

    process_service = ProcessService(self._rest)
    cube_service = self.get_cube_service()
    file_service = FileService(self._rest)

    unique_name = self.suggest_unique_object_name()

    # Transform cells to format that's consumable for TI
    csv_content = StringIO()
    csv_writer = csv.writer(csv_content, delimiter=",", quoting=csv.QUOTE_ALL)
    csv_writer.writerows(
        list(elements) + [value.replace("\r", "").replace("\n", "") if isinstance(value, str) else value]
        for elements, value in cellset_as_dict.items()
    )

    file_name = f"{unique_name}.csv"
    file_service.create(file_name=file_name, file_content=csv_content.getvalue().encode("utf-8"), **kwargs)

    try:
        # Create and execute unbound TI process to load blob file to cube
        process = self._build_blob_to_cube_process(
            cube_name=cube_name,
            process_name=unique_name,
            blob_filename=file_name,
            dimensions=dimensions or cube_service.get_dimension_names(cube_name),
            increment=increment,
            skip_non_updateable=skip_non_updateable,
            sandbox_name=sandbox_name,
            allow_spread=allow_spread,
            clear_view=clear_view,
        )

        success, status, log_file = process_service.execute_process_with_return(process=process, **kwargs)
        if not success:
            if status in ["HasMinorErrors"]:
                raise TM1pyWritePartialFailureException([status], [log_file], 1)
            else:
                raise TM1pyWriteFailureException([status], [log_file])

    finally:
        if remove_blob:
            file_service.delete(file_name=file_name)

write_through_cellset(cube_name, cellset_as_dict, dimensions=None, increment=False, deactivate_transaction_log=False, reactivate_transaction_log=False, sandbox_name=None, use_changeset=False, skip_non_updateable=False, **kwargs)

Source code in TM1py/Services/CellService.py
def write_through_cellset(
    self,
    cube_name: str,
    cellset_as_dict: Dict,
    dimensions: Iterable[str] = None,
    increment: bool = False,
    deactivate_transaction_log: bool = False,
    reactivate_transaction_log: bool = False,
    sandbox_name: str = None,
    use_changeset: bool = False,
    skip_non_updateable: bool = False,
    **kwargs,
) -> str:
    if not dimensions:
        dimensions = self.get_dimension_names_for_writing(cube_name=cube_name, **kwargs)

    if skip_non_updateable:
        cellset_as_dict = self.drop_non_updateable_cells(cellset_as_dict, cube_name, dimensions)

    if cellset_as_dict:
        mdx, values = build_mdx_and_values_from_cellset(cellset_as_dict, cube_name, dimensions)
        return self.write_values_through_cellset(
            mdx=mdx,
            values=values,
            increment=increment,
            deactivate_transaction_log=deactivate_transaction_log,
            reactivate_transaction_log=reactivate_transaction_log,
            sandbox_name=sandbox_name,
            use_changeset=use_changeset,
            **kwargs,
        )

write_through_unbound_process(cube_name, cellset_as_dict, increment=False, sandbox_name=None, precision=None, skip_non_updateable=False, measure_dimension_elements=None, is_attribute_cube=None, dimensions=None, allow_spread=False, **kwargs)

Writes data back to TM1 via an unbound TI process

Parameters:

Name Type Description Default
cube_name str

str

required
cellset_as_dict Dict

cellset_as_dict

required
increment bool

increment or update cell values

False
sandbox_name str

str

None
precision int

max precision when writhing through unbound process.

None
skip_non_updateable bool

skip cells that are not updateable (e.g. rule derived or consolidated)

False
measure_dimension_elements Dict

pass dictionary of measure elements and their types to improve performance. When all written values are numeric you can pass a defaultdict with default key: 'Numeric'

None
is_attribute_cube bool

bool or None

None
allow_spread bool

allow TI process in use_blob or use_ti to use CellPutProportionalSpread on C elements

False
kwargs

Additional arguments for the REST request.

{}

Returns:

Type Description

Success: bool, Messages: list, ChangeSet: None

Source code in TM1py/Services/CellService.py
@require_data_admin
@require_ops_admin
@manage_transaction_log
def write_through_unbound_process(
    self,
    cube_name: str,
    cellset_as_dict: Dict,
    increment: bool = False,
    sandbox_name: str = None,
    precision: int = None,
    skip_non_updateable: bool = False,
    measure_dimension_elements: Dict = None,
    is_attribute_cube: bool = None,
    dimensions: List = None,
    allow_spread: bool = False,
    **kwargs,
):
    """
    Writes data back to TM1 via an unbound TI process
    :param cube_name: str
    :param cellset_as_dict: cellset_as_dict
    :param increment: increment or update cell values
    :param sandbox_name: str
    :param precision: max precision when writhing through unbound process.
    :param skip_non_updateable: skip cells that are not updateable (e.g. rule derived or consolidated)
    :param measure_dimension_elements: pass dictionary of measure elements and their types to improve performance.
        When all written values are numeric you can pass a defaultdict with default key: 'Numeric'
    :param is_attribute_cube: bool or None
    :param allow_spread: allow TI process in use_blob or use_ti to use CellPutProportionalSpread on C elements
    :param kwargs: Additional arguments for the REST request.
    :return: Success: bool, Messages: list, ChangeSet: None
    """
    if is_attribute_cube is None:
        is_attribute_cube = cube_name.lower().startswith("}elementattributes_")

    enable_sandbox = self.generate_enable_sandbox_ti(sandbox_name)

    successes = list()
    statuses = list()
    log_files = list()

    if not measure_dimension_elements:
        measure_dimension_elements = self.get_elements_from_all_measure_hierarchies(cube_name)

    if is_attribute_cube:
        statements = self._build_attribute_update_statements(
            cube_name=cube_name,
            cellset_as_dict=cellset_as_dict,
            precision=precision,
            measure_dimension_elements=measure_dimension_elements,
            skip_non_updateable=skip_non_updateable,
        )

    else:
        if not dimensions and allow_spread:
            dimensions = self.get_dimension_names_for_writing(cube_name=cube_name, **kwargs)
        statements = self._build_cell_update_statements(
            cube_name=cube_name,
            cellset_as_dict=cellset_as_dict,
            increment=increment,
            measure_dimension_elements=measure_dimension_elements,
            precision=precision,
            skip_non_updateable=skip_non_updateable,
            dimensions=dimensions,
            allow_spread=allow_spread,
        )

    chunk = list()

    max_statements = Process.max_statements(self.version)
    for n, statement in enumerate(statements):
        chunk.append(statement)
        if n > 0 and n % (max_statements * 2) == 0:
            success, status, log_file = self._execute_write_statements(chunk, enable_sandbox, kwargs)
            successes.append(success)
            if not success:
                statuses.append(status)
                log_files.append(log_file)

            chunk = list()

    success, status, log_file = self._execute_write_statements(chunk, enable_sandbox, kwargs)
    successes.append(success)
    if not success:
        statuses.append(status)
        log_files.append(log_file)

    if not any(successes):
        if "HasMinorErrors" in statuses:
            raise TM1pyWritePartialFailureException(statuses, log_files, len(successes))

        raise TM1pyWriteFailureException(statuses, log_files)

    if not all(successes):
        raise TM1pyWritePartialFailureException(statuses, log_files, len(successes))

write_value(value, cube_name, element_tuple, dimensions=None, sandbox_name=None, **kwargs)

Write value into cube at specified coordinates

Parameters:

Name Type Description Default
value Union[str, float]

the actual value

required
cube_name str

name of the target cube

required
element_tuple Iterable

target coordinates

required
dimensions Iterable[str]

optional. Dimension names in their natural order. Will speed up the execution!

None
sandbox_name str

str

None

Returns:

Type Description
Response

response

Source code in TM1py/Services/CellService.py
@manage_changeset
def write_value(
    self,
    value: Union[str, float],
    cube_name: str,
    element_tuple: Iterable,
    dimensions: Iterable[str] = None,
    sandbox_name: str = None,
    **kwargs,
) -> Response:
    """Write value into cube at specified coordinates

    :param value: the actual value
    :param cube_name: name of the target cube
    :param element_tuple: target coordinates
    :param dimensions: optional. Dimension names in their natural order. Will speed up the execution!
    :param sandbox_name: str
    :return: response
    """
    if not dimensions:
        dimensions = self.get_dimension_names_for_writing(cube_name=cube_name)
    url = format_url("/Cubes('{}')/tm1.Update", cube_name)
    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    body_as_dict = OrderedDict()
    body_as_dict["Cells"] = [{}]
    body_as_dict["Cells"][0] = self._compose_odata_tuple_from_iterable(
        cube_name, element_tuple, dimensions, **kwargs
    )
    body_as_dict["Value"] = str(value) if value else ""
    data = json.dumps(body_as_dict, ensure_ascii=False)
    return self._rest.POST(url=url, data=data, **kwargs)

write_values(cube_name, cellset_as_dict, dimensions=None, sandbox_name=None, changeset=None, **kwargs)

Write values to a cube

For cellsets with > 1000 cells look into write or write_values_through_cellset Supports spreading shortcuts

Parameters:

Name Type Description Default
cube_name str

name of the cube

required
cellset_as_dict Dict

{(elem_a, elem_b, elem_c): 243, (elem_d, elem_e, elem_f) : 109}

required
dimensions Iterable[str]

optional. Dimension names in their natural order. Will speed up the execution!

None
sandbox_name str

str

None
changeset str

str

None

Returns:

Type Description
str

Response

Source code in TM1py/Services/CellService.py
@manage_changeset
@manage_transaction_log
def write_values(
    self,
    cube_name: str,
    cellset_as_dict: Dict,
    dimensions: Iterable[str] = None,
    sandbox_name: str = None,
    changeset: str = None,
    **kwargs,
) -> str:
    """Write values to a cube

    For cellsets with > 1000 cells look into `write` or `write_values_through_cellset`
    Supports spreading shortcuts

    :param cube_name: name of the cube
    :param cellset_as_dict: {(elem_a, elem_b, elem_c): 243, (elem_d, elem_e, elem_f) : 109}
    :param dimensions: optional. Dimension names in their natural order. Will speed up the execution!
    :param sandbox_name: str
    :param changeset: str
    :return: Response
    """
    if not dimensions:
        dimensions = self.get_dimension_names_for_writing(cube_name=cube_name, **kwargs)
    url = format_url("/Cubes('{}')/tm1.Update", cube_name)
    url = add_url_parameters(url, **{"!sandbox": sandbox_name})
    url = add_url_parameters(url, **{"!ChangeSet": changeset})

    updates = []
    for element_tuple, value in cellset_as_dict.items():
        body_as_dict = OrderedDict()
        body_as_dict["Cells"] = [{}]
        body_as_dict["Cells"][0]["Tuple@odata.bind"] = [
            format_url("Dimensions('{}')/Hierarchies('{}')/Elements('{}')", dim, dim, elem)
            for dim, elem in zip(dimensions, element_tuple)
        ]
        body_as_dict["Value"] = value if value else ""
        updates.append(json.dumps(body_as_dict, ensure_ascii=False))
    updates = "[" + ",".join(updates) + "]"
    self._rest.POST(url=url, data=updates, **kwargs)

    return changeset

write_values_through_cellset(mdx, values, increment=False, sandbox_name=None, **kwargs)

Significantly faster than write_values function

Cellset gets created according to MDX Expression. For instance: [[61, 29 ,13], [42, 54, 15], [17, 28, 81]]

Each value in the cellset can be addressed through its position: The ordinal integer value. Ordinal-enumeration goes from top to bottom from left to right Number 61 has Ordinal 0, 29 has Ordinal 1, etc.

The order of the iterable determines the insertion point in the cellset. For instance: [91, 85, 72, 68, 51, 42, 35, 28, 11]

would lead to: [[91, 85 ,72], [68, 51, 42], [35, 28, 11]]

When writing large datasets into TM1 Cubes it can be convenient to call this function asynchronously.

Parameters:

Name Type Description Default
mdx str

Valid MDX Expression.

required
values Iterable

List of values. The Order of the List/ Iterable determines the insertion point in the cellset.

required
increment bool

increment or update cells

False
sandbox_name str

str

None

Returns:

Type Description
str

changeset: str

Source code in TM1py/Services/CellService.py
@manage_changeset
@manage_transaction_log
def write_values_through_cellset(
    self, mdx: str, values: Iterable, increment: bool = False, sandbox_name: str = None, **kwargs
) -> str:
    """Significantly faster than write_values function

    Cellset gets created according to MDX Expression. For instance:
    [[61, 29 ,13],
    [42, 54, 15],
    [17, 28, 81]]

    Each value in the cellset can be addressed through its position: The ordinal integer value.
    Ordinal-enumeration goes from top to bottom from left to right
    Number 61 has Ordinal 0, 29 has Ordinal 1, etc.

    The order of the iterable determines the insertion point in the cellset.
    For instance:
    [91, 85, 72, 68, 51, 42, 35, 28, 11]

    would lead to:
    [[91, 85 ,72],
    [68, 51, 42],
    [35, 28, 11]]

    When writing large datasets into TM1 Cubes it can be convenient to call this function asynchronously.

    :param mdx: Valid MDX Expression.
    :param values: List of values. The Order of the List/ Iterable determines the insertion point in the cellset.
    :param increment: increment or update cells
    :param sandbox_name: str
    :return: changeset: str
    """

    changeset = kwargs.get("changeset")

    cellset_id = self.create_cellset(mdx=mdx, sandbox_name=sandbox_name, **kwargs)
    if increment:
        current_values = self.extract_cellset_values(
            cellset_id, use_compact_json=True, delete_cellset=False, **kwargs
        )
        values = (float(x) + float(y or 0) for x, y in zip(values, current_values))

    self.update_cellset(cellset_id=cellset_id, values=values, sandbox_name=sandbox_name, **kwargs)
    return changeset

manage_changeset(func)

Control the start and end of change sets which goups write events together in the TM1 transaction log.

Decorated function working with all non-TI based writing methods

Source code in TM1py/Services/CellService.py
@decohints
def manage_changeset(func):
    """Control the start and end of change sets which goups write events together in the TM1 transaction log.

    Decorated function working with all non-TI based writing methods
    """

    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
        use_changeset = kwargs.pop("use_changeset", False)
        if use_changeset:
            changeset = self.begin_changeset()
            try:
                return func(self, changeset=changeset, *args, **kwargs)
            finally:
                self.end_changeset(changeset)
        else:
            return func(self, *args, **kwargs)

    return wrapper

manage_transaction_log(func)

Control state of transaction log during and after write operation for a given cube through: deactivate_transaction_log and reactivate_transaction_log.

Decorated function must have either cube_name or mdx as first argument or keyword argument

Source code in TM1py/Services/CellService.py
@decohints
def manage_transaction_log(func):
    """Control state of transaction log during and after write operation for a given cube through:
    `deactivate_transaction_log` and `reactivate_transaction_log`.

    Decorated function must have either `cube_name` or `mdx` as first argument or keyword argument
    """

    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
        if "cube_name" in kwargs:
            cube_name = kwargs["cube_name"]
        elif "mdx" in kwargs:
            cube_name = get_cube(kwargs["mdx"])
        else:
            arg = args[0]
            if resembles_mdx(arg):
                cube_name = get_cube(arg)
            else:
                cube_name = arg

        deactivate_transaction_log = kwargs.pop("deactivate_transaction_log", False)
        reactivate_transaction_log = kwargs.pop("reactivate_transaction_log", False)
        try:

            if deactivate_transaction_log:
                self.deactivate_transactionlog(cube_name)
            return func(self, *args, **kwargs)

        finally:
            if reactivate_transaction_log:
                self.activate_transactionlog(cube_name)

    return wrapper

odata_compact_json(return_as_dict)

Higher order function to manage header and response when using compact JSON

Applies when decorated function has use_compact_json argument set to True

Currently only supports responses with only cell properties and where they are explicitly specified: * Cellsets('...')?$expand=Axes(...),Cells($select=Ordinal,Value...) does NOT work ! * Cellsets('...')?$expand=Cells does NOT work ! * Cellsets('...')?$expand=Cells($select=Ordinal,Value...) works !

Source code in TM1py/Services/CellService.py
@decohints
def odata_compact_json(return_as_dict: bool):
    """Higher order function to manage header and response when using compact JSON

    Applies when decorated function has `use_compact_json` argument set to True

    Currently only supports responses with only cell properties and where they are explicitly specified:
        * Cellsets('...')?$expand=Axes(...),Cells($select=Ordinal,Value...) does NOT work !
        * Cellsets('...')?$expand=Cells does NOT work !
        * Cellsets('...')?$expand=Cells($select=Ordinal,Value...) works !

    """

    def wrap(func):
        @functools.wraps(func)
        def wrapper(self, *args, **kwargs):

            if not kwargs.get("use_compact_json", False):
                return func(self, *args, **kwargs)

            # Update Accept Header
            original_header = self._rest.add_compact_json_header()

            try:
                response = func(self, *args, **kwargs)
                context = response["@odata.context"]

                if context.startswith("$metadata#Cellsets"):
                    return extract_compact_json_cellset(context, response, return_as_dict)

                else:
                    raise NotImplementedError("odata_compact_json decorator must only be used on cellsets")

            finally:
                # Restore original header
                self._rest.add_http_header("Accept", original_header)

        return wrapper

    return wrap

tidy_cellset(func)

Higher order function to tidy up cellset after usage

Source code in TM1py/Services/CellService.py
@decohints
def tidy_cellset(func):
    """Higher order function to tidy up cellset after usage"""

    @functools.wraps(func)
    def wrapper(self, cellset_id, *args, **kwargs):
        try:
            return func(self, cellset_id, *args, **kwargs)

        finally:
            if kwargs.get("delete_cellset", True):
                sandbox_name = kwargs.get("sandbox_name", None)
                try:
                    self.delete_cellset(cellset_id=cellset_id, sandbox_name=sandbox_name)

                except TM1pyRestException as ex:
                    # Fail silently if cellset is already removed
                    if not ex.status_code == 404:
                        raise ex

    return wrapper