Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/api/modules/declarative_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ def get_nonchainsuccession_violations(job_id: str, request: Request) -> ReturnGr
return request.app.state.jobs[job_id].result.get("nonchainsuccession", [])


# **************** Retrieving Declarative Model Attributes - PM4PY ****************
# **************** Retrieving Declarative Model Attributes - PQL Queries ****************


@router.get("/get_always_after_pql/")
Expand Down
136 changes: 86 additions & 50 deletions backend/pql_queries/declarative_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

# **************** Formatting Function ****************

def format_graph_and_table (curr_df: pd.DataFrame) -> ReturnGraphType:

def format_graph_and_table(curr_df: pd.DataFrame) -> ReturnGraphType:
"""Formats the DataFrame into a graph and table structure.

Args:
Expand All @@ -28,44 +29,55 @@ def format_graph_and_table (curr_df: pd.DataFrame) -> ReturnGraphType:
Returns:
ReturnGraphType: A dictionary containing the formatted graph and table.
"""
output: ReturnGraphType = {"graphs": [], "tables": []}

if not curr_df.empty :
if curr_df.shape[1] == 3 :
output: ReturnGraphType = {"graphs": [], "tables": []}

if not curr_df.empty:
if curr_df.shape[1] == 3:
nodes = []
edges = []
for i, row in curr_df.iterrows(): # type: ignore
for i, row in curr_df.iterrows(): # type: ignore
nodes.append(str(row[curr_df.columns[0]])) # type: ignore
nodes.append(str(row[curr_df.columns[1]])) # type: ignore
edges.append({ # type: ignore
'from': str(row[curr_df.columns[0]]), # type: ignore
'to': str(row[curr_df.columns[1]]), # type: ignore
'label': str(row[curr_df.columns[2]]) # type: ignore
})

nodes = [{'id': str(ele)} for ele in list(set(list(nodes)))] # type: ignore
output["graphs"].append({
"nodes": nodes, # type: ignore
"edges": edges
})

headers = list(curr_df.columns)
rows = curr_df.values.tolist() # type: ignore
output["tables"].append({
"headers": headers, # type: ignore
"rows": [[str(ele) for ele in row] for row in rows] # type: ignore
})
else :
headers = list(curr_df.columns)
rows = curr_df.values.tolist() # type: ignore
output["tables"].append({
"headers": headers, # type: ignore
"rows": [[str(ele) for ele in row] for row in rows] # type: ignore
})
edges.append(
{ # type: ignore
"from": str(row[curr_df.columns[0]]), # type: ignore
"to": str(row[curr_df.columns[1]]), # type: ignore
"label": str(row[curr_df.columns[2]]), # type: ignore
}
)

nodes = [{"id": str(ele)} for ele in list(set(list(nodes)))] # type: ignore
output["graphs"].append(
{
"nodes": nodes, # type: ignore
"edges": edges,
}
)

headers = list(curr_df.columns)
rows = curr_df.values.tolist() # type: ignore
output["tables"].append(
{
"headers": headers, # type: ignore
"rows": [[str(ele) for ele in row] for row in rows], # type: ignore
}
)
else:
headers = list(curr_df.columns)
rows = curr_df.values.tolist() # type: ignore
output["tables"].append(
{
"headers": headers, # type: ignore
"rows": [[str(ele) for ele in row] for row in rows], # type: ignore
}
)
return output


# **************** PQL Functions ****************


# Always before
def get_always_before_relation(celonis: CelonisConnectionManager) -> ReturnGraphType:
"""Compute Always-Before summary using PQL.
Expand All @@ -76,23 +88,37 @@ def get_always_before_relation(celonis: CelonisConnectionManager) -> ReturnGraph
Returns:
ReturnGraphType: A dictionary containing the formatted graph and table.
"""
target_df: pd.DataFrame = DataFrame(columns=["Activity A", "Activity B", "# Occurrences"])
act_table = get_activities(celonis) # type: ignore
activitiy_pairs = list(combinations(act_table["Activity"].to_list(), 2)) # type: ignore
for i, pair in enumerate(activitiy_pairs): # type: ignore
target_df: pd.DataFrame = DataFrame(
columns=["Activity A", "Activity B", "# Occurrences"]
)
act_table = get_activities(celonis) # type: ignore
activitiy_pairs = list(combinations(act_table["Activity"].to_list(), 2)) # type: ignore
for i, pair in enumerate(activitiy_pairs): # type: ignore
query = {
"A before B": f"""MATCH_PROCESS ("ACTIVITIES"."concept:name", NODE ['{pair[0]}'] as src,
NODE ['{pair[1]}'] as tgt CONNECTED BY EVENTUALLY [src , tgt])""",
"B before A": f"""MATCH_PROCESS ("ACTIVITIES"."concept:name", NODE ['{pair[1]}'] as src,
NODE ['{pair[0]}'] as tgt CONNECTED BY EVENTUALLY [src , tgt])""",
}
pair_df = celonis.get_dataframe_from_celonis(query) # type: ignore
if (pair_df["B before A"] == 1).any() and not (pair_df["A before B"] == 1).any(): # type: ignore
target_df.loc[i] = [pair[1], pair[0], int((pair_df["B before A"] == 1).sum())] # type: ignore
elif (pair_df["A before B"] == 1).any() and not (pair_df["B before A"] == 1).any(): # type: ignore
target_df.loc[i] = [pair[0], pair[1], int((pair_df["A before B"] == 1).sum())] # type: ignore
output = format_graph_and_table(target_df)
return output
pair_df = celonis.get_dataframe_from_celonis(query) # type: ignore
if (pair_df["B before A"] == 1).any() and not (
pair_df["A before B"] == 1
).any(): # type: ignore
target_df.loc[i] = [
pair[1],
pair[0],
int((pair_df["B before A"] == 1).sum()),
] # type: ignore
elif (pair_df["A before B"] == 1).any() and not (
pair_df["B before A"] == 1
).any(): # type: ignore
target_df.loc[i] = [
pair[0],
pair[1],
int((pair_df["A before B"] == 1).sum()),
] # type: ignore
output = format_graph_and_table(target_df)
return output


# Always after
Expand All @@ -107,18 +133,28 @@ def get_always_after_relation(celonis: CelonisConnectionManager) -> ReturnGraphT
"""
target_df = DataFrame(columns=["Activity A", "Activity B", "# Occurrences"])
act_table = get_activities(celonis)
activitiy_pairs = list(combinations(act_table["Activity"].to_list(), 2)) # type: ignore
for i, pair in enumerate(activitiy_pairs): # type: ignore
activitiy_pairs = list(combinations(act_table["Activity"].to_list(), 2)) # type: ignore
for i, pair in enumerate(activitiy_pairs): # type: ignore
query = {
"A after B": f"""MATCH_PROCESS ("ACTIVITIES"."concept:name", NODE ['{pair[1]}'] as src,
NODE ['{pair[0]}'] as tgt CONNECTED BY EVENTUALLY [src , tgt])""",
"B after A": f"""MATCH_PROCESS ("ACTIVITIES"."concept:name", NODE ['{pair[0]}'] as src,
NODE ['{pair[1]}'] as tgt CONNECTED BY EVENTUALLY [src , tgt])""",
}
pair_df = celonis.get_dataframe_from_celonis(query) # type: ignore
if (pair_df["B after A"] == 1).any() and not (pair_df["A after B"] == 1).any(): # type: ignore
target_df.loc[i] = [pair[1], pair[0], int((pair_df["B after A"] == 1).sum())] # type: ignore
elif (pair_df["A after B"] == 1).any() and not (pair_df["B after A"] == 1).any(): # type: ignore
target_df.loc[i] = [pair[0], pair[1], int((pair_df["A after B"] == 1).sum())] # type: ignore
output = format_graph_and_table(target_df)
return output
pair_df = celonis.get_dataframe_from_celonis(query) # type: ignore
if (pair_df["B after A"] == 1).any() and not (pair_df["A after B"] == 1).any(): # type: ignore
target_df.loc[i] = [
pair[1],
pair[0],
int((pair_df["B after A"] == 1).sum()),
] # type: ignore
elif (pair_df["A after B"] == 1).any() and not (
pair_df["B after A"] == 1
).any(): # type: ignore
target_df.loc[i] = [
pair[0],
pair[1],
int((pair_df["A after B"] == 1).sum()),
] # type: ignore
output = format_graph_and_table(target_df)
return output
Loading
Loading