Skip to content

Metadata

neureptrace.metadata

add_binary_label(metadata, *, source_column, positive_pattern, label_column, negative_pattern=None, positive_label='positive', negative_label='negative', case_sensitive=False)

Add a binary label column by matching text patterns in an existing column.

When negative_pattern is omitted, every non-null source value that does not match positive_pattern receives the negative label. When negative_pattern is provided, unmatched rows receive missing labels and rows that match both patterns keep the positive label.

Source code in src/neureptrace/metadata.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
def add_binary_label(
    metadata: pd.DataFrame,
    *,
    source_column: str,
    positive_pattern: str,
    label_column: str,
    negative_pattern: str | None = None,
    positive_label: str = "positive",
    negative_label: str = "negative",
    case_sensitive: bool = False,
) -> pd.DataFrame:
    """Add a binary label column by matching text patterns in an existing column.

    When ``negative_pattern`` is omitted, every non-null source value that does
    not match ``positive_pattern`` receives the negative label. When
    ``negative_pattern`` is provided, unmatched rows receive missing labels and
    rows that match both patterns keep the positive label.
    """
    source_column = _non_empty_text(source_column, name="source_column")
    label_column = _non_empty_text(label_column, name="label_column")
    case_sensitive = _boolean(case_sensitive, name="case_sensitive")
    positive_regex = _compile_pattern(positive_pattern, name="positive_pattern", case_sensitive=case_sensitive)
    negative_regex = None if negative_pattern is None else _compile_pattern(negative_pattern, name="negative_pattern", case_sensitive=case_sensitive)
    positive_label, negative_label = _validate_binary_labels(positive_label, negative_label)

    if source_column not in metadata.columns:
        raise ValueError(f"Source column '{source_column}' not found in metadata.")
    source = metadata[source_column]
    if isinstance(source, pd.DataFrame):
        raise ValueError(f"Source column '{source_column}' must identify exactly one metadata column.")
    if label_column in metadata.columns:
        raise ValueError(f"Label column '{label_column}' already exists.")

    source = source.astype("string")
    positive = source.str.contains(positive_regex, regex=True, na=False)
    if negative_regex is None:
        negative = source.notna() & ~positive
    else:
        negative = source.str.contains(negative_regex, regex=True, na=False) & ~positive

    labeled = metadata.copy()
    labeled[label_column] = pd.NA
    labeled.loc[positive, label_column] = positive_label
    labeled.loc[negative, label_column] = negative_label
    return labeled

prepare_binary_metadata(events_csv, out_path, *, source_column, positive_pattern, label_column, negative_pattern=None, positive_label='positive', negative_label='negative', case_sensitive=False)

Load metadata, add a binary label, and write the result as CSV.

Source code in src/neureptrace/metadata.py
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
def prepare_binary_metadata(
    events_csv: Path,
    out_path: Path,
    *,
    source_column: str,
    positive_pattern: str,
    label_column: str,
    negative_pattern: str | None = None,
    positive_label: str = "positive",
    negative_label: str = "negative",
    case_sensitive: bool = False,
) -> pd.DataFrame:
    """Load metadata, add a binary label, and write the result as CSV."""
    events_csv = Path(events_csv)
    out_path = Path(out_path)
    if events_csv.resolve(strict=False) == out_path.resolve(strict=False):
        raise ValueError("out_path must not overwrite events_csv.")

    metadata = pd.read_csv(events_csv)
    labeled = add_binary_label(
        metadata,
        source_column=source_column,
        positive_pattern=positive_pattern,
        negative_pattern=negative_pattern,
        label_column=label_column,
        positive_label=positive_label,
        negative_label=negative_label,
        case_sensitive=case_sensitive,
    )
    out_path.parent.mkdir(parents=True, exist_ok=True)
    labeled.to_csv(out_path, index=False)
    return labeled