Skip to content

Minor changes#106

Merged
ypriverol merged 9 commits into
masterfrom
dev
Sep 25, 2025
Merged

Minor changes#106
ypriverol merged 9 commits into
masterfrom
dev

Conversation

@ypriverol

@ypriverol ypriverol commented Sep 25, 2025

Copy link
Copy Markdown
Member

PR Type

Bug fix, Enhancement, Documentation


Description

  • Add filtering for missing SDRF files with warning

  • Expand label-free quantification detection to include "lfq"

  • Update README with corrected commands and citation

  • Improve error handling for reference files


Diagram Walkthrough

flowchart LR
  A["Input Data"] --> B["Filter Missing SDRF Files"]
  B --> C["Detect LFQ Labels"]
  C --> D["Apply Peptide Filtering"]
  D --> E["Generate Output"]
Loading

File Walkthrough

Relevant files
Bug fix
peptide_normalization.py
Add SDRF file filtering with warnings                                       

ibaqpy/ibaq/peptide_normalization.py

  • Add filtering for reference files not found in SDRF
  • Log warning for missing files before dropping them
  • Improve data quality by handling NA values in Run column
+12/-0   
Enhancement
quantification_type.py
Enhance label-free quantification detection                           

ibaqpy/model/quantification_type.py

  • Expand label-free detection to include "lfq" keyword
  • Update error message to mention both "label free" and "lfq"
  • Improve quantification scheme classification robustness
+4/-2     
Documentation
README.md
Update documentation and citation                                               

README.md

  • Fix command examples from ibaqpy to ibaqpyc
  • Update parameter descriptions for clarity
  • Replace bioRxiv citation with published journal reference
+5/-5     

Summary by CodeRabbit

  • New Features

    • Expanded LFQ detection to recognize both “lfq” and “label free,” with a clearer error message.
  • Bug Fixes

    • Peptide normalization now handles missing SDRF Run values gracefully by warning and skipping affected rows instead of failing.
  • Documentation

    • Updated commands and options in examples from ibaqpy to ibaqpyc, refreshed parameter descriptions and example file references, and replaced the citation with the latest bibliographic entry.

@coderabbitai

coderabbitai Bot commented Sep 25, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Documentation updates rename CLI references and citation details. Peptide normalization now warns and drops rows where SDRF Run is missing before calculations. Quantification type classification recognizes “lfq” in addition to “label free” for single-label inputs, with an updated error message.

Changes

Cohort / File(s) Summary of Changes
Documentation refresh
README.md
Renamed CLI examples/options from ibaqpy to ibaqpyc; adjusted parameter descriptions (e.g., parquet, sdrf); updated example file references; replaced citation block with new bibliographic entry for Ibaqpy.
Peptide normalization: missing SDRF Run handling
ibaqpy/ibaq/peptide_normalization.py
During initial filtering, if any SDRF Run values are NA: collect corresponding Reference values, log a warning listing them, and drop those rows to skip calculations. No API/signature changes.
Quantification classification: LFQ keyword expansion
ibaqpy/model/quantification_type.py
In classify(), detect LFQ when input contains “lfq” or “label free” for single-label cases; updated error message to mention “label free (or lfq)”. Other logic unchanged.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant Pipeline as PeptideNormalization
    participant SDRF as SDRF Data

    User->>Pipeline: Start normalization
    Pipeline->>SDRF: Load references/runs
    alt Any Run == NA
        Pipeline->>Pipeline: Collect References with NA Run
        Note right of Pipeline: Warn: Missing SDRF Run for listed References
        Pipeline->>SDRF: Drop rows with NA Run
    end
    Pipeline->>Pipeline: Proceed with calculations on remaining rows
    Pipeline-->>User: Normalized results
Loading
sequenceDiagram
    autonumber
    actor User
    participant QT as QuantificationType.classify
    User->>QT: classify(labels)
    alt Single label contains "lfq" or "label free"
        QT-->>User: Return LFQ classification
    else if TMT/iTRAQ patterns
        QT-->>User: Return respective classification
    else
        QT-->>User: Error: Expect label free (or lfq) or supported multiplex
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • Dev #101 — Also updates README citation content; overlaps with this PR’s documentation/citation changes.

Poem

Hop hop, docs got a shiny new name,
Warnings nibble NA runs from the game.
LFQ hears “lfq” now—what luck!
My whiskers twitch: no rows stuck.
With tidy refs and cleaner flow,
I bounce through peptides, ready to go. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The title "Minor changes" is too generic and does not convey any specific updates in the pull request, which include documentation revisions in the README and enhancements to peptide normalization and quantification type classification. It fails to summarize the main contributions and leaves reviewers unclear about the scope. A more descriptive title would improve clarity and traceability. Please revise the title to clearly reflect the key changes, for example by mentioning README documentation updates and the missing SDRF run handling addition in peptide_normalization, so that the pull request intent is immediately clear to reviewers.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Inplace Mutation

The code drops rows with NA in RUN using inplace operations on a potentially sliced DataFrame, which can trigger chained assignment pitfalls and unintended side effects; consider avoiding inplace and using .loc or reassignment for safety.

# "Run" is NA for reference files not found in the SDRF file.
if data_df[RUN].isna().any():

    missing_files = data_df.loc[
        data_df[RUN].isna(), "Reference"
    ].drop_duplicates().tolist()

    logger.warning(
        f"Reference files {missing_files} are not present in the SDRF file. Skipping calculation."
    )
    data_df.dropna(subset=[RUN], inplace=True)
Logic Robustness

The LFQ detection uses substring checks that may match unintended labels (e.g., a label containing "tmt lfq mix" would be flagged LFQ first); validate the precedence and consider stricter matching or ordering.

if len(labels) == 1 and any(
    keyword in s.lower() for s in labels for keyword in ["lfq", "label free"]
):
    label_category = cls.LFQ

elif any("tmt" in s.lower() for s in labels):
    label_category = cls.TMT

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Optimize performance and improve code style

Refactor the code to avoid calling data_df[RUN].isna() twice by storing the
boolean mask in a variable. Also, replace the discouraged inplace=True argument
with DataFrame reassignment for better practice.

ibaqpy/ibaq/peptide_normalization.py [212-221]

-if data_df[RUN].isna().any():
-
-    missing_files = data_df.loc[
-        data_df[RUN].isna(), "Reference"
-    ].drop_duplicates().tolist()
+is_na_mask = data_df[RUN].isna()
+if is_na_mask.any():
+    missing_files = (
+        data_df.loc[is_na_mask, "Reference"].drop_duplicates().tolist()
+    )
 
     logger.warning(
-        f"Reference files {missing_files} are not present in the SDRF file. Skipping calculation."
+        "Reference files %s are not present in the SDRF file. Skipping calculation.",
+        missing_files,
     )
-    data_df.dropna(subset=[RUN], inplace=True)
+    data_df = data_df.dropna(subset=[RUN])
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly identifies a minor inefficiency and a pandas best-practice violation (inplace=True), offering a cleaner, more modern, and slightly more performant implementation.

Low
Simplify inefficient label checking logic

Simplify the label checking logic by removing the redundant list comprehension.
Since labels is guaranteed to have one element, directly access it and check for
the required keywords.

ibaqpy/model/quantification_type.py [69-71]

-if len(labels) == 1 and any(
-    keyword in s.lower() for s in labels for keyword in ["lfq", "label free"]
-):
+if len(labels) == 1:
+    label_str = next(iter(labels)).lower()
+    if "lfq" in label_str or "label free" in label_str:
  • Apply / Chat
Suggestion importance[1-10]: 4

__

Why: The suggestion correctly points out that the list comprehension is unnecessarily complex given the len(labels) == 1 check, and the proposed change improves code readability and simplicity.

Low
  • More

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
ibaqpy/model/quantification_type.py (1)

69-71: Harden LFQ detection against hyphen/underscore and non-string labels

Current check misses "label-free"/"label_free" and can raise on non-strings. Normalize and string-coerce.

Apply this diff:

-        if len(labels) == 1 and any(
-            keyword in s.lower() for s in labels for keyword in ["lfq", "label free"]
-        ):
+        if len(labels) == 1 and any(
+            k in str(s).lower().replace("-", " ").replace("_", " ")
+            for s in labels
+            for k in ("lfq", "label free")
+        ):
README.md (1)

226-226: Fix markdownlint MD034 (bare URL) in citation

Switch DOI to a markdown link to satisfy linter.

Apply this diff:

-> Zheng P, Audain E, Webel H, Dai C, Klein J, Hitz MP, Sachsenberg T, Bai M, Perez-Riverol Y. Ibaqpy: A scalable Python package for baseline quantification in proteomics leveraging SDRF metadata. J Proteomics. 2025 Jun 15;317:105440. doi: https://doi.org/10.1016/j.jprot.2025.105440. Epub 2025 Apr 21. PMID: 40268243.
+> Zheng P, Audain E, Webel H, Dai C, Klein J, Hitz MP, Sachsenberg T, Bai M, Perez-Riverol Y. Ibaqpy: A scalable Python package for baseline quantification in proteomics leveraging SDRF metadata. J Proteomics. 2025 Jun 15;317:105440. doi: [10.1016/j.jprot.2025.105440](https://doi.org/10.1016/j.jprot.2025.105440). Epub 2025 Apr 21. PMID: 40268243.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d33657 and 0771474.

📒 Files selected for processing (3)
  • README.md (3 hunks)
  • ibaqpy/ibaq/peptide_normalization.py (1 hunks)
  • ibaqpy/model/quantification_type.py (2 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
README.md

226-226: Bare URL used

(MD034, no-bare-urls)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (4)
ibaqpy/model/quantification_type.py (1)

101-102: Clearer error message — LGTM

Updated message reads better and reflects LFQ synonyms.

README.md (3)

164-165: Option descriptions — LGTM

Updated help text aligns with new CLI usage.


195-195: Duplicate of CLI verification

Same concern as Line 157 regarding ibaqpyc exposure.


157-157: Packaging entry point for ibaqpyc is configured
Defined under [tool.poetry.scripts] in pyproject.toml and entry_points in recipe/meta.yaml—no changes needed.

Comment on lines +211 to +222
# "Run" is NA for reference files not found in the SDRF file.
if data_df[RUN].isna().any():

missing_files = data_df.loc[
data_df[RUN].isna(), "Reference"
].drop_duplicates().tolist()

logger.warning(
f"Reference files {missing_files} are not present in the SDRF file. Skipping calculation."
)
data_df.dropna(subset=[RUN], inplace=True)

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 | 🔴 Critical

Avoid KeyError on missing 'Reference' column; make warning robust and drop non-existent RUN rows safely

"Reference" may not exist post-renaming (parquet_map). Use a fallback to available columns (e.g., "reference_file_name", SAMPLE_ID) and include the missing count in the log. Also avoid inplace to prevent chained-assignment pitfalls.

Apply this diff:

-    # "Run" is NA for reference files not found in the SDRF file.
-    if data_df[RUN].isna().any():
-
-        missing_files = data_df.loc[
-            data_df[RUN].isna(), "Reference"
-        ].drop_duplicates().tolist()
-
-        logger.warning(
-            f"Reference files {missing_files} are not present in the SDRF file. Skipping calculation."
-        )
-        data_df.dropna(subset=[RUN], inplace=True)
+    # "Run" is NA for reference files not found in the SDRF file.
+    if data_df[RUN].isna().any():
+        n_missing = int(data_df[RUN].isna().sum())
+        ref_col = next(
+            (c for c in ("Reference", "reference_file_name", SAMPLE_ID) if c in data_df.columns),
+            None,
+        )
+        missing_files = []
+        if ref_col:
+            missing_files = (
+                data_df.loc[data_df[RUN].isna(), ref_col].dropna().drop_duplicates().tolist()
+            )
+            logger.warning(
+                f"{n_missing} rows have NA Run; {ref_col} values {missing_files} are not present in the SDRF. Skipping calculation for them."
+            )
+        else:
+            logger.warning(
+                f"{n_missing} rows have NA Run but no reference column found among "
+                f"('Reference', 'reference_file_name', '{SAMPLE_ID}'). Dropping those rows."
+            )
+        data_df = data_df.dropna(subset=[RUN])
📝 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
# "Run" is NA for reference files not found in the SDRF file.
if data_df[RUN].isna().any():
missing_files = data_df.loc[
data_df[RUN].isna(), "Reference"
].drop_duplicates().tolist()
logger.warning(
f"Reference files {missing_files} are not present in the SDRF file. Skipping calculation."
)
data_df.dropna(subset=[RUN], inplace=True)
# "Run" is NA for reference files not found in the SDRF file.
if data_df[RUN].isna().any():
n_missing = int(data_df[RUN].isna().sum())
ref_col = next(
(c for c in ("Reference", "reference_file_name", SAMPLE_ID) if c in data_df.columns),
None,
)
missing_files = []
if ref_col:
missing_files = (
data_df.loc[data_df[RUN].isna(), ref_col]
.dropna()
.drop_duplicates()
.tolist()
)
logger.warning(
f"{n_missing} rows have NA Run; {ref_col} values {missing_files} are not present in the SDRF. "
"Skipping calculation for them."
)
else:
logger.warning(
f"{n_missing} rows have NA Run but no reference column found among "
f"('Reference', 'reference_file_name', '{SAMPLE_ID}'). Dropping those rows."
)
data_df = data_df.dropna(subset=[RUN])
🤖 Prompt for AI Agents
In ibaqpy/ibaq/peptide_normalization.py around lines 211-222, the code assumes a
"Reference" column exists and uses inplace drop, which can raise KeyError or
cause chained-assignment issues; update it to first detect an available
identifier column by checking for "Reference", then "reference_file_name", then
"SAMPLE_ID" (use the first that exists), build a list of missing identifiers and
count (handle case where none of these columns exist by using indices or an
empty list), log a warning that includes the missing count and the identifier
list, and avoid inplace operations by assigning the result of
dropna(subset=[RUN]) back to data_df (e.g., data_df =
data_df.dropna(subset=[RUN])).

@ypriverol ypriverol merged commit 5421716 into master Sep 25, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants