Skip to content

Commit

Permalink
Merge pull request #55 from DJHig/fix-calculated-members
Browse files Browse the repository at this point in the history
Fix build headers for aggregate queries
  • Loading branch information
MariusWirtz authored Aug 1, 2018
2 parents 7643a06 + 38c9d66 commit 0dcc554
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 40 deletions.
104 changes: 79 additions & 25 deletions TM1py/Services/CellService.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,19 @@ def execute_view(self, cube_name, view_name, cell_properties=None, private=True,
cellset_id = self.create_cellset_from_view(cube_name=cube_name, view_name=view_name, private=private)
return self.extract_cellset(cellset_id=cellset_id, cell_properties=cell_properties, top=top)

def execute_mdx_raw(self, mdx, cell_properties=None, elem_properties=None, member_properties=None, top=None):
def execute_mdx_raw(
self,
mdx,
cell_properties=None,
elem_properties=None,
member_properties=None,
top=None):
""" 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', 'Ordinal', 'RuleDerived', ...]
: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 top: Integer limiting the number of cells and the number or rows returned
:return: Raw format from TM1.
"""
Expand All @@ -232,6 +239,7 @@ def execute_view_raw(
:param private: True (private) or False (public)
:param cell_properties: List of properties to be queried from the cell. E.g. ['Value', 'Ordinal', 'RuleDerived', ...]
: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 top: Integer limiting the number of cells and the number or rows returned
:return: Raw format from TM1.
"""
Expand Down Expand Up @@ -321,7 +329,13 @@ def execute_view_cellcount(self, cube_name, view_name, private=True):
cellset_id = self.create_cellset_from_view(cube_name=cube_name, view_name=view_name, private=private)
return self.extract_cellset_cellcount(cellset_id)

def execute_mdx_ui_dygraph(self, mdx, value_precision=2):
def execute_mdx_ui_dygraph(
self,
mdx,
elem_properties=None,
member_properties=None,
value_precision=2,
top=None):
""" 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
Expand All @@ -339,14 +353,28 @@ def execute_mdx_ui_dygraph(self, mdx, value_precision=2):
['Q4-2004', 14321501.940000001, 10333095.839474997]]
},
: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
:return: dict : { titles: [], headers: [axis][], cells: { Page0: [ [column name, column values], [], ... ], ...} }
"""
cellset_id = self.create_cellset(mdx)
data = self.extract_cellset_raw(cellset_id=cellset_id, member_properties=["Name", "UniqueName"])
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)
return Utils.build_ui_dygraph_arrays_from_cellset(raw_cellset_as_dict=data, value_precision=value_precision)

def execute_view_ui_dygraph(self, cube_name, view_name, private=True, value_precision=2):
def execute_view_ui_dygraph(
self,
cube_name,
view_name,
private=True,
elem_properties=None,
member_properties=None,
value_precision=2,
top=None):
"""
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.
Expand Down Expand Up @@ -376,14 +404,26 @@ def execute_view_ui_dygraph(self, cube_name, view_name, private=True, value_prec
: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: number decimals
:return:
"""
cellset_id = self.create_cellset_from_view(cube_name=cube_name, view_name=view_name, private=private)
data = self.extract_cellset_raw(cellset_id=cellset_id, member_properties=["Name", "UniqueName"])
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)
return Utils.build_ui_dygraph_arrays_from_cellset(raw_cellset_as_dict=data, value_precision=value_precision)

def execute_mdx_ui_array(self, mdx, value_precision=2):
def execute_mdx_ui_array(
self,
mdx,
elem_properties=None,
member_properties=None,
value_precision=2,
top=None):
"""
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.
Expand Down Expand Up @@ -411,14 +451,28 @@ def execute_mdx_ui_array(self, mdx, value_precision=2):
},
: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
:return: dict : { titles: [], headers: [axis][], cells: { Page0: { Row0: { [row values], Row1: [], ...}, ...}, ...} }
"""
cellset_id = self.create_cellset(mdx)
data = self.extract_cellset_raw(cellset_id=cellset_id, member_properties=["Name", "UniqueName"])
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)
return Utils.build_ui_arrays_from_cellset(raw_cellset_as_dict=data, value_precision=value_precision)

def execute_view_ui_array(self, cube_name, view_name, private=True, value_precision=2):
def execute_view_ui_array(
self,
cube_name,
view_name,
private=True,
elem_properties=None,
member_properties=None,
value_precision=2,
top=None):
"""
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.
Expand Down Expand Up @@ -448,11 +502,17 @@ def execute_view_ui_array(self, cube_name, view_name, private=True, value_precis
: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 properties to be queried from the member. E.g. ['Name', 'UniqueName']
:param value_precision: Integer (optional) specifying number of decimal places to return
: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)
data = self.extract_cellset_raw(cellset_id=cellset_id, member_properties=["Name", "UniqueName"])
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)
return Utils.build_ui_arrays_from_cellset(raw_cellset_as_dict=data, value_precision=value_precision)

@tidy_cellset
Expand All @@ -477,25 +537,15 @@ def extract_cellset_raw(
elif 'Ordinal' not in cell_properties:
cell_properties.append('Ordinal')

if not elem_properties:
elem_properties = ['UniqueName']
elif 'UniqueName' not in elem_properties:
elem_properties.append('UniqueName')

if not member_properties:
member_properties = ['UniqueName']
elif 'UniqueName' not in member_properties:
elem_properties.append('UniqueName')

request = "/api/v1/Cellsets('{cellset_id}')?$expand=" \
"Cube($select=Name;$expand=Dimensions($select=Name))," \
"Axes($expand=Tuples($expand=Members($select={member_properties};$expand=Element{elem_properties}){top_rows}))," \
"Axes($expand=Tuples($expand=Members($select={member_properties}{elem_properties}){top_rows}))," \
"Cells($select={cell_properties}{top_cells})" \
.format(cellset_id=cellset_id,
top_rows=";$top={}".format(top) if top else "",
cell_properties=",".join(cell_properties),
member_properties=",".join(member_properties),
elem_properties=("($select=" + ",".join(elem_properties) + ")") if len(elem_properties) > 0 else "",
elem_properties=(";$expand=Element($select=" + ",".join(elem_properties) + ")") if len(elem_properties or []) > 0 else "",
top_cells=";$top={}".format(top) if top else "")
response = self._rest.GET(request=request)
return response.json()
Expand Down Expand Up @@ -540,10 +590,14 @@ def extract_cellset(self, cellset_id, cell_properties=None, top=None):
cell_properties = ['Value', 'Ordinal']
elif 'Ordinal' not in cell_properties:
cell_properties.append('Ordinal')
raw_cellset = self.extract_cellset_raw(cellset_id, cell_properties=cell_properties, top=top)
return Utils.build_content_from_cellset(raw_cellset_as_dict=raw_cellset,
cell_properties=cell_properties,
top=top)

raw_cellset = self.extract_cellset_raw(
cellset_id,
cell_properties=cell_properties,
elem_properties=['UniqueName'],
member_properties=['UniqueName'],
top=top)
return Utils.build_content_from_cellset(raw_cellset_as_dict=raw_cellset, top=top)

def create_cellset(self, mdx):
""" Execute MDX in order to create cellset at server. return the cellset-id
Expand Down
19 changes: 4 additions & 15 deletions TM1py/Utils/Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,10 @@ def sort_addresstuple(cube_dimensions, unsorted_addresstuple):
return tuple(sorted_addresstupple)


def build_content_from_cellset(raw_cellset_as_dict, cell_properties, top=None):
def build_content_from_cellset(raw_cellset_as_dict, top=None):
""" transform raw cellset data into concise dictionary
:param raw_cellset_as_dict:
:param cell_properties:
:param top: Maximum Number of cells
:return:
"""
Expand Down Expand Up @@ -97,10 +96,7 @@ def build_content_from_cellset(raw_cellset_as_dict, cell_properties, top=None):
coordinates = elements_on_axe0 + elements_on_axe2 + elements_on_axe1
coordinates_sorted = sort_addresstuple(cube_dimensions, coordinates)
# get cell properties
content_as_dict[coordinates_sorted] = {}
for cell_property in cell_properties:
value = raw_cellset_as_dict['Cells'][ordinal_cells][cell_property]
content_as_dict[coordinates_sorted][cell_property] = value
content_as_dict[coordinates_sorted] = raw_cellset_as_dict['Cells'][ordinal_cells]
ordinal_axe0 += 1
ordinal_cells += 1
if top is not None and ordinal_cells >= top:
Expand Down Expand Up @@ -248,15 +244,8 @@ def build_headers_from_cellset(raw_cellset_as_dict, force_header_dimensionality=
members = []
for tindex in range(cardinality[axis]):
tuples_as_dict = raw_cellset_as_dict['Axes'][axis]['Tuples'][tindex]['Members']
members_on_row = [
{ k:v for (k,v) in zip(['Name']+list(member['Element'].keys()),[member['Name']]+list(member['Element'].values())) }
for member in tuples_as_dict]
if len(members_on_row) == 1:
name = members_on_row[0]['Name']
else:
name = ' / '.join(tuple(member['Name'] for member in members_on_row))

members.append({'name': name, 'members':members_on_row})
name = ' / '.join(tuple(member['Name'] for member in tuples_as_dict))
members.append({'name': name, 'members':tuples_as_dict})

if (axis == dimensionality -1 and cardinality[axis] == 1):
titles = members
Expand Down

0 comments on commit 0dcc554

Please sign in to comment.