Skip to content
Open
Show file tree
Hide file tree
Changes from 15 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
1 change: 1 addition & 0 deletions .github/workflows/build-windows-executable-app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ jobs:
cp -r src streamlit_exe
cp -r content streamlit_exe
cp -r assets streamlit_exe
cp -r scripts streamlit_exe
cp -r static streamlit_exe
cp -r example-data streamlit_exe
cp openms-bin/*.dll streamlit_exe
Expand Down
9 changes: 9 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,14 @@
],
}

with open('settings.json', 'r') as f:
settings = json.load(f)
if settings['enable_flashida']:
pages["🧠 FLASHIda"] = ([
st.Page(Path("content", "FLASHIda", "FLASHIdaWorkflow.py"), title="Workflow", icon="⚙️"),
st.Page(Path("content", "FLASHIda", "FLASHIdaSimulatorWorkflow.py"), title="Simulator", icon="⚙️"),
st.Page(Path("content", "FLASHIda", "FLASHIdaViewer.py"), title="Viewer", icon="👀"),
])

pg = st.navigation(pages, expanded=True)
pg.run()
21 changes: 21 additions & 0 deletions content/FLASHIda/FLASHIdaSimulatorWorkflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import streamlit as st

from src.Workflow import IdaSimulatorWorkflow
from src.common.common import page_setup


params = page_setup()

wf = IdaSimulatorWorkflow()

st.title('FLASHIda - Intelligent Data Acquisition')

t = st.tabs(["📁 **File Upload**", "⚙️ **Configure**", "🚀 **Run**"])
with t[0]:
wf.show_file_upload_section()

with t[1]:
wf.show_parameter_section()

with t[2]:
wf.show_execution_section()
126 changes: 126 additions & 0 deletions content/FLASHIda/FLASHIdaViewer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import streamlit as st

from pathlib import Path

from src.common.common import page_setup, save_params
from src.workflow.FileManager import FileManager
from src.render.render import render_grid

DEFAULT_LAYOUT = [['ms1_deconv_heat_map']]

def select_experiment():
st.session_state.selected_experiment0_ida = st.session_state.selected_experiment_dropdown_ida
print(st.session_state.selected_experiment0_ida)
if len(layout) > 1:
for exp_index in range(1, len(layout)):
if st.session_state[f'selected_experiment_dropdown_{exp_index}_ida'] is None:
continue
st.session_state[f"selected_experiment{exp_index}_ida"] = st.session_state[f'selected_experiment_dropdown_{exp_index}_ida']

Comment on lines +11 to +25
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix global variable dependencies in function.

The select_experiment function references layout and other variables from the global scope, which makes it non-reusable and harder to test.

-def select_experiment():
+def select_experiment(layout):
     st.session_state.selected_experiment0_ida = st.session_state.selected_experiment_dropdown_ida
-    print(st.session_state.selected_experiment0_ida)
     if len(layout) > 1:
         for exp_index in range(1, len(layout)):
             if st.session_state[f'selected_experiment_dropdown_{exp_index}_ida'] is None:
                 continue
             st.session_state[f"selected_experiment{exp_index}_ida"] = st.session_state[f'selected_experiment_dropdown_{exp_index}_ida']
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def select_experiment():
st.session_state.selected_experiment0_ida = st.session_state.selected_experiment_dropdown_ida
print(st.session_state.selected_experiment0_ida)
if len(layout) > 1:
for exp_index in range(1, len(layout)):
if st.session_state[f'selected_experiment_dropdown_{exp_index}_ida'] is None:
continue
st.session_state[f"selected_experiment{exp_index}_ida"] = st.session_state[f'selected_experiment_dropdown_{exp_index}_ida']
def select_experiment(layout):
st.session_state.selected_experiment0_ida = st.session_state.selected_experiment_dropdown_ida
if len(layout) > 1:
for exp_index in range(1, len(layout)):
if st.session_state[f'selected_experiment_dropdown_{exp_index}_ida'] is None:
continue
st.session_state[f"selected_experiment{exp_index}_ida"] = st.session_state[f'selected_experiment_dropdown_{exp_index}_ida']
🤖 Prompt for AI Agents
In content/FLASHIda/FLASHIdaViewer.py around lines 11 to 19, the function
select_experiment uses the global variable layout and session_state keys
directly, making it dependent on external state. Refactor the function to accept
layout and session_state as parameters instead of accessing them globally.
Update all references inside the function to use these parameters, which will
improve reusability and testability by removing hidden dependencies.

def validate_selected_index(file_manager, selected_experiment):
results = file_manager.get_results_list(['simulation_dfs'])
if selected_experiment in st.session_state:
if st.session_state[selected_experiment] in results:
return name_to_index[st.session_state[selected_experiment]]
else:
del st.session_state[selected_experiment]
return None
Comment on lines +20 to +35
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix global variable dependency in validation function.

The validate_selected_index function references name_to_index from the global scope, which makes it non-reusable.

-def validate_selected_index(file_manager, selected_experiment):
+def validate_selected_index(file_manager, selected_experiment, name_to_index):
     results = file_manager.get_results_list(['simulation_dfs'])
     if selected_experiment in st.session_state:
         if st.session_state[selected_experiment] in results:
             return name_to_index[st.session_state[selected_experiment]]
         else:
             del st.session_state[selected_experiment]
     return None
🤖 Prompt for AI Agents
In content/FLASHIda/FLASHIdaViewer.py around lines 20 to 27, the function
validate_selected_index uses the global variable name_to_index, making it
non-reusable. To fix this, add name_to_index as a parameter to the function
signature and pass it explicitly when calling the function, removing the
dependency on the global scope.


# page initialization
params = page_setup()

# Get available results
file_manager = FileManager(
st.session_state["workspace"],
Path(st.session_state['workspace'], 'flashidasimulator', 'cache')
)

results = file_manager.get_results_list(['simulation_dfs'])

if file_manager.result_exists('layout', 'layout'):
layout = file_manager.get_results('layout', 'layout')['layout']
side_by_side = layout['side_by_side']
layout = layout['layout']

else:
layout = [DEFAULT_LAYOUT]
side_by_side = False

### if no input file is given, show blank page
if len(results) == 0:
st.error('No results to show yet. Please run a workflow first!')
st.stop()

# Map names to index
name_to_index = {n : i for i, n in enumerate(results)}

if len(layout) == 2 and side_by_side:
c1, c2 = st.columns(2)
with c1:
st.selectbox(
"choose experiment", results,
key="selected_experiment_dropdown_ida",
index=validate_selected_index(file_manager, 'selected_experiment0_ida'),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Update function calls to pass required parameters.

Since the helper functions now need additional parameters, update the function calls accordingly.

-            index=validate_selected_index(file_manager, 'selected_experiment0_ida'),
-            on_change=select_experiment
+            index=validate_selected_index(file_manager, 'selected_experiment0_ida', name_to_index),
+            on_change=lambda: select_experiment(layout)

Apply similar changes to other function calls.

Also applies to: 75-75, 91-91, 114-114

🤖 Prompt for AI Agents
In content/FLASHIda/FLASHIdaViewer.py at lines 63, 75, 91, and 114, the function
calls to helper functions like validate_selected_index need to be updated to
include the new required parameters. Review the function definitions to identify
all required parameters and modify each call to pass these parameters
accordingly, ensuring all calls match the updated function signatures.

on_change=select_experiment
)
if 'selected_experiment0_ida' in st.session_state:
render_grid(
st.session_state.selected_experiment0_ida, layout[0], file_manager,
'flashidasimulator', "selected_experiment0_ida", 'flash_viewer_grid_0_ida'
)
with c2:
st.selectbox(
"choose experiment", results,
key=f'selected_experiment_dropdown_1_ida',
index=validate_selected_index(file_manager, 'selected_experiment1_ida'),
on_change=select_experiment
)
if f"selected_experiment1_ida" in st.session_state:
with st.spinner('Loading component...'):
render_grid(
st.session_state["selected_experiment1_ida"], layout[1],
file_manager, 'flashidasimulator', 'selected_experiment1_ida',
'flash_viewer_grid_1_ida'
)

else:
### for only single experiment on one view
st.selectbox(
"choose experiment", results,
key="selected_experiment_dropdown_ida",
index=validate_selected_index(file_manager, 'selected_experiment0_ida'),
on_change=select_experiment
)


if 'selected_experiment0_ida' in st.session_state:
print('Lets go!')
render_grid(
st.session_state.selected_experiment0_ida, layout[0], file_manager,
'flashidasimulator', 'selected_experiment0_ida'
)

### for multiple experiments on one view
if len(layout) > 1:

for exp_index, exp_layout in enumerate(layout):
if exp_index == 0: continue # skip the first experiment

st.divider() # horizontal line

st.selectbox(
"choose experiment", results,
key=f'selected_experiment_dropdown_{exp_index}_ida',
index=validate_selected_index(file_manager, f'selected_experiment{exp_index}_ida'),
on_change=select_experiment
)
# if #experiment input files are less than #layouts, all the pre-selection will be the first experiment
if f"selected_experiment{exp_index}_ida" in st.session_state:
render_grid(
st.session_state["selected_experiment%d_ida" % exp_index],
layout[exp_index], file_manager, 'flashidasimulator',
"selected_experiment%d_ida" % exp_index,
'flash_viewer_grid_%d_ida' % exp_index
)

save_params(params)
20 changes: 20 additions & 0 deletions content/FLASHIda/FLASHIdaWorkflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import streamlit as st

from src.Workflow import IdaWorkflow
from src.common.common import page_setup


params = page_setup()

wf = IdaWorkflow()

st.title('FLASHIda - Intelligent Data Acquisition')

t = st.tabs(["⚙️ **Configure**", "🚀 **Run**"])


with t[0]:
wf.show_parameter_section()

with t[1]:
wf.show_execution_section()
107 changes: 107 additions & 0 deletions scripts/flashida/write_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import json
import sys

import xml.etree.ElementTree as ET

############################
# default paramter values #
###########################
#
# Mandatory keys for each parameter
# key: a unique identifier
# value: the default value
#
# Optional keys for each parameter
# name: the name of the parameter
# hide: don't show the parameter in the parameter section (e.g. for input/output files)
# options: a list of valid options for the parameter
# min: the minimum value for the parameter (int and float)
# max: the maximum value for the parameter (int and float)
# step_size: the step size for the parameter (int and float)
# help: a description of the parameter
# widget_type: the type of widget to use for the parameter (default: auto)
# advanced: whether or not the parameter is advanced (default: False)

DEFAULTS = [
{"key": "in", "value": [], "help": "Input files for Python Script.", "hide": True},
{'key': 'TopN', 'name': 'TopN', 'value': 3},
{'key': 'Duration', 'name': 'Duration', 'value': 67},
'MS1',
{'key': 'Analyzer', 'name': 'Analyzer', 'value': 'Orbitrap'},
{'key': 'FirstMass', 'name': 'FirstMass', 'value': 400},
{'key': 'LastMass', 'name': 'LastMass', 'value': 2000},
{'key': 'OrbitrapResolution', 'name': 'OrbitrapResolution', 'value': 120000},
{'key': 'AGCTarget', 'name': 'AGCTarget', 'value': 800000},
{'key': 'MaxIT', 'name': 'MaxIT', 'value': 50},
{'key': 'Microscans', 'name': 'Microscans', 'value': 1},
{'key': 'DataType', 'name': 'DataType', 'value': 'Centroid'},
{'key': 'RFLens', 'name': 'RFLens', 'value': 30},
{'key': 'SourceCID', 'name': 'SourceCID', 'value': 0},
'MS2',
{'key': 'Analyzer', 'name': 'Analyzer', 'value': 'Orbitrap'},
{'key': 'FirstMass', 'name': 'FirstMass', 'value': 200},
{'key': 'OrbitrapResolution', 'name': 'OrbitrapResolution', 'value': 60000},
{'key': 'AGCTarget', 'name': 'AGCTarget', 'value': 500000},
{'key': 'MaxIT', 'name': 'MaxIT', 'value': 118},
{'key': 'Microscans', 'name': 'Microscans', 'value': 1},
{'key': 'DataType', 'name': 'DataType', 'value': 'Centroid'},
{'key': 'Activation', 'name': 'Activation', 'value': 'HCD'},
{'key': 'CollisionEnergy', 'name': 'CollisionEnergy', 'value': 29},
'IDA',
{'key': 'MaxMs2CountPerMs1', 'name': 'MaxMs2CountPerMs1','value': 4},
{'key': 'QScoreThreshold', 'name': 'QScoreThreshold', 'value': 0.2},
{'key': 'TQScoreThreshold', 'name': 'TQScoreThreshold', 'value': 0.99},
{'key': 'MinCharge', 'name': 'MinCharge', 'value': 4},
{'key': 'MaxCharge', 'name': 'MaxCharge', 'value': 50},
{'key': 'MinMass', 'name': 'MinMass', 'value': 500},
{'key': 'MaxMass', 'name': 'MaxMass', 'value': 50000},
{'key': 'Tolerances', 'name': 'Tolerances', 'value': [10.0, 10.0]},
{'key': 'TargetLogs', 'name': 'TargetLogs', 'value': [r'C:\Users\KyowonJeong\Desktop\FLASHIdaTmp\test1.log']},
{'key': 'RTWindow', 'name': 'RTWindow', 'value': 180},
{'key': 'TargetMode', 'name': 'TargetMode', 'value': 0},
{'key': 'UseFAIMS', 'name': 'UseFAIMS', 'value': False},
{'key': 'UseCVQScore', 'name': 'UseCVQScore', 'value': False},
{'key': 'CycleTime', 'name': 'CycleTime', 'value': 180},
{'key': 'CVValues', 'name': 'CVValues', 'value': [-10.0, -30.0, -40.0, -50.0, -60.0]},
]
Comment on lines +26 to +66
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix DEFAULTS structure and formatting issues.

There are several issues with the DEFAULTS list:

  1. Line 30 contains a string literal 'MS1' that should be a dictionary entry
  2. Missing whitespace after comma on line 52
  3. The structure mixes strings (section headers) and dictionaries inconsistently
     {"key": "in", "value": [], "help": "Input files for Python Script.", "hide": True},
     {'key': 'TopN', 'name': 'TopN', 'value': 3},
     {'key': 'Duration', 'name': 'Duration', 'value': 67},
-    'MS1',
+    'MS1',
     {'key': 'Analyzer', 'name': 'Analyzer', 'value': 'Orbitrap'},
     {'key': 'FirstMass', 'name': 'FirstMass', 'value': 400},
     {'key': 'LastMass', 'name': 'LastMass', 'value': 2000},
     {'key': 'OrbitrapResolution', 'name': 'OrbitrapResolution', 'value': 120000},
     {'key': 'AGCTarget', 'name': 'AGCTarget', 'value': 800000},
     {'key': 'MaxIT', 'name': 'MaxIT', 'value': 50},
     {'key': 'Microscans', 'name': 'Microscans', 'value': 1},
     {'key': 'DataType', 'name': 'DataType', 'value': 'Centroid'},
     {'key': 'RFLens', 'name': 'RFLens', 'value': 30},
     {'key': 'SourceCID', 'name': 'SourceCID', 'value': 0},
     'MS2',
     {'key': 'Analyzer', 'name': 'Analyzer', 'value': 'Orbitrap'},
     {'key': 'FirstMass', 'name': 'FirstMass', 'value': 200},
     {'key': 'OrbitrapResolution', 'name': 'OrbitrapResolution', 'value': 60000},
     {'key': 'AGCTarget', 'name': 'AGCTarget', 'value': 500000},
     {'key': 'MaxIT', 'name': 'MaxIT', 'value': 118},
     {'key': 'Microscans', 'name': 'Microscans', 'value': 1},
     {'key': 'DataType', 'name': 'DataType', 'value': 'Centroid'},
     {'key': 'Activation', 'name': 'Activation', 'value': 'HCD'},
     {'key': 'CollisionEnergy', 'name': 'CollisionEnergy', 'value': 29},
     'IDA',
-    {'key': 'MaxMs2CountPerMs1', 'name': 'MaxMs2CountPerMs1','value': 4},
+    {'key': 'MaxMs2CountPerMs1', 'name': 'MaxMs2CountPerMs1', 'value': 4},

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Flake8 (7.2.0)

[error] 52-52: missing whitespace after ','

(E231)

🤖 Prompt for AI Agents
In scripts/flashida/write_method.py between lines 26 and 66, the DEFAULTS list
improperly mixes string literals like 'MS1' as section headers with dictionary
entries, causing inconsistent structure. Replace these string literals with
dictionary entries that clearly mark sections, for example using a key like
'section' or similar. Also, fix the missing whitespace after the comma on line
52 to maintain proper formatting and readability. Ensure the entire DEFAULTS
list consistently uses dictionaries for all entries.


def get_params():
if len(sys.argv) > 1:
with open(sys.argv[1], "r") as f:
return json.load(f)
else:
return {}

Comment on lines +68 to +74
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add proper function spacing and improve function design.

The function lacks proper spacing and could be more robust.

+

 def get_params():
     if len(sys.argv) > 1:
         with open(sys.argv[1], "r") as f:
             return json.load(f)
     else:
         return {}

+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def get_params():
if len(sys.argv) > 1:
with open(sys.argv[1], "r") as f:
return json.load(f)
else:
return {}
def get_params():
if len(sys.argv) > 1:
with open(sys.argv[1], "r") as f:
return json.load(f)
else:
return {}
🧰 Tools
🪛 Flake8 (7.2.0)

[error] 68-68: expected 2 blank lines, found 1

(E302)

🤖 Prompt for AI Agents
In scripts/flashida/write_method.py around lines 68 to 74, the get_params
function lacks proper spacing and could be improved for robustness. Add a blank
line before the function definition for proper spacing. Enhance the function by
adding error handling for file operations and JSON loading to prevent crashes if
the file is missing or contains invalid JSON. Also, consider validating the
input argument count more explicitly.

if __name__ == "__main__":
params = get_params()

input_xml = params.pop('input_xml')

# Create method.xml
root = ET.Element("MethodParameters")
subsections = {}
for key, value in params.items():
if ':' in key:
section, param = key.split(':')
if section not in subsections:
subsections[section] = ET.SubElement(root, section)
section = subsections[section]
tag = ET.SubElement(section, param)
else:
tag = ET.SubElement(root, key)
# Handle list inputs
if key in ['IDA:Tolerances', 'IDA:CVValues']:
for item in value.split('\n'):
element = ET.SubElement(tag, 'double')
element.text = item.strip()
elif key in ['IDA:TargetLogs']:
for item in value.split('\n'):
element = ET.SubElement(tag, 'string')
element.text = item.strip().replace('\\\\', '\\')
elif isinstance(value, bool):
tag.text = str(value).lower()
else:
tag.text = str(value)
tree = ET.ElementTree(root)
ET.indent(tree, space=" ")
tree.write(input_xml, encoding="utf-8", xml_declaration=True)
Comment on lines +75 to +107
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add proper spacing and improve error handling.

The main execution block needs better spacing and error handling for missing keys.

+
 if __name__ == "__main__":
     params = get_params()

-    input_xml = params.pop('input_xml')
+    if 'input_xml' not in params:
+        raise ValueError("Missing required 'input_xml' parameter")
+    input_xml = params.pop('input_xml')

     # Create method.xml
     root = ET.Element("MethodParameters")
     subsections = {}
     for key, value in params.items():
         if ':' in key:
             section, param = key.split(':')
             if section not in subsections:
                 subsections[section] = ET.SubElement(root, section)
             section = subsections[section]
             tag = ET.SubElement(section, param)
         else:
             tag = ET.SubElement(root, key)
         # Handle list inputs
         if key in ['IDA:Tolerances', 'IDA:CVValues']:
             for item in value.split('\n'):
                 element = ET.SubElement(tag, 'double')
                 element.text = item.strip()
         elif key in ['IDA:TargetLogs']:
             for item in value.split('\n'):
                 element = ET.SubElement(tag, 'string')
                 element.text = item.strip().replace('\\\\', '\\')
         else:
             tag.text = str(value)
     tree = ET.ElementTree(root)
     ET.indent(tree, space="  ")
     tree.write(input_xml, encoding="utf-8", xml_declaration=True)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if __name__ == "__main__":
params = get_params()
input_xml = params.pop('input_xml')
# Create method.xml
root = ET.Element("MethodParameters")
subsections = {}
for key, value in params.items():
if ':' in key:
section, param = key.split(':')
if section not in subsections:
subsections[section] = ET.SubElement(root, section)
section = subsections[section]
tag = ET.SubElement(section, param)
else:
tag = ET.SubElement(root, key)
# Handle list inputs
if key in ['IDA:Tolerances', 'IDA:CVValues']:
for item in value.split('\n'):
element = ET.SubElement(tag, 'double')
element.text = item.strip()
elif key in ['IDA:TargetLogs']:
for item in value.split('\n'):
element = ET.SubElement(tag, 'string')
element.text = item.strip().replace('\\\\', '\\')
else:
tag.text = str(value)
tree = ET.ElementTree(root)
ET.indent(tree, space=" ")
tree.write(input_xml, encoding="utf-8", xml_declaration=True)
if __name__ == "__main__":
params = get_params()
if 'input_xml' not in params:
raise ValueError("Missing required 'input_xml' parameter")
input_xml = params.pop('input_xml')
# Create method.xml
root = ET.Element("MethodParameters")
subsections = {}
for key, value in params.items():
if ':' in key:
section, param = key.split(':')
if section not in subsections:
subsections[section] = ET.SubElement(root, section)
section = subsections[section]
tag = ET.SubElement(section, param)
else:
tag = ET.SubElement(root, key)
# Handle list inputs
if key in ['IDA:Tolerances', 'IDA:CVValues']:
for item in value.split('\n'):
element = ET.SubElement(tag, 'double')
element.text = item.strip()
elif key in ['IDA:TargetLogs']:
for item in value.split('\n'):
element = ET.SubElement(tag, 'string')
element.text = item.strip().replace('\\\\', '\\')
else:
tag.text = str(value)
tree = ET.ElementTree(root)
ET.indent(tree, space=" ")
tree.write(input_xml, encoding="utf-8", xml_declaration=True)
🧰 Tools
🪛 Flake8 (7.2.0)

[error] 75-75: expected 2 blank lines after class or function definition, found 1

(E305)

🤖 Prompt for AI Agents
In scripts/flashida/write_method.py around lines 75 to 105, improve the main
execution block by adding proper blank lines for readability and include error
handling for missing keys in the params dictionary, especially for 'input_xml'.
Wrap the key access in a try-except block to catch KeyError and provide a clear
error message or fallback behavior. Also, ensure consistent spacing between
logical code sections to enhance clarity.

1 change: 1 addition & 0 deletions settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
}
},
"online_deployment": false,
"enable_flashida": true,
"enable_workspaces": true,
"test": true,
"workspaces_dir": ".."
Expand Down
Loading
Loading