Skip to content
Merged
17 changes: 15 additions & 2 deletions dashboard/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ def update(
ctrl.figure_update(fig)


@state.change("experiment")
@state.change(
"experiment",
"experiment_date_range",
)
def update_on_change_experiment(**kwargs):
# skip if triggered on server ready (all state variables marked as modified)
if len(state.modified_keys) == 1:
Expand Down Expand Up @@ -361,14 +364,24 @@ def gui_setup():
# add toolbar components
with layout.toolbar:
vuetify.VSpacer()
# experiment selector
vuetify.VSelect(
v_model=("experiment",),
label="Experiments",
items=(experiments,),
dense=True,
hide_details=True,
prepend_icon="mdi-atom",
style="max-width: 250px",
style="max-width: 250px; margin-right: 14px;",
)
# date range selector for experiment filtering
vuetify.VDateInput(
v_model=("experiment_date_range",),
label="Date range",
multiple="range",
dense=True,
hide_details=True,
style="max-width: 250px; margin-right: 14px;",
)
# set up router view
with layout.content:
Expand Down
8 changes: 6 additions & 2 deletions dashboard/model_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from lume_model.models.ensemble import NNEnsemble
from lume_model.models.gp_model import GPModel
from trame.widgets import vuetify3 as vuetify
from utils import verify_input_variables, timer, load_config_dict
from utils import verify_input_variables, timer, load_config_dict, create_date_filter
from error_manager import add_error
from sfapi_manager import monitor_sfapi_job
from state_manager import state
Expand Down Expand Up @@ -190,9 +190,13 @@ async def training_kernel(self):
client_id=state.sfapi_client_id, secret=state.sfapi_key
) as client:
perlmutter = await client.compute(Machine.perlmutter)
# Upload the config.yaml to nersc
# upload the configuration file to NERSC
config_dict = load_config_dict(state.experiment)
config_dict["simulation_calibration"] = state.simulation_calibration
# add date range filter to the configuration dictionary
date_filter = create_date_filter(state.experiment_date_range)
config_dict["date_filter"] = date_filter
Comment on lines +196 to +198
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should add to the configuration file a new section that reads, e.g.,

date_filter:
  date:
    $gte: 2024-03-28 00:00:00
    $lte: 2024-03-28 23:59:59.999000

# define the target path on NERSC
target_path = "/global/cfs/cdirs/m558/superfacility/model_training"
[target_path] = await perlmutter.ls(target_path, directory=True)
with tempfile.TemporaryDirectory() as temp_dir:
Expand Down
3 changes: 3 additions & 0 deletions dashboard/state_manager.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from pathlib import Path
from trame.app import get_server
from trame.widgets import vuetify3 as vuetify


EXPERIMENTS_PATH = Path.cwd().parent / "experiments/"
Expand All @@ -8,6 +9,7 @@
server = get_server(client_type="vue3")
state = server.state
ctrl = server.controller
vuetify.enable_lab() # Enable Labs components


def initialize_state():
Expand All @@ -23,6 +25,7 @@ def initialize_state():
][0]
print(f"Setting default experiment to {default_experiment}...")
state.experiment = default_experiment
state.experiment_date_range = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the config.yaml file contains a section

date_filter:
  date:
    $gte: 2024-03-28 00:00:00
    $lte: 2024-03-28 23:59:59.999000

will experiment_date_range be initialized with these values in the dashboad?

# ML model
state.model_type = "Neural Network (single)"
state.model_training = False
Expand Down
38 changes: 37 additions & 1 deletion dashboard/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,47 @@ def load_variables(experiment):
return (input_variables, output_variables, simulation_calibration)


def create_date_filter(experiment_date_range):
# build date filter if date range is set
date_filter = {}
if experiment_date_range:
start_date = pd.to_datetime(experiment_date_range[0].to_datetime())
start_date = start_date.to_pydatetime().replace(hour=0, minute=0, second=0)
# VDateInput returns exclusive end date for date ranges:
# - subtract 1 day for multi-date ranges with different start/end dates
# - do not subtract anything (use end date as is) for single-date ranges
end_date = pd.to_datetime(experiment_date_range[-1].to_datetime())
end_date_correction = (
pd.Timedelta(days=0)
if len(experiment_date_range) == 1
else pd.Timedelta(days=1)
)
end_date = end_date - end_date_correction
end_date = end_date.to_pydatetime().replace(hour=23, minute=59, second=59)
# remove timezone info to match naive datetime in database
start_date = (
start_date.replace(tzinfo=None) if start_date.tzinfo else start_date
)
end_date = end_date.replace(tzinfo=None) if end_date.tzinfo else end_date
date_filter = {
"date": {
"$gte": start_date,
"$lte": end_date,
}
}
print(f"Filtering data between {start_date.date()} and {end_date.date()}...")
return date_filter


@timer
def load_data(db):
print("Loading data from database...")
# create date filter if date range is set
date_filter = create_date_filter(state.experiment_date_range)
# load experiment and simulation data points in dataframes
exp_data = pd.DataFrame(db[state.experiment].find({"experiment_flag": 1}))
exp_data = pd.DataFrame(
db[state.experiment].find({"experiment_flag": 1, **date_filter})
)
sim_data = pd.DataFrame(db[state.experiment].find({"experiment_flag": 0}))
# Store '_id', 'date' as string
for key in ["_id", "date"]:
Expand Down
3 changes: 2 additions & 1 deletion ml/train_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,8 @@ def write_model(model, model_type, experiment, db):

# Extract experimental and simulation data from the database as pandas dataframe
db = connect_to_db(config_dict)
df_exp = pd.DataFrame(db[experiment].find({"experiment_flag": 1}))
date_filter = config_dict["date_filter"]
Copy link
Contributor

@RemiLehe RemiLehe Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we modify this so that, if there is no dates in the config.yaml file, it simply ignores the date selection? e.g. config_dict.get( 'date_filter', {} )

df_exp = pd.DataFrame(db[experiment].find({"experiment_flag": 1, **date_filter}))
Comment on lines 442 to 443
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change mimics the new lines 111-113 in dashboard/utils.py:

-    exp_data = pd.DataFrame(db[state.experiment].find({"experiment_flag": 1}))
+    exp_data = pd.DataFrame(
+        db[state.experiment].find({"experiment_flag": 1, **date_filter})
+    )

df_sim = pd.DataFrame(db[experiment].find({"experiment_flag": 0}))

# Apply simulation calibration to the simulation data
Expand Down
Loading