Skip to content

Commit

Permalink
new options for mz calculator
Browse files Browse the repository at this point in the history
- always add adduct info to metabolite name
- add two metabolite entries: with protons only and with additional adducts
  • Loading branch information
axelwalter committed Dec 29, 2023
1 parent 6e32724 commit 8440fc3
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 17 deletions.
23 changes: 16 additions & 7 deletions pages/2_📟_Mass_to_Charge_Calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,22 @@
help="Will be created automatically if omitted.")
neutral_loss = c1.text_input(
"neutral losses (optional)", "", help="Sum formula of neutral losses (e.g. H2O).")
add_adduct_info = c1.checkbox("add adduct info to name", True, help="Always add adduct information to metabolite name separated by `#` if a custom name was chosen.")
charge = c2.number_input(
"**charge**", -50, 50, 1, help="Enter charge. Negative numbers for negative ion mode, positive numbers for positive ion mode.")
c2.markdown("adducts", help="Specify adducts except for protons (H) up the number of charges in total, the remaing will be filled with protons (positive mode). In negative mode as the absolute charge number of protons will be removed regardless of specified additional adducts.")
c2.markdown("addtional adducts", help="Specify adducts except for protons (H) up the number of charges in total, the remaing will be filled with protons (positive mode). In negative mode as the absolute charge number of protons will be removed regardless of specified additional adducts.")
adducts = c2.data_editor(pd.DataFrame({"adduct": ["Na", "K", "HCOOH"], "number": [0, 0, 0]}), hide_index=True, use_container_width=True)
add_both_adducts = c2.checkbox("add two entries: protons only **and** with additional adducts", False, help="Add to entries to table. One contains only addition or loss of protons, the other considers the additional adduct table. Useful to include e.g. always the sodium adduct as well: `metabolite#[M+H]+` and `metabolite#[M+Na]+`.")
create_compound_button = st.form_submit_button(
"Add new metabolite", use_container_width=True,
help="Calculate m/z from sum formula and adduct and add metabolite to table.")
if create_compound_button:
save_df(create_compound(
formula, charge, adducts, neutral_loss, name),
input_table_path)
if add_both_adducts and adducts["number"].sum() > 0:
save_df(pd.concat([create_compound(formula, charge, pd.DataFrame({"adduct": [], "number": []}), "", name, True),
create_compound(formula, charge, adducts, neutral_loss, name, True)]),
input_table_path)
else:
save_df(create_compound(formula, charge, adducts, neutral_loss, name, add_adduct_info), input_table_path)

with tabs[1]:
with st.form("build-metabolite-form"):
Expand Down Expand Up @@ -73,14 +78,16 @@
name = c1.text_input("metabolite name (optional)", "",
help="Will be created automatically if omitted.")
elimination = c1.text_input("elimination product (optional)", "H2O", help="Remove elemination product when combining two metabolites.")
c2.markdown("adducts", help="Specify adducts except for protons (H) up the number of charges in total, the remaing will be filled with protons (positive mode). In negative mode as the absolute charge number of protons will be removed regardless of specified additional adducts.")
add_adduct_info = c1.checkbox("add adduct info to name", True, help="Always add adduct information to metabolite name separated by `#` if a custom name was chosen.")
c2.markdown("additional adducts", help="Specify adducts except for protons (H) up the number of charges in total, the remaing will be filled with protons (positive mode). In negative mode as the absolute charge number of protons will be removed regardless of specified additional adducts.")
adducts = c2.data_editor(pd.DataFrame({"adduct": ["Na", "K", "HCOOH"], "number": [0, 0, 0]}), hide_index=True, use_container_width=True)
add_both_adducts = c2.checkbox("add two entries: protons only **and** with additional adducts", False, help="Add to entries to table. One contains only addition or loss of protons, the other considers the additional adduct table. Useful to include e.g. always the sodium adduct as well: `metabolite#[M+H]+` and `metabolite#[M+Na]+`.")
build_compound_button = st.form_submit_button(
"Calculate metabolite", use_container_width=True,
help="Calculate m/z from sum formula and adduct and add metabolite to table.")

if build_compound_button:
save_df(build_compound(builder, charge, adducts, name, pd.read_csv(input_table_path), elimination), input_table_path)
save_df(build_compound(builder, charge, adducts, name, pd.read_csv(input_table_path), elimination, add_adduct_info, add_both_adducts), input_table_path)

with tabs[2]:
# Create file uploader
Expand All @@ -96,6 +103,7 @@
if st.button("Replace current table with uploaded table (will delete current data).", type="primary", use_container_width=True):
# Save the table (customize the path as needed)
df.to_csv(input_table_path, index=False)
st.session_state["mz_calc_success"] = [f"Uploaded table **{uploaded_file.name}**"]
st.rerun()
else:
st.error("The uploaded file does not match the required format or data types.")
Expand All @@ -104,7 +112,8 @@
st.error(f"An error occurred: {e}")

if "mz_calc_success" in st.session_state:
st.success(st.session_state["mz_calc_success"])
for message in st.session_state["mz_calc_success"]:
st.success(message)
if "mz_calc_error" in st.session_state:
st.error(st.session_state["mz_calc_error"])

Expand Down
2 changes: 1 addition & 1 deletion pages/3_🔍_Extracted_Ion_Chromatograms.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
df_path = Path(st.session_state.workspace, "mzML-files.tsv")

if not df_path.exists():
st.warning("Upload/select some mzML files first!")
mzML_files = None
else:
df = pd.read_csv(df_path, sep="\t")

Expand Down
2 changes: 1 addition & 1 deletion pages/4_🧪_Untargeted_Metabolomics.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
df_path = Path(st.session_state.workspace, "mzML-files.tsv")

if not df_path.exists():
st.warning("Upload/select some mzML files first!")
mzML_files = []
else:
df = pd.read_csv(df_path, sep="\t")

Expand Down
20 changes: 12 additions & 8 deletions src/masscalculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def get_mass(formula, adduct):
except:
return

def create_compound(formula, charge, adducts, neutral_loss, name):
def create_compound(formula, charge, adducts, neutral_loss, name, add_adduct_info):
if not formula:
st.session_state["mz_calc_error"] = "Enter sum formula for new metabolite."
return pd.DataFrame()
Expand Down Expand Up @@ -279,10 +279,10 @@ def create_compound(formula, charge, adducts, neutral_loss, name):
else:
adduct_string = f"[M{adduct_notation}]{charge_sign}"
# determine a name
if name:
compound_name = name
else:
compound_name = f"{formula}#{adduct_string}"
# Determine compound name
compound_name = name if name else f"{formula}#{adduct_string}"
if name and add_adduct_info:
compound_name += f"#{adduct_string}"
# determine m/z
mz = compound.calc_mass()

Expand All @@ -308,7 +308,7 @@ def can_eliminate(compound_one, compound_two, elimination_formula):

return True

def build_compound(builder, charge, adducts, name, df, elimination):
def build_compound(builder, charge, adducts, name, df, elimination, add_adduct_info, add_both_adducts):
# check elimination
if not Compound(elimination).check_formula():
st.session_state["mz_calc_error"] = "Elimination product has invalid formula."
Expand Down Expand Up @@ -346,7 +346,11 @@ def build_compound(builder, charge, adducts, name, df, elimination):

if not name:
name = "+".join([f"{int(entry['number'])}({entry['metabolite']})" for _, entry in builder.iterrows()]).replace("+-", "-")
return create_compound(compound.formula, charge, adducts, "", name)

if add_both_adducts and adducts["number"].sum() > 0:
return pd.concat([create_compound(compound.formula, charge, pd.DataFrame({"adduct": [], "number": []}), "", name, True),
create_compound(compound.formula, charge, adducts, "", name, True)])
return create_compound(compound.formula, charge, adducts, "", name, add_adduct_info)


def save_df(new_compound_df, input_table_path):
Expand All @@ -358,7 +362,7 @@ def save_df(new_compound_df, input_table_path):
del st.session_state["mz_calc_success"]
st.rerun()
pd.concat([new_compound_df, df]).to_csv(input_table_path, index=False)
st.session_state["mz_calc_success"] = f"**{new_compound_df['name'][0]}** with adducts **{new_compound_df['adduct'][0]}** and m/z **{new_compound_df['mz'][0]}**"
st.session_state["mz_calc_success"] = [f"**{row['name']}** with adducts **{row['adduct']}** and m/z **{row['mz']}**" for _, row in new_compound_df.iterrows()]
if "mz_calc_error" in st.session_state:
del st.session_state["mz_calc_error"]
st.rerun()
Expand Down

0 comments on commit 8440fc3

Please sign in to comment.