Skip to content

Commit

Permalink
Hide decimator internals (Avaiga#1959)
Browse files Browse the repository at this point in the history
* Added a sample for decimation
* Change chart mode to markers for demoing decimator zoom facility
* Hide decimator internals for the time begin
* Add return types where needed
  • Loading branch information
FabienLelaquais authored Oct 8, 2024
1 parent 08dd9a1 commit 8c5cd89
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 18 deletions.
2 changes: 1 addition & 1 deletion doc/gui/examples/charts/advanced_large_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class Processing(Enum):
# Create the DataFrame
data = pd.DataFrame({"X": x_values, "Y": y_values_noise})

page = "<|{data}|chart|x=X|y=Y|mode=lines|decimator=decimator|>"
page = "<|{data}|chart|x=X|y=Y|mode=markers|decimator=decimator|>"

if __name__ == "__main__":
Gui(page).run(title="Chart - Advanced - Large datasets")
15 changes: 7 additions & 8 deletions taipy/gui/data/decimator/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def _df_apply_decimator(
x_column_name = self.__get_indexed_df_col(df)
column_list = [x_column_name, y_column_name, z_column_name] if z_column_name else [x_column_name, y_column_name]
points = df[column_list].to_numpy()
mask = self.decimate(points, payload)
mask = self._decimate(points, payload)
return df[mask], is_copied

def _on_decimate_df(
Expand Down Expand Up @@ -171,7 +171,7 @@ def _on_decimate_df(
is_decimator_applied = False
if nb_rows_max and self._is_applicable(df, nb_rows_max, chart_mode):
try:
df, is_copied = self.apply_decimator(
df, is_copied = self._apply_decimator(
t.cast(pd.DataFrame, df),
x_column,
y_column,
Expand All @@ -188,16 +188,15 @@ def _on_decimate_df(
df = df.filter(filterd_columns, axis=1)
return df, is_decimator_applied, is_copied

def on_decimate(
def _on_decimate(
self,
df: pd.DataFrame,
decimator_instance_payload: t.Dict[str, t.Any],
decimator_payload: t.Dict[str, t.Any],
is_copied: bool = False,
filter_unused_columns: bool = True,
):
) -> t.Tuple:
"""NOT DOCUMENTED
This function is executed whenever a decimator is found during runtime.
Users can override this function by providing an alternate implementation inside the constructor
Expand Down Expand Up @@ -225,15 +224,15 @@ def on_decimate(
_warn("Error executing user defined on_decimate function: ", e)
return self._on_decimate_df(df, decimator_instance_payload, decimator_payload, filter_unused_columns)

def apply_decimator(
def _apply_decimator(
self,
dataframe: pd.DataFrame,
x_column_name: t.Optional[str],
y_column_name: str,
z_column_name: str,
payload: t.Dict[str, t.Any],
is_copied: bool,
):
) -> t.Tuple:
"""NOT DOCUMENTED
This function is executed whenever a decimator is applied to the data.
Expand Down Expand Up @@ -263,7 +262,7 @@ def apply_decimator(
return self._df_apply_decimator(dataframe, x_column_name, y_column_name, z_column_name, payload, is_copied)

@abstractmethod
def decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:
def _decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:
"""NOT DOCUMENTED
Decimate the dataset.
Expand Down
2 changes: 1 addition & 1 deletion taipy/gui/data/decimator/lttb.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def _areas_of_triangles(a, bs, c):
a_minus_bs = a - bs
return 0.5 * abs((a[0] - c[0]) * (bs_minus_a[:, 1]) - (a_minus_bs[:, 0]) * (c[1] - a[1]))

def decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:
def _decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:
n_out = self._n_out
if n_out >= data.shape[0]:
return np.full(len(data), True)
Expand Down
2 changes: 1 addition & 1 deletion taipy/gui/data/decimator/minmax.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def __init__(
super().__init__(threshold, zoom)
self._n_out = n_out // 2

def decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:
def _decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:
if self._n_out >= data.shape[0]:
return np.full(len(data), False)
# Create a boolean mask
Expand Down
10 changes: 5 additions & 5 deletions taipy/gui/data/decimator/rdp.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def __init__(
self._n_out = n_out

@staticmethod
def dsquared_line_points(P1, P2, points):
def __dsquared_line_points(P1, P2, points):
"""
Calculate only squared distance, only needed for comparison
"""
Expand Down Expand Up @@ -93,7 +93,7 @@ def __rdp_epsilon(data, epsilon: int):
P1 = data[start]
P2 = data[end]
points = data[start + 1 : end]
dsq = RDP.dsquared_line_points(P1, P2, points)
dsq = RDP.__dsquared_line_points(P1, P2, points)

mask_eps = dsq > epsilon**2

Expand Down Expand Up @@ -129,7 +129,7 @@ def __rdp_points(M, n_out):
(start, end) = stack.pop()
if end - start <= 1:
continue
dsq = RDP.dsquared_line_points(M[start], M[end], M[start + 1 : end])
dsq = RDP.__dsquared_line_points(M[start], M[end], M[start + 1 : end])
max_dist_index = np.argmax(dsq) + start + 1
weights[max_dist_index] = np.amax(dsq)
stack.append((start, max_dist_index))
Expand All @@ -138,9 +138,9 @@ def __rdp_points(M, n_out):

return weights >= maxTolerance

def decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:
def _decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:
if self._epsilon:
return RDP.__rdp_epsilon(data, self._epsilon)
elif self._n_out:
return RDP.__rdp_points(data, self._n_out)
raise RuntimeError("RDP Decimator failed to run. Fill in either 'epsilon' or 'n_out' value")
raise RuntimeError("RDP Decimator failed to run. One of 'epsilon' or 'n_out' values must be specified")
2 changes: 1 addition & 1 deletion taipy/gui/data/decimator/scatter_decimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def __init__(
self._binning_ratio = binning_ratio if binning_ratio > 0 else 1
self._max_overlap_points = max_overlap_points if max_overlap_points is not None else 3

def decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:
def _decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:
n_rows = data.shape[0]
mask = np.empty(n_rows, dtype=bool)
width = payload.get("width", None)
Expand Down
2 changes: 1 addition & 1 deletion taipy/gui/data/pandas_data_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ def __get_data( # noqa: C901
if isinstance(decimator_instance, PropertyType.decimator.value):
# Run the on_decimate method -> check if the decimator should be applied
# -> apply the decimator
decimated_df, is_decimator_applied, is_copied = decimator_instance.on_decimate(
decimated_df, is_decimator_applied, is_copied = decimator_instance._on_decimate(
df, decimator_pl, decimator_payload, is_copied
)
# add decimated dataframe to the list of decimated
Expand Down

0 comments on commit 8c5cd89

Please sign in to comment.