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
9 changes: 9 additions & 0 deletions dash_app/components/form_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,15 @@ def manual_filename_input(id):
)


def normalize_scores_line_level(id):
return dbc.Col(
dbc.Checkbox(
id=id,
label="Normalize scores",
),
)


def redirect_to_results_input(id):
return dbc.Col(
[
Expand Down
3 changes: 3 additions & 0 deletions dash_app/components/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
columns_to_include_input,
analysis_name_input,
base_path_input,
normalize_scores_line_level,
)


Expand Down Expand Up @@ -389,6 +390,7 @@ def project_settings_form(
color_by_directory_id,
line_display_mode_id,
manual_filename_id,
normalize_scores_id,
):
submit_btn = submit_button(submit_id, "Apply")
form = dbc.Form(
Expand All @@ -401,6 +403,7 @@ def project_settings_form(
color_by_directory_input(color_by_directory_id),
manual_filename_input(manual_filename_id),
line_display_mode_input(line_display_mode_id),
normalize_scores_line_level(normalize_scores_id),
],
width=8,
),
Expand Down
13 changes: 12 additions & 1 deletion dash_app/components/layouts.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def create_ano_line_level_result_layout(
error_toast_id,
success_toast_id,
grid_image_link_id,
normalize_scores_id,
):

error_toast_row = dbc.Row(error_toast(error_toast_id))
Expand Down Expand Up @@ -126,9 +127,17 @@ def create_ano_line_level_result_layout(
className="dbc mt-3 ms-4 me-4",
)

normalize_scores_store = dbc.Row(dcc.Store(id=normalize_scores_id))

layout = [
dbc.Container(
[metadata_row, create_grid_image_link, error_toast_row, success_toast_row]
[
metadata_row,
create_grid_image_link,
error_toast_row,
success_toast_row,
normalize_scores_store,
]
),
dbc.Container(plot_selector_row),
dbc.Container(plot_row, fluid=True),
Expand Down Expand Up @@ -292,6 +301,7 @@ def create_project_layout(
edit_name_input_id,
submit_edit_name_id,
task_logs_modal_id,
normalize_scores_id,
):

error_toast_row = dbc.Row(error_toast(error_toast_id))
Expand Down Expand Up @@ -351,6 +361,7 @@ def create_project_layout(
color_by_directory_id,
line_display_mode_input_id,
manual_filename_id,
normalize_scores_id,
),
body=True,
),
Expand Down
7 changes: 7 additions & 0 deletions dash_app/pages/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def layout(project_id=None, **kwargs):
"edit-name-input",
"submit-edit-name",
"task-logs-modal-project",
"normalize-scores-project",
)


Expand Down Expand Up @@ -148,9 +149,11 @@ def get_analyses(_, project_id):
Output("color-by-directory-project", "value"),
Output("line-display-mode-project", "value"),
Output("manual-filename-project", "value"),
Output("normalize-scores-project", "value"),
Input("project-id", "data"),
)
def get_settings(project_id):
# TODO: what is return True?
if not project_id:
return True

Expand All @@ -164,6 +167,7 @@ def get_settings(project_id):
settings.get("color_by_directory"),
settings.get("line_level_display_mode"),
settings.get("manual_filename_input"),
settings.get("line_level_normalization"),
)


Expand Down Expand Up @@ -281,6 +285,7 @@ def edit_analysis_name(submit_n_clicks, new_name, analysis_id, url_path):
State("color-by-directory-project", "value"),
State("line-display-mode-project", "value"),
State("manual-filename-project", "value"),
State("normalize-scores-project", "value"),
State("project-id", "data"),
prevent_initial_call=True,
)
Expand All @@ -290,6 +295,7 @@ def apply_settings(
color_by_directory,
line_display_mode,
manual_filename_input,
normalize_scores,
project_id,
):
if not n_clicks:
Expand All @@ -300,6 +306,7 @@ def apply_settings(
"color_by_directory": color_by_directory,
"line_level_display_mode": line_display_mode,
"manual_filename_input": manual_filename_input,
"line_level_normalization": normalize_scores,
}
response, error = make_api_call(
payload, f"projects/{project_id}/settings", requests_type="PATCH"
Expand Down
25 changes: 23 additions & 2 deletions dash_app/pages/result_pages/ano_line_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def layout(analysis_id=None, **kwargs):
"error-toast-ano-line-res",
"success-toats-ano-line-res",
"multi-plot-link-ano-line-res",
"normalize-scores-store-ano-line-res",
)

return base + content
Expand Down Expand Up @@ -74,6 +75,7 @@ def get_data(analysis_id):
Output("error-toast-ano-line-res", "children", allow_duplicate=True),
Output("error-toast-ano-line-res", "is_open", allow_duplicate=True),
Output("multi-plot-link-ano-line-res", "href"),
Output("normalize-scores-store-ano-line-res", "data"),
Input("stored-data-ano-line-res", "data"),
State("analysis-id-ano-line-res", "data"),
prevent_initial_call=True,
Expand Down Expand Up @@ -102,19 +104,35 @@ def generate_dropdown_and_metadata(encoded_df, analysis_id):
str(error),
True,
dash.no_update,
dash.no_update,
)

metadata = response.json()
project_id = metadata.get("project_id")
metadata_rows = format_metadata_rows(metadata)

response_settings, error_settings = make_api_call(
{}, f"projects/{project_id}/settings", "GET"
)
if error_settings or response_settings is None:
return (
dash.no_update,
dash.no_update,
dash.no_update,
str(error_settings),
True,
dash.no_update,
dash.no_update,
)

return (
options,
[html.Tbody(metadata_rows)],
f"/dash/project/{project_id}",
dash.no_update,
False,
f"/dash/analysis/ano-line-level/{analysis_id}/grid",
response_settings.json().get("line_level_normalization"),
)


Expand All @@ -124,9 +142,10 @@ def generate_dropdown_and_metadata(encoded_df, analysis_id):
Input("plot-selector-ano-line-res", "value"),
Input("switch", "value"),
State("stored-data-ano-line-res", "data"),
State("normalize-scores-store-ano-line-res", "data"),
prevent_initial_call=True,
)
def render_plot(selected_plot, switch_on, encoded_df):
def render_plot(selected_plot, switch_on, encoded_df, normalize_scores):
if not encoded_df or not selected_plot:
return dash.no_update, dash.no_update

Expand All @@ -141,7 +160,9 @@ def render_plot(selected_plot, switch_on, encoded_df):
"minWidth": "600px",
"width": "90%",
}
fig = create_line_level_plot(df, selected_plot, theme)
fig = create_line_level_plot(
df, selected_plot, theme, normalize_scores=normalize_scores
)

return fig, style

Expand Down
42 changes: 27 additions & 15 deletions dash_app/utils/plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,19 @@ def get_options(df) -> list[dict]:
return [{"label": seq_id, "value": seq_id} for seq_id in seq_ids]


def create_line_level_plot(df, selected_plot, theme="plotly_white"):
def create_line_level_plot(
df, selected_plot, theme="plotly_white", normalize_scores=True
):
df = df.filter(pl.col("seq_id") == selected_plot)

if df.get_column("line_number", default=None) is None:
df = df.with_row_index()
xaxis_title = "Index"
x_column = "index"
else:
xaxis_title = "Line Number"
x_column = "line_number"

prediction_columns = [
col
for col in df.columns
Expand All @@ -31,18 +43,10 @@ def create_line_level_plot(df, selected_plot, theme="plotly_white"):
],
]

df = df.filter(pl.col("seq_id") == selected_plot)
if df.get_column("line_number", default=None) is None:
df = df.with_row_index()
xaxis_title = "Index"
x_column = "index"
else:
xaxis_title = "Line Number"
x_column = "line_number"

for columns in measure_groups:
if columns:
df = _normalize_prediction_columns(df, columns)
if normalize_scores:
for columns in measure_groups:
if columns:
df = _normalize_prediction_columns(df, columns)

# polars documentation says that map_elements is slow.
# Change if it becomes an issue.
Expand Down Expand Up @@ -72,13 +76,21 @@ def create_line_level_plot(df, selected_plot, theme="plotly_white"):
)
)

title = (
f"Normalized Anomaly Score<br>File: {file_name}<br>Directory: {directory_name}"
if normalize_scores
else f"Anomaly Score<br>File: {file_name}<br>Directory: {directory_name}"
)
fig.update_layout(
title=f"Normalized Anomaly Score<br>File: {file_name}<br>Directory: {directory_name}",
title=title,
xaxis_title=xaxis_title,
yaxis_title="Anomaly Score (0 - 1)",
yaxis_title="Anomaly Score (0 - 1)" if normalize_scores else "Anomaly Score",
template=theme,
)

if not normalize_scores:
fig.update_yaxes(type="log")

return fig


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Add normalization option to line level analysis

Revision ID: 1fce494a5a86
Revises: a9fe74ac20ca
Create Date: 2025-08-27 13:25:04.838544

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '1fce494a5a86'
down_revision = 'a9fe74ac20ca'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('settings', schema=None) as batch_op:
batch_op.add_column(sa.Column('line_level_normalization', sa.Boolean(), nullable=True))

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('settings', schema=None) as batch_op:
batch_op.drop_column('line_level_normalization')

# ### end Alembic commands ###
2 changes: 2 additions & 0 deletions server/api/crud_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ def update_settings(project_id: int):
settings.color_by_directory = validated_data.color_by_directory
settings.line_level_display_mode = validated_data.line_level_display_mode
settings.manual_filename_input = validated_data.manual_filename_input
settings.line_level_normalization = validated_data.line_level_normalization

db.session.commit()

return {}, 200
Expand Down
1 change: 1 addition & 0 deletions server/api/validator_models/crud_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ class SettingsParams(BaseModel):
"data_points_only"
)
manual_filename_input: bool
line_level_normalization: bool
2 changes: 2 additions & 0 deletions server/models/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class Settings(db.Model):
color_by_directory = db.Column(db.Boolean, default=True)
line_level_display_mode = db.Column(db.String, default="data_points_only")
manual_filename_input = db.Column(db.Boolean, default=False)
line_level_normalization = db.Column(db.Boolean, default=True)

project_id = db.Column(db.Integer, db.ForeignKey("projects.id"), nullable=False)
project = db.relationship("Project", back_populates="settings")
Expand All @@ -21,4 +22,5 @@ def to_dict(self):
"color_by_directory": self.color_by_directory,
"line_level_display_mode": self.line_level_display_mode,
"manual_filename_input": self.manual_filename_input,
"line_level_normalization": self.line_level_normalization,
}
Loading