Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update INH/ACT/Z-SCORE plots #114

Merged
merged 12 commits into from
Sep 26, 2023
5 changes: 5 additions & 0 deletions dashboard/assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@
align-items: center;
}

.stats-input{
margin-left: 10px ;
width: 150px
}

.btn-report {
width: 350px;
}
Expand Down
71 changes: 63 additions & 8 deletions dashboard/data/combine.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ def combine_bmg_echo_data(
df_stats: pd.DataFrame,
plate_values: np.ndarray,
modes: dict[Mode],
echo_keys: tuple[str] = ("Destination Plate Barcode", "Destination Well"),
) -> pd.DataFrame:
"""
Combine Echo data with activation and inhibition values.
Expand All @@ -147,9 +146,11 @@ def combine_bmg_echo_data(
:param df_stats: dataframe containing statistics for each plate
:param plate_values: numpy array with activation and inhibition values - shape: (#plates, 2, 16, 24)
:param modes: dictionary with modes for each plate
:param echo_keys: keys used to merge Echo data with activation and inhibition values #TODO: maybe not necessary and should be hard-coded?
:return: dataframe with Echo data and activation and inhibition values
"""
PLATE = "Destination Plate Barcode"
WELL = "Destination Well"

if modes is None:
modes = dict()
act_inh_dict = get_activation_inhibition_zscore_dict(df_stats, plate_values, modes)
Expand All @@ -158,17 +159,19 @@ def combine_bmg_echo_data(
activation_inhibition_df = get_activation_inhibition_zscore_df(
barcode, values_dict
)

dfs.append(
echo_df.merge(
activation_inhibition_df,
left_on=echo_keys,
right_on=("Barcode", "Well"),
activation_inhibition_df.merge(
echo_df, left_on=("Barcode", "Well"), right_on=(PLATE, WELL), how="left"
)
)

bmg_echo_combined_df = pd.concat(dfs, ignore_index=True).drop(
columns=["Barcode", "Well"]
bmg_echo_combined_df = (
pd.concat(dfs, ignore_index=True)
.drop(columns=[PLATE, WELL])
.rename(columns={"Barcode": PLATE, "Well": WELL})
)

return reorder_bmg_echo_columns(bmg_echo_combined_df)


Expand All @@ -178,8 +181,60 @@ def split_compounds_controls(df: pd.DataFrame) -> tuple[pd.DataFrame]:
:param df: dataframe with compounds and controls
:return: tuple of dataframes with compounds, positive controls and negative controls
"""
columns_to_drop = ["EOS", "Source Plate Barcode", "Source Well", "Actual Volume"]
mask = df["Destination Well"].str[-2:]
control_pos_df = df[mask == "24"]
control_pos_df = control_pos_df.drop(
columns=columns_to_drop, errors="ignore"
) # no error raised if the specified column does not exist
control_neg_df = df[mask == "23"]
control_neg_df = control_neg_df.drop(columns=columns_to_drop, errors="ignore")
compounds_df = df[~mask.isin(["23", "24"])]
return compounds_df, control_pos_df, control_neg_df


def aggregate_well_plate_stats(
df: pd.DataFrame, assign_x_coords: bool = False
) -> tuple[pd.DataFrame]:
"""
Aggregates the statistics (mean and std) per plate needed for the plots.
self
:param df: dataframe with echo and bmg data combined
:param key: key to group by
:param assign_x_coords: whether to assign x coordinates to the plates
:return: dataframe: echo_bmg_df with additional columns useful for
plotting activation/inhibition/z-score and one with statistics per plate
"""

PLATE = "Destination Plate Barcode"
ACTIVATION = "% ACTIVATION"
INHIBITION = "% INHIBITION"
Z_SCORE = "Z-SCORE"

stats_df = (
df.groupby(PLATE)[[ACTIVATION, INHIBITION, Z_SCORE]]
.agg(["mean", "std", "min", "max"])
.reset_index()
)
stats_df.columns = [
PLATE,
f"{ACTIVATION}_mean",
f"{ACTIVATION}_std",
f"{ACTIVATION}_min",
f"{ACTIVATION}_max",
f"{INHIBITION}_mean",
f"{INHIBITION}_std",
f"{INHIBITION}_min",
f"{INHIBITION}_max",
f"{Z_SCORE}_mean",
f"{Z_SCORE}_std",
f"{Z_SCORE}_min",
f"{Z_SCORE}_max",
]

if assign_x_coords:
for col in [ACTIVATION, INHIBITION, Z_SCORE]:
stats_df = stats_df.sort_values(by=f"{col}_mean") # sort by mean
stats_df[f"{col}_x"] = range(len(stats_df)) # get the x coordinates

return stats_df
1 change: 1 addition & 0 deletions dashboard/data/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pandas as pd


# TODO: TO BE REMOVED???
def generate_dummy_links_dataframe(compound_ids: list[str]) -> pd.DataFrame:
eos = [
f"[EOS{i+1}](https://ecbd.eu/compound/EOS{i+1})"
Expand Down
1 change: 1 addition & 0 deletions dashboard/pages/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
dcc.Store(id="error-msg", data=""),
html.Div(id="dummy"),
dcc.Store(id="user-uuid", storage_type="local"),
dcc.Store(id="report-data-csv", storage_type="local"),
dcc.Store(id="report-data-second-stage", storage_type="local"),
dcc.Store(id="report-data-third-stage", storage_type="local"),
],
Expand Down
Loading