diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b1178e5..a3ca57f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. +## [Unreleased] + +### 🚀 Features + +- Add unified `pyprophet export feature-scores` command that works with all file formats (OSW, Parquet, Split Parquet) + - Auto-detects SCORE tables and adjusts behavior intelligently + - Applies RANK==1 filtering when SCORE tables exist + - Plots only VAR_ columns for unscored files + - Supports MS1, MS2, and transition level features + +### 🔧 Deprecated + +- Deprecate `pyprophet export score-plots` command in favor of `pyprophet export feature-scores` + - Old command still works with deprecation warning for backward compatibility + ## [3.0.4] - 2025-10-21 ### 🚀 Features diff --git a/docs/cli.rst b/docs/cli.rst index 85453d89..a2ff1a1c 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -144,10 +144,27 @@ To convert OpenSwath's *.osw* / *.sqMass* format to a parquet format, you can us :prog: pyprophet export parquet :nested: none -Export Score Plots -^^^^^^^^^^^^^^^^^^ +Export Feature Score Plots +^^^^^^^^^^^^^^^^^^^^^^^^^^^ -It may be useful to export the distribution of scores for the different input features. This can help you investigate the distribution and quality of scores for target-decoy separation. +To export the distribution of feature scores (VAR_ columns) and, if available, scorer scores (SCORE columns), you can use the :program:`export feature-scores` subcommand. This command works with all file formats (OSW, Parquet, and Split Parquet): + +- **For unscored files**: Plots only VAR_ columns (feature variables) +- **For scored files**: Applies RANK==1 filtering and plots both SCORE and VAR_ columns + +This is useful for investigating the distribution and quality of scores for target-decoy separation. + +.. click:: pyprophet.cli.export:export_feature_scores + :prog: pyprophet export feature-scores + :nested: none + +Export Score Plots (Deprecated) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. deprecated:: 3.1 + Use :program:`pyprophet export feature-scores` instead. + +The :program:`export score-plots` command is deprecated and will be removed in a future version. It has been replaced by the more flexible :program:`export feature-scores` command which works with all file formats. .. click:: pyprophet.cli.export:export_score_plots :prog: pyprophet export score-plots diff --git a/pyprophet/cli/export.py b/pyprophet/cli/export.py index 50371fc3..2dde75c3 100644 --- a/pyprophet/cli/export.py +++ b/pyprophet/cli/export.py @@ -14,6 +14,9 @@ from ..export.export_report import ( export_scored_report as _export_scored_report, ) +from ..export.export_report import ( + export_feature_scores as _export_feature_scores, +) from ..export.calibration_report import generate_report as generate_calibration_report from ..glyco.export import ( export_score_plots as export_glyco_score_plots, @@ -43,8 +46,10 @@ def export(): export.add_command(export_parquet, name="parquet") export.add_command(export_compound, name="compound") export.add_command(export_glyco, name="glyco") - export.add_command(export_score_plots, name="score-plots") + export.add_command(export_feature_scores, name="feature-scores") + export.add_command(export_score_plots, name="score-plots") # Deprecated export.add_command(export_scored_report, name="score-report") + export.add_command(export_feature_scores, name="feature-scores") export.add_command(export_calibration_report, name="calibration-report") return export @@ -829,7 +834,35 @@ def export_glyco( ) -# Export score plots +# Export feature scores (unified command) +@click.command(name="feature-scores", cls=AdvancedHelpCommand) +@click.option( + "--in", + "infile", + required=True, + type=click.Path(exists=True), + help="PyProphet input file (OSW, Parquet, or Split Parquet directory).", +) +@click.option( + "--out", + "outfile", + type=click.Path(exists=False), + help="Output PDF file path. If not specified, will be derived from input filename.", +) +@measure_memory_usage_and_time +def export_feature_scores(infile, outfile): + """ + Export feature score plots + + Works with OSW, Parquet, and Split Parquet formats. + - If SCORE tables exist: applies RANK==1 filtering and plots SCORE + VAR_ columns + - If SCORE tables don't exist: plots only VAR_ columns + """ + from ..export.export_report import export_feature_scores as _export_feature_scores + _export_feature_scores(infile, outfile) + + +# Export score plots (deprecated - use feature-scores instead) @click.command(name="score-plots", cls=AdvancedHelpCommand) @click.option( "--in", @@ -849,8 +882,11 @@ def export_glyco( @measure_memory_usage_and_time def export_score_plots(infile, glycoform): """ - Export score plots + Export score plots (DEPRECATED - use 'feature-scores' instead) + + This command is deprecated. Please use 'pyprophet export feature-scores' instead. """ + logger.warning("DEPRECATED: 'pyprophet export score-plots' is deprecated. Use 'pyprophet export feature-scores' instead.") if infile.endswith(".osw"): if not glycoform: _export_score_plots(infile) @@ -880,6 +916,33 @@ def export_scored_report(infile): _export_scored_report(infile, outfile) +# Export feature scores +@click.command(name="feature-scores", cls=AdvancedHelpCommand) +@click.option( + "--in", + "infile", + required=True, + type=click.Path(exists=True), + help="PyProphet input file (OSW, Parquet, or Split Parquet directory).", +) +@click.option( + "--out", + "outfile", + type=click.Path(exists=False), + help="Output PDF file. If not provided, will be auto-generated based on input filename.", +) +@measure_memory_usage_and_time +def export_feature_scores(infile, outfile): + """ + Export feature score plots from a PyProphet input file. + + Creates plots showing the distribution of feature scores (var_* columns) + at different levels (ms1, ms2, transition, alignment) colored by target/decoy status. + Works with OSW, Parquet, and Split Parquet files (scored or unscored). + """ + _export_feature_scores(infile, outfile) + + # Export OpenSwath Calibration debug plots @click.command(name="calibration-report", cls=AdvancedHelpCommand) @click.option( diff --git a/pyprophet/export/export_report.py b/pyprophet/export/export_report.py index ea5042da..4a105c6b 100644 --- a/pyprophet/export/export_report.py +++ b/pyprophet/export/export_report.py @@ -1,5 +1,8 @@ import sqlite3 import pandas as pd +import os +from pathlib import Path +from loguru import logger from .._config import ExportIOConfig @@ -7,9 +10,234 @@ from ..io.dispatcher import ReaderDispatcher from ..io.util import get_parquet_column_names from ..io.util import check_sqlite_table +from ..io.util import _ensure_pyarrow from ..report import plot_scores +def export_feature_scores(infile, outfile=None): + """ + Export feature score plots from a PyProphet input file. + + This function works with OSW, Parquet, and Split Parquet formats. + - If SCORE tables exist: applies RANK==1 filtering and plots SCORE + VAR_ columns + - If SCORE tables don't exist: plots only VAR_ columns + + Parameters + ---------- + infile : str + Path to input file (OSW, Parquet, or Split Parquet directory) + outfile : str, optional + Path for output PDF files. If None, derives from infile. + """ + # Detect file type based on extension and existence + if infile.endswith(".osw"): + file_type = "osw" + elif infile.endswith(".parquet"): + file_type = "parquet" + elif os.path.isdir(infile): + # Check if it's a split parquet directory + precursor_file = os.path.join(infile, "precursors_features.parquet") + if os.path.exists(precursor_file): + file_type = "parquet_split" + else: + raise ValueError(f"Directory {infile} does not appear to be a valid split parquet directory") + else: + raise ValueError(f"Unsupported file type for {infile}") + + logger.info(f"Detected file type: {file_type}") + + # Generate output filename if not provided + if outfile is None: + if file_type == "osw": + outfile = infile.replace(".osw", "_feature_scores.pdf") + elif file_type == "parquet": + outfile = infile.replace(".parquet", "_feature_scores.pdf") + else: # parquet_split + outfile = infile.rstrip("/") + "_feature_scores.pdf" + + logger.info(f"Output file: {outfile}") + + # Create config and reader based on file type + config = ExportIOConfig( + infile=infile, + outfile=outfile, + subsample_ratio=1.0, + level="export", + context="export_feature_scores", + ) + + # Get appropriate reader + reader = ReaderDispatcher.get_reader(config) + + # Export feature scores using the reader's method + reader.export_feature_scores(outfile, _plot_feature_scores) + + logger.info(f"Feature score plots exported to {outfile}") + + +def _plot_feature_scores(df: pd.DataFrame, outfile: str, level: str, append: bool = False, sample_size: int = 100000): + """ + Create plots for feature scores at a specific level. + + Parameters + ---------- + df : pd.DataFrame + DataFrame containing feature scores and DECOY column. + outfile : str + Path to the output PDF file. + level : str + Level name (ms1, ms2, transition, or alignment). + append : bool + If True, append to existing PDF. If False, create new PDF. + sample_size : int + Maximum number of rows to use for plotting. If df has more rows, + a stratified sample (by DECOY) will be taken to reduce memory usage. + """ + # Get all columns that contain feature scores (VAR_ or SCORE columns) + score_cols = [col for col in df.columns if ("VAR_" in col.upper() or col.upper().startswith("SCORE")) and col != "DECOY"] + + if not score_cols: + logger.warning(f"No feature score columns found for {level} level") + return + + logger.info(f"Found {len(score_cols)} feature score columns for {level} level") + + # Prepare data for plotting - ensure DECOY column exists + if "DECOY" not in df.columns: + logger.warning(f"No DECOY column found for {level} level, skipping") + return + + # Only select the columns we need for plotting + plot_df = df[score_cols + ["DECOY"]].dropna(subset=["DECOY"]).copy() + + # Check if we have any data left after dropping NAs + if len(plot_df) == 0: + logger.warning(f"No valid data rows found for {level} level after removing rows with null DECOY values") + return + + # Memory optimization: Sample data if it's too large + if len(plot_df) > sample_size: + logger.info(f"Dataset has {len(plot_df)} rows, sampling {sample_size} rows (stratified by DECOY) to reduce memory usage") + # Stratified sampling to maintain target/decoy ratio + target_df = plot_df[plot_df["DECOY"] == 0] + decoy_df = plot_df[plot_df["DECOY"] == 1] + + # Calculate sample sizes proportional to original distribution + n_targets = len(target_df) + n_decoys = len(decoy_df) + total = n_targets + n_decoys + + # Handle edge cases where one group might be empty + if total == 0: + logger.warning(f"No data with valid DECOY values for {level} level") + return + + target_sample_size = int(sample_size * n_targets / total) if n_targets > 0 else 0 + decoy_sample_size = int(sample_size * n_decoys / total) if n_decoys > 0 else 0 + + # Sample from each group + samples = [] + if n_targets > 0: + if n_targets > target_sample_size and target_sample_size > 0: + target_sample = target_df.sample(n=target_sample_size, random_state=42) + else: + target_sample = target_df + samples.append(target_sample) + + if n_decoys > 0: + if n_decoys > decoy_sample_size and decoy_sample_size > 0: + decoy_sample = decoy_df.sample(n=decoy_sample_size, random_state=42) + else: + decoy_sample = decoy_df + samples.append(decoy_sample) + + # Combine samples + plot_df = pd.concat(samples, ignore_index=True) + logger.info(f"Sampled {len(plot_df)} rows") + + # Ensure DECOY is 0 or 1 + if plot_df["DECOY"].dtype == bool: + plot_df["DECOY"] = plot_df["DECOY"].astype(int) + + # Generate a temporary output file for this level + temp_outfile = outfile.replace(".pdf", f"_{level}_temp.pdf") + + # Rename columns to match plot_scores expectations + # plot_scores expects columns named "SCORE", "MAIN_VAR_*", or "VAR_*" + rename_dict = {} + for col in score_cols: + # Ensure column names start with VAR_ or SCORE + if not col.upper().startswith("VAR_") and not col.upper().startswith("SCORE"): + # Extract the var part from column names like FEATURE_MS1_VAR_XXX + parts = col.split("VAR_") + if len(parts) > 1: + new_name = "VAR_" + parts[-1] + else: + new_name = "VAR_" + col + rename_dict[col] = new_name + + if rename_dict: + plot_df.rename(columns=rename_dict, inplace=True) + + # Call plot_scores with the formatted dataframe + plot_scores(plot_df, temp_outfile) + + # Check if the temporary file was created and has content + if not os.path.exists(temp_outfile): + logger.warning(f"plot_scores did not create output file for {level} level, skipping") + return + + if os.path.getsize(temp_outfile) == 0: + logger.warning(f"plot_scores created empty output file for {level} level, skipping") + os.remove(temp_outfile) + return + + # If appending, merge PDFs, otherwise just rename + if append and os.path.exists(outfile): + from pypdf import PdfReader, PdfWriter + + try: + # Merge the PDFs + writer = PdfWriter() + + # Add pages from existing PDF + with open(outfile, "rb") as f: + existing_pdf = PdfReader(f) + for page in existing_pdf.pages: + writer.add_page(page) + + # Add pages from new PDF + with open(temp_outfile, "rb") as f: + new_pdf = PdfReader(f) + for page in new_pdf.pages: + writer.add_page(page) + + # Write merged PDF + with open(outfile, "wb") as f: + writer.write(f) + + # Remove temporary file + os.remove(temp_outfile) + except Exception as e: + logger.warning(f"Failed to merge PDF for {level} level: {e}. Skipping this level.") + # Clean up temporary file if it exists + if os.path.exists(temp_outfile): + os.remove(temp_outfile) + return + else: + # Just rename temporary file to output file + try: + if os.path.exists(outfile): + os.remove(outfile) + os.rename(temp_outfile, outfile) + except Exception as e: + logger.warning(f"Failed to save PDF for {level} level: {e}. Skipping this level.") + # Clean up temporary file if it exists + if os.path.exists(temp_outfile): + os.remove(temp_outfile) + return + + def export_score_plots(infile): """ Export score plots from a PyProphet input file. @@ -149,3 +377,228 @@ def export_scored_report( df = reader.read() post_scoring_report(df, outfile) + + +def export_feature_scores(infile: str, outfile: str = None): + """ + Export feature score plots from a PyProphet input file. + + This function creates plots showing the distribution of feature scores + (var_* columns) at different levels (ms1, ms2, transition, alignment) + colored by target/decoy status. Works with OSW, Parquet, and Split Parquet files. + + Parameters + ---------- + infile : str + Path to the input file (OSW, Parquet, or Split Parquet format). + outfile : str, optional + Path to the output PDF file. If None, will be auto-generated based on input filename. + """ + # Detect file type based on extension and existence + if infile.endswith(".osw"): + file_type = "osw" + elif infile.endswith(".parquet"): + file_type = "parquet" + elif os.path.isdir(infile): + # Check if it's a split parquet directory + precursor_file = os.path.join(infile, "precursors_features.parquet") + if os.path.exists(precursor_file): + file_type = "parquet_split" + else: + raise ValueError(f"Directory {infile} does not appear to be a valid split parquet directory") + else: + raise ValueError(f"Unsupported file type for {infile}") + + logger.info(f"Detected file type: {file_type}") + + # Generate output filename if not provided + if outfile is None: + if file_type == "osw": + outfile = infile.replace(".osw", "_feature_scores.pdf") + elif file_type == "parquet": + outfile = infile.replace(".parquet", "_feature_scores.pdf") + else: # parquet_split + outfile = infile.rstrip("/") + "_feature_scores.pdf" + + logger.info(f"Output file: {outfile}") + + # Create config and reader based on file type + config = ExportIOConfig( + infile=infile, + outfile=outfile, + subsample_ratio=1.0, + level="export", + context="export_feature_scores", + ) + + # Get appropriate reader + reader = ReaderDispatcher.get_reader(config) + + # Export feature scores using the reader's method + reader.export_feature_scores(outfile, _plot_feature_scores) + + logger.info(f"Feature score plots exported to {outfile}") + + + +def _plot_feature_scores(df: pd.DataFrame, outfile: str, level: str, append: bool = False, sample_size: int = 100000): + """ + Create plots for feature scores at a specific level. + + Parameters + ---------- + df : pd.DataFrame + DataFrame containing feature scores and DECOY column. + outfile : str + Path to the output PDF file. + level : str + Level name (ms1, ms2, transition, or alignment). + append : bool + If True, append to existing PDF. If False, create new PDF. + sample_size : int + Maximum number of rows to use for plotting. If df has more rows, + a stratified sample (by DECOY) will be taken to reduce memory usage. + """ + # Get all columns that contain feature scores (VAR_ columns or columns with _VAR_ in name) + score_cols = [col for col in df.columns if "VAR_" in col.upper() and col != "DECOY"] + + if not score_cols: + logger.warning(f"No feature score columns found for {level} level") + return + + logger.info(f"Found {len(score_cols)} feature score columns for {level} level: {score_cols}") + + # Prepare data for plotting - ensure DECOY column exists + if "DECOY" not in df.columns: + logger.warning(f"No DECOY column found for {level} level, skipping") + return + + # Only select the columns we need for plotting + plot_df = df[score_cols + ["DECOY"]].dropna(subset=["DECOY"]).copy() + + # Check if we have any data left after dropping NAs + if len(plot_df) == 0: + logger.warning(f"No valid data rows found for {level} level after removing rows with null DECOY values") + return + + # Memory optimization: Sample data if it's too large + if len(plot_df) > sample_size: + logger.info(f"Dataset has {len(plot_df)} rows, sampling {sample_size} rows (stratified by DECOY) to reduce memory usage") + # Stratified sampling to maintain target/decoy ratio + target_df = plot_df[plot_df["DECOY"] == 0] + decoy_df = plot_df[plot_df["DECOY"] == 1] + + # Calculate sample sizes proportional to original distribution + n_targets = len(target_df) + n_decoys = len(decoy_df) + total = n_targets + n_decoys + + # Handle edge cases where one group might be empty + if total == 0: + logger.warning(f"No data with valid DECOY values for {level} level") + return + + target_sample_size = int(sample_size * n_targets / total) if n_targets > 0 else 0 + decoy_sample_size = int(sample_size * n_decoys / total) if n_decoys > 0 else 0 + + # Sample from each group + samples = [] + if n_targets > 0: + if n_targets > target_sample_size and target_sample_size > 0: + target_sample = target_df.sample(n=target_sample_size, random_state=42) + else: + target_sample = target_df + samples.append(target_sample) + + if n_decoys > 0: + if n_decoys > decoy_sample_size and decoy_sample_size > 0: + decoy_sample = decoy_df.sample(n=decoy_sample_size, random_state=42) + else: + decoy_sample = decoy_df + samples.append(decoy_sample) + + # Combine samples + plot_df = pd.concat(samples, ignore_index=True) + logger.info(f"Sampled {len(plot_df)} rows ({len(samples[0]) if len(samples) > 0 and n_targets > 0 else 0} targets, {len(samples[-1]) if len(samples) > 0 and n_decoys > 0 else 0} decoys)") + + # Ensure DECOY is 0 or 1 + if plot_df["DECOY"].dtype == bool: + plot_df["DECOY"] = plot_df["DECOY"].astype(int) + + # Generate a temporary output file for this level + temp_outfile = outfile.replace(".pdf", f"_{level}_temp.pdf") + + # Rename columns to match plot_scores expectations + # plot_scores expects columns named "SCORE", "MAIN_VAR_*", or "VAR_*" + rename_dict = {} + for i, col in enumerate(score_cols): + # Ensure column names start with VAR_ + if not col.upper().startswith("VAR_"): + # Extract the var part from column names like FEATURE_MS1_VAR_XXX + parts = col.split("VAR_") + if len(parts) > 1: + new_name = "VAR_" + parts[-1] + else: + new_name = "VAR_" + col + rename_dict[col] = new_name + + if rename_dict: + plot_df.rename(columns=rename_dict, inplace=True) + + # Call plot_scores with the formatted dataframe + plot_scores(plot_df, temp_outfile) + + # Check if the temporary file was created and has content + if not os.path.exists(temp_outfile): + logger.warning(f"plot_scores did not create output file for {level} level, skipping") + return + + if os.path.getsize(temp_outfile) == 0: + logger.warning(f"plot_scores created empty output file for {level} level, skipping") + os.remove(temp_outfile) + return + + # If appending, merge PDFs, otherwise just rename + if append and os.path.exists(outfile): + from pypdf import PdfReader, PdfWriter + + try: + # Merge the PDFs + writer = PdfWriter() + + # Add pages from existing PDF + with open(outfile, "rb") as f: + existing_pdf = PdfReader(f) + for page in existing_pdf.pages: + writer.add_page(page) + + # Add pages from new PDF + with open(temp_outfile, "rb") as f: + new_pdf = PdfReader(f) + for page in new_pdf.pages: + writer.add_page(page) + + # Write merged PDF + with open(outfile, "wb") as f: + writer.write(f) + + # Remove temporary file + os.remove(temp_outfile) + except Exception as e: + logger.warning(f"Failed to merge PDF for {level} level: {e}. Skipping this level.") + # Clean up temporary file if it exists + if os.path.exists(temp_outfile): + os.remove(temp_outfile) + return + else: + # Just rename temporary file to output file + try: + if os.path.exists(outfile): + os.remove(outfile) + os.rename(temp_outfile, outfile) + except Exception as e: + logger.warning(f"Failed to save PDF for {level} level: {e}. Skipping this level.") + # Clean up temporary file if it exists + if os.path.exists(temp_outfile): + os.remove(temp_outfile) + return diff --git a/pyprophet/io/export/osw.py b/pyprophet/io/export/osw.py index 5e015039..b25c8826 100644 --- a/pyprophet/io/export/osw.py +++ b/pyprophet/io/export/osw.py @@ -860,6 +860,238 @@ def _get_peptide_protein_score_table_sqlite(self, con, level: str) -> str: return f"{view_name} AS ({merged})" + def export_feature_scores(self, outfile: str, plot_callback): + """ + Export feature scores from OSW file for plotting. + + Detects if SCORE tables exist and adjusts behavior: + - If SCORE tables exist: applies RANK==1 filtering and plots SCORE + VAR_ columns + - If SCORE tables don't exist: plots only VAR_ columns + + Parameters + ---------- + outfile : str + Path to the output PDF file. + plot_callback : callable + Function to call for plotting each level's data. + Signature: plot_callback(df, outfile, level, append) + """ + con = sqlite3.connect(self.infile) + + try: + # Check for SCORE tables + has_score_ms1 = check_sqlite_table(con, "SCORE_MS1") + has_score_ms2 = check_sqlite_table(con, "SCORE_MS2") + has_score_transition = check_sqlite_table(con, "SCORE_TRANSITION") + + if has_score_ms1 or has_score_ms2 or has_score_transition: + logger.info("SCORE tables detected - applying RANK==1 filter and plotting SCORE + VAR_ columns") + else: + logger.info("No SCORE tables detected - plotting only VAR_ columns") + + # Process MS1 level if available + if check_sqlite_table(con, "FEATURE_MS1"): + logger.info("Processing MS1 level feature scores") + + if has_score_ms1: + # Scored mode: Include SCORE columns and apply RANK==1 filter + ms1_query = """ + SELECT *, + RUN_ID || '_' || PRECURSOR_ID AS GROUP_ID + FROM FEATURE_MS1 + INNER JOIN + (SELECT RUN_ID, + ID, + PRECURSOR_ID, + EXP_RT + FROM FEATURE) AS FEATURE ON FEATURE_MS1.FEATURE_ID = FEATURE.ID + INNER JOIN + (SELECT ID, + CHARGE AS VAR_PRECURSOR_CHARGE, + DECOY + FROM PRECURSOR) AS PRECURSOR ON FEATURE.PRECURSOR_ID = PRECURSOR.ID + INNER JOIN SCORE_MS1 ON FEATURE.ID = SCORE_MS1.FEATURE_ID + WHERE RANK == 1 + ORDER BY RUN_ID, + PRECURSOR.ID ASC, + FEATURE.EXP_RT ASC + """ + else: + # Unscored mode: Only VAR_ columns + cursor = con.cursor() + cursor.execute("PRAGMA table_info(FEATURE_MS1)") + all_cols = [row[1] for row in cursor.fetchall()] + var_cols = [col for col in all_cols if "VAR_" in col.upper()] + + if var_cols: + var_cols_sql = ", ".join([f"FEATURE_MS1.{col}" for col in var_cols]) + ms1_query = f""" + SELECT + {var_cols_sql}, + PRECURSOR.DECOY + FROM FEATURE_MS1 + INNER JOIN FEATURE ON FEATURE_MS1.FEATURE_ID = FEATURE.ID + INNER JOIN PRECURSOR ON FEATURE.PRECURSOR_ID = PRECURSOR.ID + """ + else: + logger.warning("No VAR_ columns found in FEATURE_MS1 table") + ms1_query = None + + if ms1_query: + df_ms1 = pd.read_sql_query(ms1_query, con) + if not df_ms1.empty: + plot_callback(df_ms1, outfile, "ms1", append=False) + + # Process MS2 level if available + if check_sqlite_table(con, "FEATURE_MS2"): + logger.info("Processing MS2 level feature scores") + + if has_score_ms2: + # Scored mode: Include SCORE columns and apply RANK==1 filter + ms2_query = """ + SELECT *, + RUN_ID || '_' || PRECURSOR_ID AS GROUP_ID + FROM FEATURE_MS2 + INNER JOIN + (SELECT RUN_ID, + ID, + PRECURSOR_ID, + EXP_RT + FROM FEATURE) AS FEATURE ON FEATURE_MS2.FEATURE_ID = FEATURE.ID + INNER JOIN + (SELECT ID, + CHARGE AS VAR_PRECURSOR_CHARGE, + DECOY + FROM PRECURSOR) AS PRECURSOR ON FEATURE.PRECURSOR_ID = PRECURSOR.ID + INNER JOIN + (SELECT PRECURSOR_ID AS ID, + COUNT(*) AS VAR_TRANSITION_NUM_SCORE + FROM TRANSITION_PRECURSOR_MAPPING + INNER JOIN TRANSITION ON TRANSITION_PRECURSOR_MAPPING.TRANSITION_ID = TRANSITION.ID + WHERE DETECTING==1 + GROUP BY PRECURSOR_ID) AS VAR_TRANSITION_SCORE ON FEATURE.PRECURSOR_ID = VAR_TRANSITION_SCORE.ID + INNER JOIN SCORE_MS2 ON FEATURE.ID = SCORE_MS2.FEATURE_ID + WHERE RANK == 1 + ORDER BY RUN_ID, + PRECURSOR.ID ASC, + FEATURE.EXP_RT ASC + """ + else: + # Unscored mode: Only VAR_ columns + cursor = con.cursor() + cursor.execute("PRAGMA table_info(FEATURE_MS2)") + all_cols = [row[1] for row in cursor.fetchall()] + var_cols = [col for col in all_cols if "VAR_" in col.upper()] + + if var_cols: + var_cols_sql = ", ".join([f"FEATURE_MS2.{col}" for col in var_cols]) + ms2_query = f""" + SELECT + {var_cols_sql}, + PRECURSOR.DECOY + FROM FEATURE_MS2 + INNER JOIN FEATURE ON FEATURE_MS2.FEATURE_ID = FEATURE.ID + INNER JOIN PRECURSOR ON FEATURE.PRECURSOR_ID = PRECURSOR.ID + """ + else: + logger.warning("No VAR_ columns found in FEATURE_MS2 table") + ms2_query = None + + if ms2_query: + df_ms2 = pd.read_sql_query(ms2_query, con) + if not df_ms2.empty: + append = check_sqlite_table(con, "FEATURE_MS1") + plot_callback(df_ms2, outfile, "ms2", append=append) + + # Process transition level if available + if check_sqlite_table(con, "FEATURE_TRANSITION"): + logger.info("Processing transition level feature scores") + + if has_score_transition: + # Scored mode: Include SCORE columns and apply RANK==1 filter + transition_query = """ + SELECT TRANSITION.DECOY AS DECOY, + FEATURE_TRANSITION.*, + PRECURSOR.CHARGE AS VAR_PRECURSOR_CHARGE, + TRANSITION.VAR_PRODUCT_CHARGE AS VAR_PRODUCT_CHARGE, + SCORE_TRANSITION.*, + RUN_ID || '_' || FEATURE_TRANSITION.FEATURE_ID || '_' || PRECURSOR_ID || '_' || FEATURE_TRANSITION.TRANSITION_ID AS GROUP_ID + FROM FEATURE_TRANSITION + INNER JOIN + (SELECT RUN_ID, + ID, + PRECURSOR_ID, + EXP_RT + FROM FEATURE) AS FEATURE ON FEATURE_TRANSITION.FEATURE_ID = FEATURE.ID + INNER JOIN PRECURSOR ON FEATURE.PRECURSOR_ID = PRECURSOR.ID + INNER JOIN SCORE_TRANSITION ON FEATURE_TRANSITION.FEATURE_ID = SCORE_TRANSITION.FEATURE_ID + AND FEATURE_TRANSITION.TRANSITION_ID = SCORE_TRANSITION.TRANSITION_ID + INNER JOIN + (SELECT ID, + CHARGE AS VAR_PRODUCT_CHARGE, + DECOY + FROM TRANSITION) AS TRANSITION ON FEATURE_TRANSITION.TRANSITION_ID = TRANSITION.ID + ORDER BY RUN_ID, + PRECURSOR.ID, + FEATURE.EXP_RT, + TRANSITION.ID + """ + else: + # Unscored mode: Only VAR_ columns + cursor = con.cursor() + cursor.execute("PRAGMA table_info(FEATURE_TRANSITION)") + all_cols = [row[1] for row in cursor.fetchall()] + var_cols = [col for col in all_cols if "VAR_" in col.upper()] + + if var_cols: + var_cols_sql = ", ".join([f"FEATURE_TRANSITION.{col}" for col in var_cols]) + transition_query = f""" + SELECT + {var_cols_sql}, + TRANSITION.DECOY + FROM FEATURE_TRANSITION + INNER JOIN FEATURE ON FEATURE_TRANSITION.FEATURE_ID = FEATURE.ID + INNER JOIN TRANSITION ON FEATURE_TRANSITION.TRANSITION_ID = TRANSITION.ID + """ + else: + logger.warning("No VAR_ columns found in FEATURE_TRANSITION table") + transition_query = None + + if transition_query: + df_transition = pd.read_sql_query(transition_query, con) + if not df_transition.empty: + append = check_sqlite_table(con, "FEATURE_MS1") or check_sqlite_table(con, "FEATURE_MS2") + plot_callback(df_transition, outfile, "transition", append=append) + + # Process alignment level if available (no SCORE tables for alignment) + if check_sqlite_table(con, "FEATURE_MS2_ALIGNMENT"): + logger.info("Processing alignment level feature scores") + # Get only VAR_ columns to reduce memory usage + cursor = con.cursor() + cursor.execute("PRAGMA table_info(FEATURE_MS2_ALIGNMENT)") + all_cols = [row[1] for row in cursor.fetchall()] + var_cols = [col for col in all_cols if "VAR_" in col.upper()] + + if var_cols: + var_cols_sql = ", ".join(var_cols) + alignment_query = f""" + SELECT + {var_cols_sql}, + LABEL AS DECOY + FROM FEATURE_MS2_ALIGNMENT + """ + df_alignment = pd.read_sql_query(alignment_query, con) + if not df_alignment.empty: + append = (check_sqlite_table(con, "FEATURE_MS1") or + check_sqlite_table(con, "FEATURE_MS2") or + check_sqlite_table(con, "FEATURE_TRANSITION")) + plot_callback(df_alignment, outfile, "alignment", append=append) + else: + logger.warning("No VAR_ columns found in FEATURE_MS2_ALIGNMENT table") + + finally: + con.close() + class OSWWriter(BaseOSWWriter): """ diff --git a/pyprophet/io/export/parquet.py b/pyprophet/io/export/parquet.py index f9cc2e19..3bcd8872 100644 --- a/pyprophet/io/export/parquet.py +++ b/pyprophet/io/export/parquet.py @@ -4,7 +4,7 @@ from ..._config import ExportIOConfig from .._base import BaseParquetReader, BaseParquetWriter -from ..util import get_parquet_column_names +from ..util import get_parquet_column_names, _ensure_pyarrow class ParquetReader(BaseParquetReader): @@ -601,6 +601,135 @@ def _read_for_export_scored_report(self, con) -> pd.DataFrame: return df + def export_feature_scores(self, outfile: str, plot_callback): + """ + Export feature scores from Parquet file for plotting. + + Detects if SCORE columns exist and adjusts behavior: + - If SCORE columns exist: applies RANK==1 filtering and plots SCORE + VAR_ columns + - If SCORE columns don't exist: plots only VAR_ columns + + Parameters + ---------- + outfile : str + Path to the output PDF file. + plot_callback : callable + Function to call for plotting each level's data. + Signature: plot_callback(df, outfile, level, append) + """ + logger.info(f"Reading parquet file: {self.infile}") + # Ensure pyarrow is available + pa, _, _ = _ensure_pyarrow() + + # First, read only column names to identify what to load + parquet_file = pa.parquet.ParquetFile(self.infile) + all_columns = parquet_file.schema.names + + # Check for SCORE columns + score_cols = [col for col in all_columns if col.startswith("SCORE_")] + has_scores = len(score_cols) > 0 + + if has_scores: + logger.info("SCORE columns detected - applying RANK==1 filter and plotting SCORE + VAR_ columns") + else: + logger.info("No SCORE columns detected - plotting only VAR_ columns") + + # Identify columns to read for each level + ms1_cols = [col for col in all_columns if col.startswith("FEATURE_MS1_VAR_")] + ms2_cols = [col for col in all_columns if col.startswith("FEATURE_MS2_VAR_")] + transition_cols = [col for col in all_columns if col.startswith("FEATURE_TRANSITION_VAR_")] + + # Determine which columns to read (only what we need) + cols_to_read = set() + + # Add SCORE columns if they exist + if has_scores: + cols_to_read.update(score_cols) + # Add RANK column for filtering + if "SCORE_MS2_PEAK_GROUP_RANK" in all_columns: + cols_to_read.add("SCORE_MS2_PEAK_GROUP_RANK") + # Add ID columns for grouping + if "RUN_ID" in all_columns: + cols_to_read.add("RUN_ID") + if "PRECURSOR_ID" in all_columns: + cols_to_read.add("PRECURSOR_ID") + + if ms1_cols and "PRECURSOR_DECOY" in all_columns: + cols_to_read.update(ms1_cols) + cols_to_read.add("PRECURSOR_DECOY") + if ms2_cols and "PRECURSOR_DECOY" in all_columns: + cols_to_read.update(ms2_cols) + cols_to_read.add("PRECURSOR_DECOY") + if transition_cols and "TRANSITION_DECOY" in all_columns: + cols_to_read.update(transition_cols) + cols_to_read.add("TRANSITION_DECOY") + + if not cols_to_read: + logger.warning("No VAR_ columns found in parquet file") + return + + # Read only the columns we need + logger.info(f"Reading {len(cols_to_read)} columns from parquet file") + df = pd.read_parquet(self.infile, columns=list(cols_to_read)) + + # Apply RANK==1 filter if SCORE columns exist + if has_scores and 'SCORE_MS2_PEAK_GROUP_RANK' in df.columns: + logger.info(f"Filtering to RANK==1: {len(df)} -> ", end="") + df = df[df['SCORE_MS2_PEAK_GROUP_RANK'] == 1].copy() + logger.info(f"{len(df)} rows") + + # Generate GROUP_ID if needed + if has_scores and 'GROUP_ID' not in df.columns: + if 'RUN_ID' in df.columns and 'PRECURSOR_ID' in df.columns: + df['GROUP_ID'] = df['RUN_ID'].astype(str) + '_' + df['PRECURSOR_ID'].astype(str) + + # Process MS1 level + if ms1_cols and "PRECURSOR_DECOY" in df.columns: + logger.info("Processing MS1 level feature scores") + select_cols = ms1_cols + ["PRECURSOR_DECOY"] + # Add SCORE columns if present + if has_scores: + score_ms1_cols = [col for col in score_cols if 'MS1' in col.upper()] + select_cols.extend(score_ms1_cols) + if 'GROUP_ID' in df.columns: + select_cols.append('GROUP_ID') + ms1_df = df[select_cols].copy() + ms1_df.rename(columns={"PRECURSOR_DECOY": "DECOY"}, inplace=True) + plot_callback(ms1_df, outfile, "ms1", append=False) + del ms1_df # Free memory + + # Process MS2 level + if ms2_cols and "PRECURSOR_DECOY" in df.columns: + logger.info("Processing MS2 level feature scores") + select_cols = ms2_cols + ["PRECURSOR_DECOY"] + # Add SCORE columns if present + if has_scores: + score_ms2_cols = [col for col in score_cols if 'MS2' in col.upper() or 'MS1' not in col.upper()] + select_cols.extend(score_ms2_cols) + if 'GROUP_ID' in df.columns: + select_cols.append('GROUP_ID') + ms2_df = df[select_cols].copy() + ms2_df.rename(columns={"PRECURSOR_DECOY": "DECOY"}, inplace=True) + append = bool(ms1_cols) + plot_callback(ms2_df, outfile, "ms2", append=append) + del ms2_df # Free memory + + # Process transition level + if transition_cols and "TRANSITION_DECOY" in df.columns: + logger.info("Processing transition level feature scores") + select_cols = transition_cols + ["TRANSITION_DECOY"] + # Add SCORE columns if present + if has_scores: + score_transition_cols = [col for col in score_cols if 'TRANSITION' in col.upper()] + select_cols.extend(score_transition_cols) + if 'GROUP_ID' in df.columns: + select_cols.append('GROUP_ID') + transition_df = df[select_cols].copy() + transition_df.rename(columns={"TRANSITION_DECOY": "DECOY"}, inplace=True) + append = bool(ms1_cols or ms2_cols) + plot_callback(transition_df, outfile, "transition", append=append) + del transition_df # Free memory + class ParquetWriter(BaseParquetWriter): """ diff --git a/pyprophet/io/export/split_parquet.py b/pyprophet/io/export/split_parquet.py index 265130a8..8eb4a696 100644 --- a/pyprophet/io/export/split_parquet.py +++ b/pyprophet/io/export/split_parquet.py @@ -4,7 +4,7 @@ import duckdb from loguru import logger -from ..util import get_parquet_column_names +from ..util import get_parquet_column_names, _ensure_pyarrow from .._base import BaseSplitParquetReader, BaseSplitParquetWriter from ..._config import ExportIOConfig @@ -666,6 +666,169 @@ def _build_feature_vars_sql(self) -> str: return ", " + ", ".join(feature_vars) if feature_vars else "" + def export_feature_scores(self, outfile: str, plot_callback): + """ + Export feature scores from split Parquet directory for plotting. + + Detects if SCORE columns exist and adjusts behavior: + - If SCORE columns exist: applies RANK==1 filtering and plots SCORE + VAR_ columns + - If SCORE columns don't exist: plots only VAR_ columns + + Parameters + ---------- + outfile : str + Path to the output PDF file. + plot_callback : callable + Function to call for plotting each level's data. + Signature: plot_callback(df, outfile, level, append) + """ + # Ensure pyarrow is available + pa, _, _ = _ensure_pyarrow() + + # Read precursor features - only necessary columns + precursor_file = os.path.join(self.infile, "precursors_features.parquet") + logger.info(f"Reading precursor features from: {precursor_file}") + + # First check what columns are available + precursor_parquet = pa.parquet.ParquetFile(precursor_file) + all_columns = precursor_parquet.schema.names + + # Check for SCORE columns + score_cols = [col for col in all_columns if col.startswith("SCORE_")] + has_scores = len(score_cols) > 0 + + if has_scores: + logger.info("SCORE columns detected - applying RANK==1 filter and plotting SCORE + VAR_ columns") + else: + logger.info("No SCORE columns detected - plotting only VAR_ columns") + + # Identify columns to read + ms1_cols = [col for col in all_columns if col.startswith("FEATURE_MS1_VAR_")] + ms2_cols = [col for col in all_columns if col.startswith("FEATURE_MS2_VAR_")] + + cols_to_read = set() + + # Add SCORE columns if they exist + if has_scores: + cols_to_read.update(score_cols) + # Add RANK column for filtering + if "SCORE_MS2_PEAK_GROUP_RANK" in all_columns: + cols_to_read.add("SCORE_MS2_PEAK_GROUP_RANK") + # Add ID columns for grouping + if "RUN_ID" in all_columns: + cols_to_read.add("RUN_ID") + if "PRECURSOR_ID" in all_columns: + cols_to_read.add("PRECURSOR_ID") + + if ms1_cols and "PRECURSOR_DECOY" in all_columns: + cols_to_read.update(ms1_cols) + cols_to_read.add("PRECURSOR_DECOY") + if ms2_cols and "PRECURSOR_DECOY" in all_columns: + cols_to_read.update(ms2_cols) + cols_to_read.add("PRECURSOR_DECOY") + + if cols_to_read: + logger.info(f"Reading {len(cols_to_read)} columns from precursor features") + df_precursor = pd.read_parquet(precursor_file, columns=list(cols_to_read)) + + # Apply RANK==1 filter if SCORE columns exist + if has_scores and 'SCORE_MS2_PEAK_GROUP_RANK' in df_precursor.columns: + logger.info(f"Filtering to RANK==1: {len(df_precursor)} -> ", end="") + df_precursor = df_precursor[df_precursor['SCORE_MS2_PEAK_GROUP_RANK'] == 1].copy() + logger.info(f"{len(df_precursor)} rows") + + # Generate GROUP_ID if needed + if has_scores and 'GROUP_ID' not in df_precursor.columns: + if 'RUN_ID' in df_precursor.columns and 'PRECURSOR_ID' in df_precursor.columns: + df_precursor['GROUP_ID'] = df_precursor['RUN_ID'].astype(str) + '_' + df_precursor['PRECURSOR_ID'].astype(str) + + # Process MS1 level + if ms1_cols and "PRECURSOR_DECOY" in df_precursor.columns: + logger.info("Processing MS1 level feature scores") + select_cols = ms1_cols + ["PRECURSOR_DECOY"] + # Add SCORE columns if present + if has_scores: + score_ms1_cols = [col for col in score_cols if 'MS1' in col.upper()] + select_cols.extend(score_ms1_cols) + if 'GROUP_ID' in df_precursor.columns: + select_cols.append('GROUP_ID') + ms1_df = df_precursor[select_cols].copy() + ms1_df.rename(columns={"PRECURSOR_DECOY": "DECOY"}, inplace=True) + plot_callback(ms1_df, outfile, "ms1", append=False) + del ms1_df # Free memory + + # Process MS2 level + if ms2_cols and "PRECURSOR_DECOY" in df_precursor.columns: + logger.info("Processing MS2 level feature scores") + select_cols = ms2_cols + ["PRECURSOR_DECOY"] + # Add SCORE columns if present + if has_scores: + score_ms2_cols = [col for col in score_cols if 'MS2' in col.upper() or 'MS1' not in col.upper()] + select_cols.extend(score_ms2_cols) + if 'GROUP_ID' in df_precursor.columns: + select_cols.append('GROUP_ID') + ms2_df = df_precursor[select_cols].copy() + ms2_df.rename(columns={"PRECURSOR_DECOY": "DECOY"}, inplace=True) + append = bool(ms1_cols) + plot_callback(ms2_df, outfile, "ms2", append=append) + del ms2_df # Free memory + + del df_precursor # Free memory + + # Read transition features if available + transition_file = os.path.join(self.infile, "transition_features.parquet") + if os.path.exists(transition_file): + logger.info(f"Reading transition features from: {transition_file}") + + # Check what columns are available + transition_parquet = pa.parquet.ParquetFile(transition_file) + transition_all_columns = transition_parquet.schema.names + transition_cols = [col for col in transition_all_columns if col.startswith("FEATURE_TRANSITION_VAR_")] + + # Check for SCORE columns in transition file + transition_score_cols = [col for col in transition_all_columns if col.startswith("SCORE_") and 'TRANSITION' in col.upper()] + has_transition_scores = len(transition_score_cols) > 0 + + if transition_cols and "TRANSITION_DECOY" in transition_all_columns: + # Read only necessary columns + cols_to_read = transition_cols + ["TRANSITION_DECOY"] + if has_transition_scores: + cols_to_read.extend(transition_score_cols) + if 'GROUP_ID' in transition_all_columns: + cols_to_read.append('GROUP_ID') + + logger.info(f"Reading {len(cols_to_read)} columns from transition features") + df_transition = pd.read_parquet(transition_file, columns=cols_to_read) + + logger.info("Processing transition level feature scores") + transition_df = df_transition.copy() + transition_df.rename(columns={"TRANSITION_DECOY": "DECOY"}, inplace=True) + append = bool(ms1_cols or ms2_cols) + plot_callback(transition_df, outfile, "transition", append=append) + del transition_df, df_transition # Free memory + + # Read alignment features if available + alignment_file = os.path.join(self.infile, "feature_alignment.parquet") + if os.path.exists(alignment_file): + logger.info(f"Reading alignment features from: {alignment_file}") + + # Check what columns are available + alignment_parquet = pa.parquet.ParquetFile(alignment_file) + alignment_all_columns = alignment_parquet.schema.names + var_cols = [col for col in alignment_all_columns if col.startswith("VAR_")] + + if var_cols and "DECOY" in alignment_all_columns: + # Read only necessary columns + cols_to_read = var_cols + ["DECOY"] + logger.info(f"Reading {len(cols_to_read)} columns from alignment features") + df_alignment = pd.read_parquet(alignment_file, columns=cols_to_read) + + logger.info("Processing alignment level feature scores") + alignment_df = df_alignment[var_cols + ["DECOY"]].copy() + append = bool(ms1_cols or ms2_cols or (os.path.exists(transition_file) and transition_cols)) + plot_callback(alignment_df, outfile, "alignment", append=append) + del alignment_df, df_alignment # Free memory + class SplitParquetWriter(BaseSplitParquetWriter): """ diff --git a/pyprophet/report.py b/pyprophet/report.py index ecd2534e..681e75a0 100644 --- a/pyprophet/report.py +++ b/pyprophet/report.py @@ -853,11 +853,12 @@ def plot_scores(df, out, color_palette="normal"): "Error: The matplotlib package is required to create a report." ) - score_columns = ( - ["SCORE"] - + [c for c in df.columns if c.startswith("MAIN_VAR_")] - + [c for c in df.columns if c.startswith("VAR_")] - ) + # Build score_columns list, only including SCORE if it exists + score_columns = [] + if "SCORE" in df.columns: + score_columns.append("SCORE") + score_columns += [c for c in df.columns if c.startswith("MAIN_VAR_")] + score_columns += [c for c in df.columns if c.startswith("VAR_")] t_col, d_col = color_blind_friendly(color_palette) diff --git a/pyprophet/scoring/_optimized.c b/pyprophet/scoring/_optimized.c index d25f3d5e..70c9b4f9 100644 --- a/pyprophet/scoring/_optimized.c +++ b/pyprophet/scoring/_optimized.c @@ -1383,7 +1383,7 @@ static const char *__pyx_filename; static const char* const __pyx_f[] = { "pyprophet/scoring/_optimized.pyx", "", - "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd", + "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd", "cpython/type.pxd", }; /* #### Code section: utility_code_proto_before_types ### */ @@ -1606,7 +1606,7 @@ typedef struct { /* #### Code section: numeric_typedefs ### */ -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":743 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":743 * # in Cython to enable them only on the right systems. * * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<< @@ -1615,7 +1615,7 @@ typedef struct { */ typedef npy_int8 __pyx_t_5numpy_int8_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":744 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":744 * * ctypedef npy_int8 int8_t * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<< @@ -1624,7 +1624,7 @@ typedef npy_int8 __pyx_t_5numpy_int8_t; */ typedef npy_int16 __pyx_t_5numpy_int16_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":745 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":745 * ctypedef npy_int8 int8_t * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<< @@ -1633,7 +1633,7 @@ typedef npy_int16 __pyx_t_5numpy_int16_t; */ typedef npy_int32 __pyx_t_5numpy_int32_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":746 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":746 * ctypedef npy_int16 int16_t * ctypedef npy_int32 int32_t * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<< @@ -1642,7 +1642,7 @@ typedef npy_int32 __pyx_t_5numpy_int32_t; */ typedef npy_int64 __pyx_t_5numpy_int64_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":748 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":748 * ctypedef npy_int64 int64_t * * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<< @@ -1651,7 +1651,7 @@ typedef npy_int64 __pyx_t_5numpy_int64_t; */ typedef npy_uint8 __pyx_t_5numpy_uint8_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":749 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":749 * * ctypedef npy_uint8 uint8_t * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<< @@ -1660,7 +1660,7 @@ typedef npy_uint8 __pyx_t_5numpy_uint8_t; */ typedef npy_uint16 __pyx_t_5numpy_uint16_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":750 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":750 * ctypedef npy_uint8 uint8_t * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<< @@ -1669,7 +1669,7 @@ typedef npy_uint16 __pyx_t_5numpy_uint16_t; */ typedef npy_uint32 __pyx_t_5numpy_uint32_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":751 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":751 * ctypedef npy_uint16 uint16_t * ctypedef npy_uint32 uint32_t * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<< @@ -1678,7 +1678,7 @@ typedef npy_uint32 __pyx_t_5numpy_uint32_t; */ typedef npy_uint64 __pyx_t_5numpy_uint64_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":753 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":753 * ctypedef npy_uint64 uint64_t * * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<< @@ -1687,7 +1687,7 @@ typedef npy_uint64 __pyx_t_5numpy_uint64_t; */ typedef npy_float32 __pyx_t_5numpy_float32_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":754 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":754 * * ctypedef npy_float32 float32_t * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<< @@ -1696,7 +1696,7 @@ typedef npy_float32 __pyx_t_5numpy_float32_t; */ typedef npy_float64 __pyx_t_5numpy_float64_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":761 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":761 * ctypedef double complex complex128_t * * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<< @@ -1705,7 +1705,7 @@ typedef npy_float64 __pyx_t_5numpy_float64_t; */ typedef npy_longlong __pyx_t_5numpy_longlong_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":762 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":762 * * ctypedef npy_longlong longlong_t * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<< @@ -1714,7 +1714,7 @@ typedef npy_longlong __pyx_t_5numpy_longlong_t; */ typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":764 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":764 * ctypedef npy_ulonglong ulonglong_t * * ctypedef npy_intp intp_t # <<<<<<<<<<<<<< @@ -1723,7 +1723,7 @@ typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; */ typedef npy_intp __pyx_t_5numpy_intp_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":765 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":765 * * ctypedef npy_intp intp_t * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<< @@ -1732,7 +1732,7 @@ typedef npy_intp __pyx_t_5numpy_intp_t; */ typedef npy_uintp __pyx_t_5numpy_uintp_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":767 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":767 * ctypedef npy_uintp uintp_t * * ctypedef npy_double float_t # <<<<<<<<<<<<<< @@ -1741,7 +1741,7 @@ typedef npy_uintp __pyx_t_5numpy_uintp_t; */ typedef npy_double __pyx_t_5numpy_float_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":768 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":768 * * ctypedef npy_double float_t * ctypedef npy_double double_t # <<<<<<<<<<<<<< @@ -1750,7 +1750,7 @@ typedef npy_double __pyx_t_5numpy_float_t; */ typedef npy_double __pyx_t_5numpy_double_t; -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":769 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":769 * ctypedef npy_double float_t * ctypedef npy_double double_t * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<< @@ -17271,7 +17271,7 @@ static PyObject *__pyx_unpickle_Enum__set_state(struct __pyx_MemviewEnum_obj *__ return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":242 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":242 * cdef int type_num * * @property # <<<<<<<<<<<<<< @@ -17282,7 +17282,7 @@ static PyObject *__pyx_unpickle_Enum__set_state(struct __pyx_MemviewEnum_obj *__ static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_8itemsize_itemsize(PyArray_Descr *__pyx_v_self) { npy_intp __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":244 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":244 * @property * cdef inline npy_intp itemsize(self) noexcept nogil: * return PyDataType_ELSIZE(self) # <<<<<<<<<<<<<< @@ -17292,7 +17292,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_8itemsize_itemsize(PyArray_D __pyx_r = PyDataType_ELSIZE(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":242 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":242 * cdef int type_num * * @property # <<<<<<<<<<<<<< @@ -17305,7 +17305,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_8itemsize_itemsize(PyArray_D return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":246 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":246 * return PyDataType_ELSIZE(self) * * @property # <<<<<<<<<<<<<< @@ -17316,7 +17316,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_8itemsize_itemsize(PyArray_D static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_9alignment_alignment(PyArray_Descr *__pyx_v_self) { npy_intp __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":248 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":248 * @property * cdef inline npy_intp alignment(self) noexcept nogil: * return PyDataType_ALIGNMENT(self) # <<<<<<<<<<<<<< @@ -17326,7 +17326,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_9alignment_alignment(PyArray __pyx_r = PyDataType_ALIGNMENT(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":246 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":246 * return PyDataType_ELSIZE(self) * * @property # <<<<<<<<<<<<<< @@ -17339,7 +17339,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_9alignment_alignment(PyArray return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":252 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":252 * # Use fields/names with care as they may be NULL. You must check * # for this using PyDataType_HASFIELDS. * @property # <<<<<<<<<<<<<< @@ -17353,7 +17353,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_6fields_fields(PyArray_Desc PyObject *__pyx_t_1; __Pyx_RefNannySetupContext("fields", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":254 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":254 * @property * cdef inline object fields(self): * return PyDataType_FIELDS(self) # <<<<<<<<<<<<<< @@ -17366,7 +17366,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_6fields_fields(PyArray_Desc __pyx_r = ((PyObject *)__pyx_t_1); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":252 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":252 * # Use fields/names with care as they may be NULL. You must check * # for this using PyDataType_HASFIELDS. * @property # <<<<<<<<<<<<<< @@ -17381,7 +17381,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_6fields_fields(PyArray_Desc return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":256 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":256 * return PyDataType_FIELDS(self) * * @property # <<<<<<<<<<<<<< @@ -17395,7 +17395,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_5names_names(PyArray_Descr PyObject *__pyx_t_1; __Pyx_RefNannySetupContext("names", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":258 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":258 * @property * cdef inline tuple names(self): * return PyDataType_NAMES(self) # <<<<<<<<<<<<<< @@ -17408,7 +17408,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_5names_names(PyArray_Descr __pyx_r = ((PyObject*)__pyx_t_1); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":256 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":256 * return PyDataType_FIELDS(self) * * @property # <<<<<<<<<<<<<< @@ -17423,7 +17423,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_5names_names(PyArray_Descr return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":263 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":263 * # valid (the pointer can be NULL). Most users should access * # this field via the inline helper method PyDataType_SHAPE. * @property # <<<<<<<<<<<<<< @@ -17434,7 +17434,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_5names_names(PyArray_Descr static CYTHON_INLINE PyArray_ArrayDescr *__pyx_f_5numpy_5dtype_8subarray_subarray(PyArray_Descr *__pyx_v_self) { PyArray_ArrayDescr *__pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":265 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":265 * @property * cdef inline PyArray_ArrayDescr* subarray(self) noexcept nogil: * return PyDataType_SUBARRAY(self) # <<<<<<<<<<<<<< @@ -17444,7 +17444,7 @@ static CYTHON_INLINE PyArray_ArrayDescr *__pyx_f_5numpy_5dtype_8subarray_subarra __pyx_r = PyDataType_SUBARRAY(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":263 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":263 * # valid (the pointer can be NULL). Most users should access * # this field via the inline helper method PyDataType_SHAPE. * @property # <<<<<<<<<<<<<< @@ -17457,7 +17457,7 @@ static CYTHON_INLINE PyArray_ArrayDescr *__pyx_f_5numpy_5dtype_8subarray_subarra return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":267 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":267 * return PyDataType_SUBARRAY(self) * * @property # <<<<<<<<<<<<<< @@ -17468,7 +17468,7 @@ static CYTHON_INLINE PyArray_ArrayDescr *__pyx_f_5numpy_5dtype_8subarray_subarra static CYTHON_INLINE npy_uint64 __pyx_f_5numpy_5dtype_5flags_flags(PyArray_Descr *__pyx_v_self) { npy_uint64 __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":270 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":270 * cdef inline npy_uint64 flags(self) noexcept nogil: * """The data types flags.""" * return PyDataType_FLAGS(self) # <<<<<<<<<<<<<< @@ -17478,7 +17478,7 @@ static CYTHON_INLINE npy_uint64 __pyx_f_5numpy_5dtype_5flags_flags(PyArray_Descr __pyx_r = PyDataType_FLAGS(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":267 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":267 * return PyDataType_SUBARRAY(self) * * @property # <<<<<<<<<<<<<< @@ -17491,7 +17491,7 @@ static CYTHON_INLINE npy_uint64 __pyx_f_5numpy_5dtype_5flags_flags(PyArray_Descr return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":279 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":279 * ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]: * * @property # <<<<<<<<<<<<<< @@ -17502,7 +17502,7 @@ static CYTHON_INLINE npy_uint64 __pyx_f_5numpy_5dtype_5flags_flags(PyArray_Descr static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_7numiter_numiter(PyArrayMultiIterObject *__pyx_v_self) { int __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":282 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":282 * cdef inline int numiter(self) noexcept nogil: * """The number of arrays that need to be broadcast to the same shape.""" * return PyArray_MultiIter_NUMITER(self) # <<<<<<<<<<<<<< @@ -17512,7 +17512,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_7numiter_numiter(PyArrayMulti __pyx_r = PyArray_MultiIter_NUMITER(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":279 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":279 * ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]: * * @property # <<<<<<<<<<<<<< @@ -17525,7 +17525,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_7numiter_numiter(PyArrayMulti return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":284 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":284 * return PyArray_MultiIter_NUMITER(self) * * @property # <<<<<<<<<<<<<< @@ -17536,7 +17536,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_7numiter_numiter(PyArrayMulti static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_4size_size(PyArrayMultiIterObject *__pyx_v_self) { npy_intp __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":287 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":287 * cdef inline npy_intp size(self) noexcept nogil: * """The total broadcasted size.""" * return PyArray_MultiIter_SIZE(self) # <<<<<<<<<<<<<< @@ -17546,7 +17546,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_4size_size(PyArrayMultiI __pyx_r = PyArray_MultiIter_SIZE(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":284 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":284 * return PyArray_MultiIter_NUMITER(self) * * @property # <<<<<<<<<<<<<< @@ -17559,7 +17559,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_4size_size(PyArrayMultiI return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":289 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":289 * return PyArray_MultiIter_SIZE(self) * * @property # <<<<<<<<<<<<<< @@ -17570,7 +17570,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_4size_size(PyArrayMultiI static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_5index_index(PyArrayMultiIterObject *__pyx_v_self) { npy_intp __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":292 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":292 * cdef inline npy_intp index(self) noexcept nogil: * """The current (1-d) index into the broadcasted result.""" * return PyArray_MultiIter_INDEX(self) # <<<<<<<<<<<<<< @@ -17580,7 +17580,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_5index_index(PyArrayMult __pyx_r = PyArray_MultiIter_INDEX(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":289 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":289 * return PyArray_MultiIter_SIZE(self) * * @property # <<<<<<<<<<<<<< @@ -17593,7 +17593,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_5index_index(PyArrayMult return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":294 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":294 * return PyArray_MultiIter_INDEX(self) * * @property # <<<<<<<<<<<<<< @@ -17604,7 +17604,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_5index_index(PyArrayMult static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_2nd_nd(PyArrayMultiIterObject *__pyx_v_self) { int __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":297 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":297 * cdef inline int nd(self) noexcept nogil: * """The number of dimensions in the broadcasted result.""" * return PyArray_MultiIter_NDIM(self) # <<<<<<<<<<<<<< @@ -17614,7 +17614,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_2nd_nd(PyArrayMultiIterObject __pyx_r = PyArray_MultiIter_NDIM(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":294 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":294 * return PyArray_MultiIter_INDEX(self) * * @property # <<<<<<<<<<<<<< @@ -17627,7 +17627,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_2nd_nd(PyArrayMultiIterObject return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":299 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":299 * return PyArray_MultiIter_NDIM(self) * * @property # <<<<<<<<<<<<<< @@ -17638,7 +17638,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_2nd_nd(PyArrayMultiIterObject static CYTHON_INLINE npy_intp *__pyx_f_5numpy_9broadcast_10dimensions_dimensions(PyArrayMultiIterObject *__pyx_v_self) { npy_intp *__pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":302 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":302 * cdef inline npy_intp* dimensions(self) noexcept nogil: * """The shape of the broadcasted result.""" * return PyArray_MultiIter_DIMS(self) # <<<<<<<<<<<<<< @@ -17648,7 +17648,7 @@ static CYTHON_INLINE npy_intp *__pyx_f_5numpy_9broadcast_10dimensions_dimensions __pyx_r = PyArray_MultiIter_DIMS(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":299 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":299 * return PyArray_MultiIter_NDIM(self) * * @property # <<<<<<<<<<<<<< @@ -17661,7 +17661,7 @@ static CYTHON_INLINE npy_intp *__pyx_f_5numpy_9broadcast_10dimensions_dimensions return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":304 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":304 * return PyArray_MultiIter_DIMS(self) * * @property # <<<<<<<<<<<<<< @@ -17672,7 +17672,7 @@ static CYTHON_INLINE npy_intp *__pyx_f_5numpy_9broadcast_10dimensions_dimensions static CYTHON_INLINE void **__pyx_f_5numpy_9broadcast_5iters_iters(PyArrayMultiIterObject *__pyx_v_self) { void **__pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":308 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":308 * """An array of iterator objects that holds the iterators for the arrays to be broadcast together. * On return, the iterators are adjusted for broadcasting.""" * return PyArray_MultiIter_ITERS(self) # <<<<<<<<<<<<<< @@ -17682,7 +17682,7 @@ static CYTHON_INLINE void **__pyx_f_5numpy_9broadcast_5iters_iters(PyArrayMultiI __pyx_r = PyArray_MultiIter_ITERS(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":304 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":304 * return PyArray_MultiIter_DIMS(self) * * @property # <<<<<<<<<<<<<< @@ -17695,7 +17695,7 @@ static CYTHON_INLINE void **__pyx_f_5numpy_9broadcast_5iters_iters(PyArrayMultiI return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":322 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":322 * # Instead, we use properties that map to the corresponding C-API functions. * * @property # <<<<<<<<<<<<<< @@ -17706,7 +17706,7 @@ static CYTHON_INLINE void **__pyx_f_5numpy_9broadcast_5iters_iters(PyArrayMultiI static CYTHON_INLINE PyObject *__pyx_f_5numpy_7ndarray_4base_base(PyArrayObject *__pyx_v_self) { PyObject *__pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":326 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":326 * """Returns a borrowed reference to the object owning the data/memory. * """ * return PyArray_BASE(self) # <<<<<<<<<<<<<< @@ -17716,7 +17716,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_7ndarray_4base_base(PyArrayObject __pyx_r = PyArray_BASE(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":322 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":322 * # Instead, we use properties that map to the corresponding C-API functions. * * @property # <<<<<<<<<<<<<< @@ -17729,7 +17729,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_7ndarray_4base_base(PyArrayObject return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":328 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":328 * return PyArray_BASE(self) * * @property # <<<<<<<<<<<<<< @@ -17743,7 +17743,7 @@ static CYTHON_INLINE PyArray_Descr *__pyx_f_5numpy_7ndarray_5descr_descr(PyArray PyArray_Descr *__pyx_t_1; __Pyx_RefNannySetupContext("descr", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":332 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":332 * """Returns an owned reference to the dtype of the array. * """ * return PyArray_DESCR(self) # <<<<<<<<<<<<<< @@ -17756,7 +17756,7 @@ static CYTHON_INLINE PyArray_Descr *__pyx_f_5numpy_7ndarray_5descr_descr(PyArray __pyx_r = ((PyArray_Descr *)__pyx_t_1); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":328 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":328 * return PyArray_BASE(self) * * @property # <<<<<<<<<<<<<< @@ -17771,7 +17771,7 @@ static CYTHON_INLINE PyArray_Descr *__pyx_f_5numpy_7ndarray_5descr_descr(PyArray return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":334 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":334 * return PyArray_DESCR(self) * * @property # <<<<<<<<<<<<<< @@ -17782,7 +17782,7 @@ static CYTHON_INLINE PyArray_Descr *__pyx_f_5numpy_7ndarray_5descr_descr(PyArray static CYTHON_INLINE int __pyx_f_5numpy_7ndarray_4ndim_ndim(PyArrayObject *__pyx_v_self) { int __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":338 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":338 * """Returns the number of dimensions in the array. * """ * return PyArray_NDIM(self) # <<<<<<<<<<<<<< @@ -17792,7 +17792,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_7ndarray_4ndim_ndim(PyArrayObject *__pyx __pyx_r = PyArray_NDIM(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":334 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":334 * return PyArray_DESCR(self) * * @property # <<<<<<<<<<<<<< @@ -17805,7 +17805,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_7ndarray_4ndim_ndim(PyArrayObject *__pyx return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":340 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":340 * return PyArray_NDIM(self) * * @property # <<<<<<<<<<<<<< @@ -17816,7 +17816,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_7ndarray_4ndim_ndim(PyArrayObject *__pyx static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_5shape_shape(PyArrayObject *__pyx_v_self) { npy_intp *__pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":346 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":346 * Can return NULL for 0-dimensional arrays. * """ * return PyArray_DIMS(self) # <<<<<<<<<<<<<< @@ -17826,7 +17826,7 @@ static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_5shape_shape(PyArrayObjec __pyx_r = PyArray_DIMS(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":340 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":340 * return PyArray_NDIM(self) * * @property # <<<<<<<<<<<<<< @@ -17839,7 +17839,7 @@ static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_5shape_shape(PyArrayObjec return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":348 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":348 * return PyArray_DIMS(self) * * @property # <<<<<<<<<<<<<< @@ -17850,7 +17850,7 @@ static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_5shape_shape(PyArrayObjec static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_7strides_strides(PyArrayObject *__pyx_v_self) { npy_intp *__pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":353 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":353 * The number of elements matches the number of dimensions of the array (ndim). * """ * return PyArray_STRIDES(self) # <<<<<<<<<<<<<< @@ -17860,7 +17860,7 @@ static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_7strides_strides(PyArrayO __pyx_r = PyArray_STRIDES(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":348 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":348 * return PyArray_DIMS(self) * * @property # <<<<<<<<<<<<<< @@ -17873,7 +17873,7 @@ static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_7strides_strides(PyArrayO return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":355 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":355 * return PyArray_STRIDES(self) * * @property # <<<<<<<<<<<<<< @@ -17884,7 +17884,7 @@ static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_7strides_strides(PyArrayO static CYTHON_INLINE npy_intp __pyx_f_5numpy_7ndarray_4size_size(PyArrayObject *__pyx_v_self) { npy_intp __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":359 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":359 * """Returns the total size (in number of elements) of the array. * """ * return PyArray_SIZE(self) # <<<<<<<<<<<<<< @@ -17894,7 +17894,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_7ndarray_4size_size(PyArrayObject * __pyx_r = PyArray_SIZE(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":355 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":355 * return PyArray_STRIDES(self) * * @property # <<<<<<<<<<<<<< @@ -17907,7 +17907,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_7ndarray_4size_size(PyArrayObject * return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":361 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":361 * return PyArray_SIZE(self) * * @property # <<<<<<<<<<<<<< @@ -17918,7 +17918,7 @@ static CYTHON_INLINE npy_intp __pyx_f_5numpy_7ndarray_4size_size(PyArrayObject * static CYTHON_INLINE char *__pyx_f_5numpy_7ndarray_4data_data(PyArrayObject *__pyx_v_self) { char *__pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":368 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":368 * of `PyArray_DATA()` instead, which returns a 'void*'. * """ * return PyArray_BYTES(self) # <<<<<<<<<<<<<< @@ -17928,7 +17928,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy_7ndarray_4data_data(PyArrayObject *__p __pyx_r = PyArray_BYTES(__pyx_v_self); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":361 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":361 * return PyArray_SIZE(self) * * @property # <<<<<<<<<<<<<< @@ -17941,7 +17941,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy_7ndarray_4data_data(PyArrayObject *__p return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":776 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":776 * ctypedef long double complex clongdouble_t * * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< @@ -17958,7 +17958,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__ int __pyx_clineno = 0; __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":777 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":777 * * cdef inline object PyArray_MultiIterNew1(a): * return PyArray_MultiIterNew(1, a) # <<<<<<<<<<<<<< @@ -17972,7 +17972,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__ __pyx_t_1 = 0; goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":776 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":776 * ctypedef long double complex clongdouble_t * * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< @@ -17991,7 +17991,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__ return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":779 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":779 * return PyArray_MultiIterNew(1, a) * * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< @@ -18008,7 +18008,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__ int __pyx_clineno = 0; __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":780 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":780 * * cdef inline object PyArray_MultiIterNew2(a, b): * return PyArray_MultiIterNew(2, a, b) # <<<<<<<<<<<<<< @@ -18022,7 +18022,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__ __pyx_t_1 = 0; goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":779 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":779 * return PyArray_MultiIterNew(1, a) * * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< @@ -18041,7 +18041,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__ return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":782 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":782 * return PyArray_MultiIterNew(2, a, b) * * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< @@ -18058,7 +18058,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__ int __pyx_clineno = 0; __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":783 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":783 * * cdef inline object PyArray_MultiIterNew3(a, b, c): * return PyArray_MultiIterNew(3, a, b, c) # <<<<<<<<<<<<<< @@ -18072,7 +18072,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__ __pyx_t_1 = 0; goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":782 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":782 * return PyArray_MultiIterNew(2, a, b) * * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< @@ -18091,7 +18091,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__ return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":785 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":785 * return PyArray_MultiIterNew(3, a, b, c) * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< @@ -18108,7 +18108,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__ int __pyx_clineno = 0; __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":786 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":786 * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): * return PyArray_MultiIterNew(4, a, b, c, d) # <<<<<<<<<<<<<< @@ -18122,7 +18122,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__ __pyx_t_1 = 0; goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":785 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":785 * return PyArray_MultiIterNew(3, a, b, c) * * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< @@ -18141,7 +18141,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__ return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":788 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":788 * return PyArray_MultiIterNew(4, a, b, c, d) * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< @@ -18158,7 +18158,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__ int __pyx_clineno = 0; __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":789 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":789 * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): * return PyArray_MultiIterNew(5, a, b, c, d, e) # <<<<<<<<<<<<<< @@ -18172,7 +18172,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__ __pyx_t_1 = 0; goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":788 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":788 * return PyArray_MultiIterNew(4, a, b, c, d) * * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< @@ -18191,7 +18191,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__ return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":791 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":791 * return PyArray_MultiIterNew(5, a, b, c, d, e) * * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< @@ -18206,7 +18206,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__ PyObject *__pyx_t_2; __Pyx_RefNannySetupContext("PyDataType_SHAPE", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":792 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":792 * * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< @@ -18216,7 +18216,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__ __pyx_t_1 = PyDataType_HASSUBARRAY(__pyx_v_d); if (__pyx_t_1) { - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":793 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":793 * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): * return d.subarray.shape # <<<<<<<<<<<<<< @@ -18229,7 +18229,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__ __pyx_r = ((PyObject*)__pyx_t_2); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":792 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":792 * * cdef inline tuple PyDataType_SHAPE(dtype d): * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< @@ -18238,7 +18238,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__ */ } - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":795 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":795 * return d.subarray.shape * else: * return () # <<<<<<<<<<<<<< @@ -18252,7 +18252,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__ goto __pyx_L0; } - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":791 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":791 * return PyArray_MultiIterNew(5, a, b, c, d, e) * * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< @@ -18267,7 +18267,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__ return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":994 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":994 * int _import_umath() except -1 * * cdef inline void set_array_base(ndarray arr, object base) except *: # <<<<<<<<<<<<<< @@ -18281,7 +18281,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a const char *__pyx_filename = NULL; int __pyx_clineno = 0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":995 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":995 * * cdef inline void set_array_base(ndarray arr, object base) except *: * Py_INCREF(base) # important to do this before stealing the reference below! # <<<<<<<<<<<<<< @@ -18290,7 +18290,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a */ Py_INCREF(__pyx_v_base); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":996 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":996 * cdef inline void set_array_base(ndarray arr, object base) except *: * Py_INCREF(base) # important to do this before stealing the reference below! * PyArray_SetBaseObject(arr, base) # <<<<<<<<<<<<<< @@ -18299,7 +18299,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a */ __pyx_t_1 = PyArray_SetBaseObject(__pyx_v_arr, __pyx_v_base); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(2, 996, __pyx_L1_error) - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":994 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":994 * int _import_umath() except -1 * * cdef inline void set_array_base(ndarray arr, object base) except *: # <<<<<<<<<<<<<< @@ -18314,7 +18314,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a __pyx_L0:; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":998 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":998 * PyArray_SetBaseObject(arr, base) * * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< @@ -18329,7 +18329,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py int __pyx_t_1; __Pyx_RefNannySetupContext("get_array_base", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":999 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":999 * * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) # <<<<<<<<<<<<<< @@ -18338,7 +18338,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py */ __pyx_v_base = PyArray_BASE(__pyx_v_arr); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1000 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1000 * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) * if base is NULL: # <<<<<<<<<<<<<< @@ -18348,7 +18348,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py __pyx_t_1 = (__pyx_v_base == NULL); if (__pyx_t_1) { - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1001 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1001 * base = PyArray_BASE(arr) * if base is NULL: * return None # <<<<<<<<<<<<<< @@ -18359,7 +18359,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1000 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1000 * cdef inline object get_array_base(ndarray arr): * base = PyArray_BASE(arr) * if base is NULL: # <<<<<<<<<<<<<< @@ -18368,7 +18368,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py */ } - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1002 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1002 * if base is NULL: * return None * return base # <<<<<<<<<<<<<< @@ -18380,7 +18380,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py __pyx_r = ((PyObject *)__pyx_v_base); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":998 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":998 * PyArray_SetBaseObject(arr, base) * * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< @@ -18395,7 +18395,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1006 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1006 * # Versions of the import_* functions which are more suitable for * # Cython code. * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< @@ -18422,7 +18422,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { int __pyx_clineno = 0; __Pyx_RefNannySetupContext("import_array", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1007 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1007 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< @@ -18438,7 +18438,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1008 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1008 * cdef inline int import_array() except -1: * try: * __pyx_import_array() # <<<<<<<<<<<<<< @@ -18447,7 +18447,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { */ __pyx_t_4 = _import_array(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 1008, __pyx_L3_error) - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1007 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1007 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< @@ -18461,7 +18461,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { goto __pyx_L8_try_end; __pyx_L3_error:; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1009 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1009 * try: * __pyx_import_array() * except Exception: # <<<<<<<<<<<<<< @@ -18476,7 +18476,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { __Pyx_XGOTREF(__pyx_t_6); __Pyx_XGOTREF(__pyx_t_7); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1010 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1010 * __pyx_import_array() * except Exception: * raise ImportError("numpy._core.multiarray failed to import") # <<<<<<<<<<<<<< @@ -18501,7 +18501,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { } goto __pyx_L5_except_error; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1007 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1007 * # Cython code. * cdef inline int import_array() except -1: * try: # <<<<<<<<<<<<<< @@ -18517,7 +18517,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { __pyx_L8_try_end:; } - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1006 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1006 * # Versions of the import_* functions which are more suitable for * # Cython code. * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< @@ -18542,7 +18542,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1012 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1012 * raise ImportError("numpy._core.multiarray failed to import") * * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< @@ -18569,7 +18569,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { int __pyx_clineno = 0; __Pyx_RefNannySetupContext("import_umath", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1013 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1013 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< @@ -18585,7 +18585,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1014 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1014 * cdef inline int import_umath() except -1: * try: * _import_umath() # <<<<<<<<<<<<<< @@ -18594,7 +18594,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { */ __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 1014, __pyx_L3_error) - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1013 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1013 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< @@ -18608,7 +18608,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { goto __pyx_L8_try_end; __pyx_L3_error:; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1015 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1015 * try: * _import_umath() * except Exception: # <<<<<<<<<<<<<< @@ -18623,7 +18623,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { __Pyx_XGOTREF(__pyx_t_6); __Pyx_XGOTREF(__pyx_t_7); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1016 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1016 * _import_umath() * except Exception: * raise ImportError("numpy._core.umath failed to import") # <<<<<<<<<<<<<< @@ -18648,7 +18648,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { } goto __pyx_L5_except_error; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1013 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1013 * * cdef inline int import_umath() except -1: * try: # <<<<<<<<<<<<<< @@ -18664,7 +18664,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { __pyx_L8_try_end:; } - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1012 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1012 * raise ImportError("numpy._core.multiarray failed to import") * * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< @@ -18689,7 +18689,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1018 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1018 * raise ImportError("numpy._core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< @@ -18716,7 +18716,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { int __pyx_clineno = 0; __Pyx_RefNannySetupContext("import_ufunc", 0); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1019 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1019 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< @@ -18732,7 +18732,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { __Pyx_XGOTREF(__pyx_t_3); /*try:*/ { - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1020 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1020 * cdef inline int import_ufunc() except -1: * try: * _import_umath() # <<<<<<<<<<<<<< @@ -18741,7 +18741,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { */ __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 1020, __pyx_L3_error) - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1019 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1019 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< @@ -18755,7 +18755,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { goto __pyx_L8_try_end; __pyx_L3_error:; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1021 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1021 * try: * _import_umath() * except Exception: # <<<<<<<<<<<<<< @@ -18770,7 +18770,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { __Pyx_XGOTREF(__pyx_t_6); __Pyx_XGOTREF(__pyx_t_7); - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1022 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1022 * _import_umath() * except Exception: * raise ImportError("numpy._core.umath failed to import") # <<<<<<<<<<<<<< @@ -18795,7 +18795,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { } goto __pyx_L5_except_error; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1019 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1019 * * cdef inline int import_ufunc() except -1: * try: # <<<<<<<<<<<<<< @@ -18811,7 +18811,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { __pyx_L8_try_end:; } - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1018 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1018 * raise ImportError("numpy._core.umath failed to import") * * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< @@ -18836,7 +18836,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1025 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1025 * * * cdef inline bint is_timedelta64_object(object obj) noexcept: # <<<<<<<<<<<<<< @@ -18847,7 +18847,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { static CYTHON_INLINE int __pyx_f_5numpy_is_timedelta64_object(PyObject *__pyx_v_obj) { int __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1037 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1037 * bool * """ * return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type) # <<<<<<<<<<<<<< @@ -18857,7 +18857,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_is_timedelta64_object(PyObject *__pyx_v_ __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyTimedeltaArrType_Type)); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1025 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1025 * * * cdef inline bint is_timedelta64_object(object obj) noexcept: # <<<<<<<<<<<<<< @@ -18870,7 +18870,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_is_timedelta64_object(PyObject *__pyx_v_ return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1040 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1040 * * * cdef inline bint is_datetime64_object(object obj) noexcept: # <<<<<<<<<<<<<< @@ -18881,7 +18881,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_is_timedelta64_object(PyObject *__pyx_v_ static CYTHON_INLINE int __pyx_f_5numpy_is_datetime64_object(PyObject *__pyx_v_obj) { int __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1052 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1052 * bool * """ * return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type) # <<<<<<<<<<<<<< @@ -18891,7 +18891,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_is_datetime64_object(PyObject *__pyx_v_o __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyDatetimeArrType_Type)); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1040 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1040 * * * cdef inline bint is_datetime64_object(object obj) noexcept: # <<<<<<<<<<<<<< @@ -18904,7 +18904,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_is_datetime64_object(PyObject *__pyx_v_o return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1055 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1055 * * * cdef inline npy_datetime get_datetime64_value(object obj) noexcept nogil: # <<<<<<<<<<<<<< @@ -18915,7 +18915,7 @@ static CYTHON_INLINE int __pyx_f_5numpy_is_datetime64_object(PyObject *__pyx_v_o static CYTHON_INLINE npy_datetime __pyx_f_5numpy_get_datetime64_value(PyObject *__pyx_v_obj) { npy_datetime __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1062 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1062 * also needed. That can be found using `get_datetime64_unit`. * """ * return (obj).obval # <<<<<<<<<<<<<< @@ -18925,7 +18925,7 @@ static CYTHON_INLINE npy_datetime __pyx_f_5numpy_get_datetime64_value(PyObject * __pyx_r = ((PyDatetimeScalarObject *)__pyx_v_obj)->obval; goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1055 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1055 * * * cdef inline npy_datetime get_datetime64_value(object obj) noexcept nogil: # <<<<<<<<<<<<<< @@ -18938,7 +18938,7 @@ static CYTHON_INLINE npy_datetime __pyx_f_5numpy_get_datetime64_value(PyObject * return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1065 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1065 * * * cdef inline npy_timedelta get_timedelta64_value(object obj) noexcept nogil: # <<<<<<<<<<<<<< @@ -18949,7 +18949,7 @@ static CYTHON_INLINE npy_datetime __pyx_f_5numpy_get_datetime64_value(PyObject * static CYTHON_INLINE npy_timedelta __pyx_f_5numpy_get_timedelta64_value(PyObject *__pyx_v_obj) { npy_timedelta __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1069 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1069 * returns the int64 value underlying scalar numpy timedelta64 object * """ * return (obj).obval # <<<<<<<<<<<<<< @@ -18959,7 +18959,7 @@ static CYTHON_INLINE npy_timedelta __pyx_f_5numpy_get_timedelta64_value(PyObject __pyx_r = ((PyTimedeltaScalarObject *)__pyx_v_obj)->obval; goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1065 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1065 * * * cdef inline npy_timedelta get_timedelta64_value(object obj) noexcept nogil: # <<<<<<<<<<<<<< @@ -18972,7 +18972,7 @@ static CYTHON_INLINE npy_timedelta __pyx_f_5numpy_get_timedelta64_value(PyObject return __pyx_r; } -/* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1072 +/* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1072 * * * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) noexcept nogil: # <<<<<<<<<<<<<< @@ -18983,7 +18983,7 @@ static CYTHON_INLINE npy_timedelta __pyx_f_5numpy_get_timedelta64_value(PyObject static CYTHON_INLINE NPY_DATETIMEUNIT __pyx_f_5numpy_get_datetime64_unit(PyObject *__pyx_v_obj) { NPY_DATETIMEUNIT __pyx_r; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1076 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1076 * returns the unit part of the dtype for a numpy datetime64 object. * """ * return (obj).obmeta.base # <<<<<<<<<<<<<< @@ -18993,7 +18993,7 @@ static CYTHON_INLINE NPY_DATETIMEUNIT __pyx_f_5numpy_get_datetime64_unit(PyObjec __pyx_r = ((NPY_DATETIMEUNIT)((PyDatetimeScalarObject *)__pyx_v_obj)->obmeta.base); goto __pyx_L0; - /* "../../../../../tmp/pip-build-env-_tc7qfiq/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1072 + /* "../../../../../tmp/pip-build-env-x3g6sxmd/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1072 * * * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) noexcept nogil: # <<<<<<<<<<<<<< diff --git a/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_ms1_ms2_transition.out b/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_ms1_ms2_transition.out new file mode 100644 index 00000000..8235141f --- /dev/null +++ b/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_ms1_ms2_transition.out @@ -0,0 +1,8 @@ +Created 4 PDF file(s) from multi-level scoring: + MS1 files: 1 + MS2 files: 1 + Transition files: 1 + - feature_scores.pdf + - test_data_ms1_report.pdf + - test_data_ms2_report.pdf + - test_data_transition_report.pdf diff --git a/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_parquet_with_scores.out b/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_parquet_with_scores.out new file mode 100644 index 00000000..9d69ad74 --- /dev/null +++ b/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_parquet_with_scores.out @@ -0,0 +1 @@ +Successfully created feature scores from Parquet with SCORE columns diff --git a/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_scored_osw.out b/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_scored_osw.out new file mode 100644 index 00000000..14806759 --- /dev/null +++ b/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_scored_osw.out @@ -0,0 +1,3 @@ +Created 2 PDF file(s) from scored OSW: + - feature_scores.pdf + - test_data_ms2_report.pdf diff --git a/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_split_parquet_with_scores.out b/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_split_parquet_with_scores.out new file mode 100644 index 00000000..30ac013a --- /dev/null +++ b/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_split_parquet_with_scores.out @@ -0,0 +1 @@ +Successfully created feature scores from split Parquet with SCORE columns diff --git a/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_unscored_osw.out b/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_unscored_osw.out new file mode 100644 index 00000000..84d09e4d --- /dev/null +++ b/tests/_regtest_outputs/test_pyprophet_export.test_feature_scores_unscored_osw.out @@ -0,0 +1,2 @@ +Created 1 PDF file(s): + - feature_scores.pdf diff --git a/tests/test_pyprophet_export.py b/tests/test_pyprophet_export.py index 31b0ad1a..cbfff358 100644 --- a/tests/test_pyprophet_export.py +++ b/tests/test_pyprophet_export.py @@ -9,6 +9,8 @@ import pandas as pd import pytest +from pyprophet.export.export_report import export_feature_scores + pd.options.display.expand_frame_repr = False pd.options.display.precision = 4 pd.options.display.max_columns = None @@ -91,10 +93,12 @@ def run_pyprophet_command(cmd, temp_folder): ).decode() except subprocess.CalledProcessError as error: print(f"Command failed: {cmd}\n{error.output.decode()}", file=sys.stderr) - if "NotImplementedError" in error.output.decode(): # attempt to catch the specific error rather than the CalledProcessError + if ( + "NotImplementedError" in error.output.decode() + ): # attempt to catch the specific error rather than the CalledProcessError raise NotImplementedError else: - raise + raise def validate_export_results( @@ -150,12 +154,11 @@ def test_osw_analysis( f"{temp_folder}/test_data.tsv", ) + @pytest.mark.parametrize( - "calib, rt_unit", - [ (True, 'iRT'), (False, 'iRT'), (True, 'RT'), (False, 'RT')] + "calib, rt_unit", [(True, "iRT"), (False, "iRT"), (True, "RT"), (False, "RT")] ) -def test_osw_analysis_libExport(input_strategy, temp_folder, regtest, calib, rt_unit -): +def test_osw_analysis_libExport(input_strategy, temp_folder, regtest, calib, rt_unit): cmd = f"pyprophet score {input_strategy['cmd_prefix']} --level=ms2 --test --pi0_lambda=0.001 0 0 --ss_iteration_fdr=0.02 && " # peptide-level @@ -164,7 +167,6 @@ def test_osw_analysis_libExport(input_strategy, temp_folder, regtest, calib, rt_ # protein-level cmd += f"pyprophet infer protein --pi0_lambda=0 0 0 {input_strategy['cmd_prefix']} --context=global && " - # export if calib: cmd += f"pyprophet export library {input_strategy['cmd_prefix']} --out={temp_folder}/test_lib.tsv --test --max_peakgroup_qvalue=1 --max_global_peptide_qvalue=1 --max_global_protein_qvalue=1 --rt_unit={rt_unit}" @@ -183,6 +185,7 @@ def test_osw_analysis_libExport(input_strategy, temp_folder, regtest, calib, rt_ f"{temp_folder}/test_lib.tsv", ) + def test_osw_unscored(input_strategy, temp_folder, regtest): """Test export of unscored OSW data""" cmd = f"pyprophet export tsv {input_strategy['cmd_prefix']} --out={temp_folder}/test_data.tsv --format=legacy_merged" @@ -275,30 +278,31 @@ def test_parquet_export_scored_osw(test_data_osw, temp_folder, regtest): """Test exporting scored OSW with SCORE_ tables to parquet format""" # Score at MS2 level cmd = f"pyprophet score --in={test_data_osw} --level=ms2 --test --pi0_lambda=0.001 0 0 --ss_iteration_fdr=0.02 && " - + # Infer peptide level with global context cmd += f"pyprophet infer peptide --pi0_lambda=0.001 0 0 --in={test_data_osw} --context=global && " - + # Infer protein level with global context cmd += f"pyprophet infer protein --pi0_lambda=0 0 0 --in={test_data_osw} --context=global && " - + # Export to parquet (should include SCORE_ tables) cmd += f"pyprophet export parquet --in={test_data_osw} --out={temp_folder}/test_data_scored.parquet" - + run_pyprophet_command(cmd, temp_folder) - + # Verify the parquet file exists and has data import pyarrow.parquet as pq + table = pq.read_table(f"{temp_folder}/test_data_scored.parquet") df = table.to_pandas() - + # Check that we have data assert len(df) > 0, "Exported parquet file should not be empty" - + # Check that score columns are present - score_columns = [col for col in df.columns if col.startswith('SCORE_')] + score_columns = [col for col in df.columns if col.startswith("SCORE_")] assert len(score_columns) > 0, "Exported parquet should contain SCORE_ columns" - + print(f"Exported {len(df)} rows with {len(df.columns)} columns", file=regtest) print(f"Score columns found: {sorted(score_columns)}", file=regtest) print(df.head(10).sort_index(axis=1), file=regtest) @@ -308,36 +312,42 @@ def test_parquet_export_no_transition_data(test_data_osw, temp_folder, regtest): """Test exporting parquet without transition data using --no-include_transition_data flag""" # Score at MS2 level cmd = f"pyprophet score --in={test_data_osw} --level=ms2 --test --pi0_lambda=0.001 0 0 --ss_iteration_fdr=0.02 && " - + # Infer peptide level with global context cmd += f"pyprophet infer peptide --pi0_lambda=0.001 0 0 --in={test_data_osw} --context=global && " - + # Infer protein level with global context cmd += f"pyprophet infer protein --pi0_lambda=0 0 0 --in={test_data_osw} --context=global && " - + # Export to parquet without transition data cmd += f"pyprophet export parquet --in={test_data_osw} --out={temp_folder}/test_data_no_transition.parquet --no-include_transition_data" - + run_pyprophet_command(cmd, temp_folder) - + # Verify the parquet file exists and has data import pyarrow.parquet as pq + table = pq.read_table(f"{temp_folder}/test_data_no_transition.parquet") df = table.to_pandas() - + # Check that we have data assert len(df) > 0, "Exported parquet file should not be empty" - + # Check that transition-specific columns are NOT present # transition_columns = [col for col in df.columns if 'TRANSITION' in col.upper()] # assert len(transition_columns) == 0, "Exported parquet should not contain TRANSITION columns when --no-include_transition_data is used" - assert df['TRANSITION_ID'].isnull().all(), "TRANSITION_ID column should be empty when --no-include_transition_data is used" - + assert df["TRANSITION_ID"].isnull().all(), ( + "TRANSITION_ID column should be empty when --no-include_transition_data is used" + ) + # Check that score columns are present - score_columns = [col for col in df.columns if col.startswith('SCORE_')] + score_columns = [col for col in df.columns if col.startswith("SCORE_")] assert len(score_columns) > 0, "Exported parquet should contain SCORE_ columns" - - print(f"Exported {len(df)} rows with {len(df.columns)} columns (no transition data)", file=regtest) + + print( + f"Exported {len(df)} rows with {len(df.columns)} columns (no transition data)", + file=regtest, + ) print(f"Score columns found: {sorted(score_columns)}", file=regtest) print(df.head(10).sort_index(axis=1), file=regtest) @@ -346,47 +356,58 @@ def test_parquet_export_split_format(test_data_osw, temp_folder, regtest): """Test exporting to split parquet format with score data""" # Score at MS2 level cmd = f"pyprophet score --in={test_data_osw} --level=ms2 --test --pi0_lambda=0.001 0 0 --ss_iteration_fdr=0.02 && " - + # Infer peptide level with global context cmd += f"pyprophet infer peptide --pi0_lambda=0.001 0 0 --in={test_data_osw} --context=global && " - + # Infer protein level with global context cmd += f"pyprophet infer protein --pi0_lambda=0 0 0 --in={test_data_osw} --context=global && " - + # Export to split parquet format cmd += f"pyprophet export parquet --in={test_data_osw} --out={temp_folder}/test_data_split --split_transition_data" - + run_pyprophet_command(cmd, temp_folder) - + # Verify the directory exists and contains parquet files import pyarrow.parquet as pq + split_dir = Path(temp_folder) / "test_data_split" assert split_dir.exists(), "Split parquet directory should exist" - + precursor_file = split_dir / "precursors_features.parquet" transition_file = split_dir / "transition_features.parquet" - + assert precursor_file.exists(), "precursors_features.parquet should exist" assert transition_file.exists(), "transition_features.parquet should exist" - + # Read precursor data precursor_table = pq.read_table(str(precursor_file)) precursor_df = precursor_table.to_pandas() - + # Read transition data transition_table = pq.read_table(str(transition_file)) transition_df = transition_table.to_pandas() - + # Check that we have data in both files assert len(precursor_df) > 0, "Precursor parquet file should not be empty" assert len(transition_df) > 0, "Transition parquet file should not be empty" - + # Check that score columns are present in precursor file - precursor_score_columns = [col for col in precursor_df.columns if col.startswith('SCORE_')] - assert len(precursor_score_columns) > 0, "Precursor parquet should contain SCORE_ columns" - - print(f"Precursor data: {len(precursor_df)} rows with {len(precursor_df.columns)} columns", file=regtest) - print(f"Transition data: {len(transition_df)} rows with {len(transition_df.columns)} columns", file=regtest) + precursor_score_columns = [ + col for col in precursor_df.columns if col.startswith("SCORE_") + ] + assert len(precursor_score_columns) > 0, ( + "Precursor parquet should contain SCORE_ columns" + ) + + print( + f"Precursor data: {len(precursor_df)} rows with {len(precursor_df.columns)} columns", + file=regtest, + ) + print( + f"Transition data: {len(transition_df)} rows with {len(transition_df.columns)} columns", + file=regtest, + ) print(f"Precursor score columns: {sorted(precursor_score_columns)}", file=regtest) print("Precursor data sample:", file=regtest) print(precursor_df.head(5).sort_index(axis=1), file=regtest) @@ -432,3 +453,104 @@ def test_parquet_export_with_ipf(test_data_osw, temp_folder, regtest): print(f"SCORE_IPF columns found: {sorted(ipf_columns)}", file=regtest) print("Sample data with IPF scores:", file=regtest) print(df[['FEATURE_ID'] + ipf_columns].head(10).sort_index(axis=1), file=regtest) + + +# ================== FEATURE SCORES EXPORT TESTS ================== +def test_feature_scores_unscored_osw(test_data_osw, temp_folder, regtest): + """Test exporting feature scores from unscored OSW file""" + cmd = f"pyprophet export feature-scores --in={test_data_osw} --out={temp_folder}/feature_scores.pdf" + + run_pyprophet_command(cmd, temp_folder) + + # Check that output PDF files were created + output_files = list(temp_folder.glob("*.pdf")) + assert len(output_files) > 0, "Expected at least one PDF file to be created" + + print(f"Created {len(output_files)} PDF file(s):", file=regtest) + for f in sorted(output_files): + print(f" - {f.name}", file=regtest) + + +def test_feature_scores_scored_osw(test_data_osw, temp_folder, regtest): + """Test exporting feature scores from scored OSW file with SCORE tables""" + # Score at MS2 level first + cmd = f"pyprophet score --in={test_data_osw} --level=ms2 --test --pi0_lambda=0.001 0 0 --ss_iteration_fdr=0.02 && " + + # Export feature scores (should detect SCORE_MS2 table) + cmd += f"pyprophet export feature-scores --in={test_data_osw} --out={temp_folder}/feature_scores.pdf" + + run_pyprophet_command(cmd, temp_folder) + + # Check that output PDF files were created + output_files = list(temp_folder.glob("*.pdf")) + assert len(output_files) > 0, "Expected at least one PDF file to be created" + + print(f"Created {len(output_files)} PDF file(s) from scored OSW:", file=regtest) + for f in sorted(output_files): + print(f" - {f.name}", file=regtest) + + +def test_feature_scores_parquet_with_scores(test_data_osw, temp_folder, regtest): + """Test exporting feature scores from Parquet file with SCORE columns""" + # Score and export to parquet + cmd = f"pyprophet score --in={test_data_osw} --level=ms2 --test --pi0_lambda=0.001 0 0 --ss_iteration_fdr=0.02 && " + cmd += f"pyprophet export parquet --in={test_data_osw} --out={temp_folder}/test_data_scored.parquet && " + + # Export feature scores from parquet + cmd += f"pyprophet export feature-scores --in={temp_folder}/test_data_scored.parquet --out={temp_folder}/feature_scores.pdf" + + run_pyprophet_command(cmd, temp_folder) + + # Check that output PDF was created + pdf_file = temp_folder / "feature_scores.pdf" + assert pdf_file.exists(), "Expected feature_scores.pdf to be created" + + print(f"Successfully created feature scores from Parquet with SCORE columns", file=regtest) + + +def test_feature_scores_split_parquet_with_scores(test_data_osw, temp_folder, regtest): + """Test exporting feature scores from split Parquet directory with SCORE columns""" + # Score and export to split parquet + cmd = f"pyprophet score --in={test_data_osw} --level=ms2 --test --pi0_lambda=0.001 0 0 --ss_iteration_fdr=0.02 && " + cmd += f"pyprophet export parquet --in={test_data_osw} --out={temp_folder}/test_data_split --split_transition_data && " + + # Export feature scores from split parquet + cmd += f"pyprophet export feature-scores --in={temp_folder}/test_data_split --out={temp_folder}/feature_scores.pdf" + + run_pyprophet_command(cmd, temp_folder) + + # Check that output PDF was created + pdf_file = temp_folder / "feature_scores.pdf" + assert pdf_file.exists(), "Expected feature_scores.pdf to be created" + + print(f"Successfully created feature scores from split Parquet with SCORE columns", file=regtest) + + +def test_feature_scores_ms1_ms2_transition(test_data_osw, temp_folder, regtest): + """Test exporting feature scores with MS1, MS2, and transition level scoring""" + # Score at all levels + cmd = f"pyprophet score --in={test_data_osw} --level=ms1 --test --pi0_lambda=0.1 0 0 --ss_iteration_fdr=0.02 && " + cmd += f"pyprophet score --in={test_data_osw} --level=ms2 --test --pi0_lambda=0.001 0 0 --ss_iteration_fdr=0.02 && " + cmd += f"pyprophet score --in={test_data_osw} --level=transition --test --pi0_lambda=0.1 0 0 --ss_iteration_fdr=0.02 && " + + # Export feature scores (should create ms1, ms2, and transition PDFs) + cmd += f"pyprophet export feature-scores --in={test_data_osw} --out={temp_folder}/feature_scores.pdf" + + run_pyprophet_command(cmd, temp_folder) + + # Check that output PDF files were created for all levels + output_files = list(temp_folder.glob("*.pdf")) + assert len(output_files) >= 3, "Expected at least 3 PDF files (ms1, ms2, transition)" + + # Check for specific files + ms1_files = [f for f in output_files if 'ms1' in f.name.lower()] + ms2_files = [f for f in output_files if 'ms2' in f.name.lower()] + transition_files = [f for f in output_files if 'transition' in f.name.lower()] + + print(f"Created {len(output_files)} PDF file(s) from multi-level scoring:", file=regtest) + print(f" MS1 files: {len(ms1_files)}", file=regtest) + print(f" MS2 files: {len(ms2_files)}", file=regtest) + print(f" Transition files: {len(transition_files)}", file=regtest) + + for f in sorted(output_files): + print(f" - {f.name}", file=regtest)