b1-method 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- b1_method-0.1.0/PKG-INFO +68 -0
- b1_method-0.1.0/README.md +49 -0
- b1_method-0.1.0/b1_method/__init__.py +26 -0
- b1_method-0.1.0/b1_method/__main__.py +5 -0
- b1_method-0.1.0/b1_method/cli.py +245 -0
- b1_method-0.1.0/b1_method/core.py +373 -0
- b1_method-0.1.0/b1_method/examples/brand_alignment.csv +10 -0
- b1_method-0.1.0/b1_method/examples/brand_sources.csv +5 -0
- b1_method-0.1.0/b1_method/examples/emotion_alignment.csv +11 -0
- b1_method-0.1.0/b1_method/examples/emotion_sources.csv +6 -0
- b1_method-0.1.0/b1_method/examples/intelligence_alignment.csv +17 -0
- b1_method-0.1.0/b1_method/examples/intelligence_sources.csv +6 -0
- b1_method-0.1.0/b1_method/examples/personality_alignment.csv +7 -0
- b1_method-0.1.0/b1_method/examples/personality_sources.csv +7 -0
- b1_method-0.1.0/b1_method/io.py +356 -0
- b1_method-0.1.0/b1_method/temporal.py +433 -0
- b1_method-0.1.0/b1_method/tests/__init__.py +1 -0
- b1_method-0.1.0/b1_method/tests/test_core.py +102 -0
- b1_method-0.1.0/b1_method.egg-info/PKG-INFO +68 -0
- b1_method-0.1.0/b1_method.egg-info/SOURCES.txt +23 -0
- b1_method-0.1.0/b1_method.egg-info/dependency_links.txt +1 -0
- b1_method-0.1.0/b1_method.egg-info/entry_points.txt +2 -0
- b1_method-0.1.0/b1_method.egg-info/top_level.txt +1 -0
- b1_method-0.1.0/pyproject.toml +44 -0
- b1_method-0.1.0/setup.cfg +4 -0
b1_method-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: b1-method
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Domain-independent convergent derivation of canonical basis vectors from heterogeneous observations
|
|
5
|
+
Author-email: "Kafkas M. Caprazli" <caprazli@cosmologic.pro>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://cosmologic.pro
|
|
8
|
+
Keywords: measurement theory,dimensional analysis,convergent derivation,psychometrics,factor analysis,topology
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# b1-method
|
|
21
|
+
|
|
22
|
+
Domain-independent convergent derivation of canonical basis vectors from K independent sources.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install b1-method
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from b1_method import B1Analysis
|
|
34
|
+
|
|
35
|
+
alignment = {
|
|
36
|
+
"Extraversion": ["Y", "Y", "Y", "Y", "Y", "Y"],
|
|
37
|
+
"Agreeableness": ["Y", "Y", "Y*", "Y", "Y", "Y"],
|
|
38
|
+
"Conscientiousness": ["Y", "Y", "Y", "Y", "Y", "Y"],
|
|
39
|
+
"Neuroticism": ["Y", "Y", "Y*", "N*", "Y", "Y"],
|
|
40
|
+
"Openness": ["Y", "Y", "Y", "N*", "Y", "Y"],
|
|
41
|
+
"Honesty-Humility": ["N", "N", "Y", "Y*", "N", "N"],
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
result = B1Analysis(alignment, domain="Personality").run()
|
|
45
|
+
B1Analysis.print_report(result)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## CLI
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
b1-method run alignment.csv --sources sources.csv --domain Personality
|
|
52
|
+
b1-method temporal alignment.csv --sources sources.csv --domain Personality
|
|
53
|
+
b1-method version
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## How It Works
|
|
57
|
+
|
|
58
|
+
Given K independent source assessments proposing competing dimensional structures for the same domain, B1 produces a tier-classified, independence-verified basis:
|
|
59
|
+
|
|
60
|
+
- **Tier 1** (count >= ceil(2K/3)): Strong convergence — confirmed basis vectors
|
|
61
|
+
- **Tier 2** (count >= ceil(K/3)): Partial convergence — contested candidates
|
|
62
|
+
- **Tier 3** (count < ceil(K/3)): Weak/non-convergent — insufficient support
|
|
63
|
+
|
|
64
|
+
The number of Tier 1 candidates is a **lower bound** on the domain's dimensionality.
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# b1-method
|
|
2
|
+
|
|
3
|
+
Domain-independent convergent derivation of canonical basis vectors from K independent sources.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install b1-method
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from b1_method import B1Analysis
|
|
15
|
+
|
|
16
|
+
alignment = {
|
|
17
|
+
"Extraversion": ["Y", "Y", "Y", "Y", "Y", "Y"],
|
|
18
|
+
"Agreeableness": ["Y", "Y", "Y*", "Y", "Y", "Y"],
|
|
19
|
+
"Conscientiousness": ["Y", "Y", "Y", "Y", "Y", "Y"],
|
|
20
|
+
"Neuroticism": ["Y", "Y", "Y*", "N*", "Y", "Y"],
|
|
21
|
+
"Openness": ["Y", "Y", "Y", "N*", "Y", "Y"],
|
|
22
|
+
"Honesty-Humility": ["N", "N", "Y", "Y*", "N", "N"],
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
result = B1Analysis(alignment, domain="Personality").run()
|
|
26
|
+
B1Analysis.print_report(result)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## CLI
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
b1-method run alignment.csv --sources sources.csv --domain Personality
|
|
33
|
+
b1-method temporal alignment.csv --sources sources.csv --domain Personality
|
|
34
|
+
b1-method version
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## How It Works
|
|
38
|
+
|
|
39
|
+
Given K independent source assessments proposing competing dimensional structures for the same domain, B1 produces a tier-classified, independence-verified basis:
|
|
40
|
+
|
|
41
|
+
- **Tier 1** (count >= ceil(2K/3)): Strong convergence — confirmed basis vectors
|
|
42
|
+
- **Tier 2** (count >= ceil(K/3)): Partial convergence — contested candidates
|
|
43
|
+
- **Tier 3** (count < ceil(K/3)): Weak/non-convergent — insufficient support
|
|
44
|
+
|
|
45
|
+
The number of Tier 1 candidates is a **lower bound** on the domain's dimensionality.
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
MIT
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
b1-method: Domain-Independent Convergent Derivation of Canonical Basis Vectors
|
|
3
|
+
===============================================================================
|
|
4
|
+
|
|
5
|
+
Given K independent sources proposing competing dimensional structures for the
|
|
6
|
+
same domain, B1 produces a tier-classified, independence-verified, composite-
|
|
7
|
+
checked basis — a lower bound on the manifold's topological complexity.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
from b1_method import B1Analysis
|
|
11
|
+
|
|
12
|
+
analysis = B1Analysis.from_csv("sources.csv")
|
|
13
|
+
result = analysis.run()
|
|
14
|
+
result.print_report()
|
|
15
|
+
|
|
16
|
+
CLI:
|
|
17
|
+
b1-method run sources.csv
|
|
18
|
+
b1-method temporal sources.csv
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
__version__ = "0.1.0"
|
|
22
|
+
|
|
23
|
+
from b1_method.core import B1Analysis, B1Result
|
|
24
|
+
from b1_method.temporal import TemporalSimulation
|
|
25
|
+
|
|
26
|
+
__all__ = ["B1Analysis", "B1Result", "TemporalSimulation"]
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""
|
|
2
|
+
b1_method.cli — Command-line interface for the B1 method.
|
|
3
|
+
|
|
4
|
+
Entry points:
|
|
5
|
+
b1-method run <alignment.csv> [--sources <sources.csv>] [--domain <name>]
|
|
6
|
+
b1-method temporal <alignment.csv> --sources <sources.csv> [--ground-truth <gt.json>]
|
|
7
|
+
b1-method version
|
|
8
|
+
|
|
9
|
+
Designed for ``python -m b1_method`` or as a console_scripts entry point.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import argparse
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
from b1_method import __version__
|
|
18
|
+
from b1_method.core import B1Analysis
|
|
19
|
+
from b1_method.temporal import TemporalSimulation, print_temporal_report
|
|
20
|
+
from b1_method.io import (
|
|
21
|
+
load_alignment_csv,
|
|
22
|
+
load_sources_csv,
|
|
23
|
+
load_combined_csv,
|
|
24
|
+
save_report_json,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _build_parser():
|
|
29
|
+
"""Build the argument parser with subcommands."""
|
|
30
|
+
parser = argparse.ArgumentParser(
|
|
31
|
+
prog="b1-method",
|
|
32
|
+
description=(
|
|
33
|
+
"B1 Convergent Derivation Method: domain-independent derivation "
|
|
34
|
+
"of canonical basis vectors from K independent sources."
|
|
35
|
+
),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
39
|
+
|
|
40
|
+
# --- run ---
|
|
41
|
+
run_parser = subparsers.add_parser(
|
|
42
|
+
"run",
|
|
43
|
+
help="Run B1 analysis on an alignment matrix.",
|
|
44
|
+
description=(
|
|
45
|
+
"Load an alignment CSV (and optional sources CSV), run the full "
|
|
46
|
+
"B1 pipeline (C1-C5), and print the report."
|
|
47
|
+
),
|
|
48
|
+
)
|
|
49
|
+
run_parser.add_argument(
|
|
50
|
+
"alignment_csv",
|
|
51
|
+
help="Path to the alignment matrix CSV file.",
|
|
52
|
+
)
|
|
53
|
+
run_parser.add_argument(
|
|
54
|
+
"--sources",
|
|
55
|
+
dest="sources_csv",
|
|
56
|
+
default=None,
|
|
57
|
+
help="Path to the sources metadata CSV file (optional).",
|
|
58
|
+
)
|
|
59
|
+
run_parser.add_argument(
|
|
60
|
+
"--domain",
|
|
61
|
+
default=None,
|
|
62
|
+
help="Domain name for the report header (e.g. 'Personality').",
|
|
63
|
+
)
|
|
64
|
+
run_parser.add_argument(
|
|
65
|
+
"--output", "-o",
|
|
66
|
+
default=None,
|
|
67
|
+
help="Path to save the JSON report (optional).",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# --- temporal ---
|
|
71
|
+
temporal_parser = subparsers.add_parser(
|
|
72
|
+
"temporal",
|
|
73
|
+
help="Run temporal holdout simulation.",
|
|
74
|
+
description=(
|
|
75
|
+
"Feed sources to B1 in chronological order and compare "
|
|
76
|
+
"intermediate verdicts against ground-truth findings."
|
|
77
|
+
),
|
|
78
|
+
)
|
|
79
|
+
temporal_parser.add_argument(
|
|
80
|
+
"alignment_csv",
|
|
81
|
+
help="Path to the alignment matrix CSV file.",
|
|
82
|
+
)
|
|
83
|
+
temporal_parser.add_argument(
|
|
84
|
+
"--sources",
|
|
85
|
+
dest="sources_csv",
|
|
86
|
+
required=True,
|
|
87
|
+
help="Path to the sources metadata CSV file (required for temporal).",
|
|
88
|
+
)
|
|
89
|
+
temporal_parser.add_argument(
|
|
90
|
+
"--ground-truth",
|
|
91
|
+
dest="ground_truth",
|
|
92
|
+
default=None,
|
|
93
|
+
help=(
|
|
94
|
+
"Path to a JSON file mapping ground-truth questions to boolean "
|
|
95
|
+
"answers. If omitted, simulation runs without accuracy scoring."
|
|
96
|
+
),
|
|
97
|
+
)
|
|
98
|
+
temporal_parser.add_argument(
|
|
99
|
+
"--domain",
|
|
100
|
+
default=None,
|
|
101
|
+
help="Domain name for the report header.",
|
|
102
|
+
)
|
|
103
|
+
temporal_parser.add_argument(
|
|
104
|
+
"--output", "-o",
|
|
105
|
+
default=None,
|
|
106
|
+
help="Path to save the JSON report (optional).",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# --- version ---
|
|
110
|
+
subparsers.add_parser(
|
|
111
|
+
"version",
|
|
112
|
+
help="Print the package version.",
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
return parser
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _cmd_run(args):
|
|
119
|
+
"""Execute the 'run' subcommand."""
|
|
120
|
+
# Load alignment data
|
|
121
|
+
alignment, source_names = load_alignment_csv(args.alignment_csv)
|
|
122
|
+
|
|
123
|
+
# Load sources if provided
|
|
124
|
+
sources = None
|
|
125
|
+
if args.sources_csv:
|
|
126
|
+
sources = load_sources_csv(args.sources_csv)
|
|
127
|
+
|
|
128
|
+
# Build and run analysis
|
|
129
|
+
domain = args.domain or _guess_domain(args.alignment_csv)
|
|
130
|
+
analysis = B1Analysis(
|
|
131
|
+
alignment=alignment,
|
|
132
|
+
sources=sources,
|
|
133
|
+
domain=domain,
|
|
134
|
+
)
|
|
135
|
+
result = analysis.run()
|
|
136
|
+
|
|
137
|
+
# Print report
|
|
138
|
+
B1Analysis.print_report(result)
|
|
139
|
+
|
|
140
|
+
# Save JSON if requested
|
|
141
|
+
if args.output:
|
|
142
|
+
save_report_json(result, args.output)
|
|
143
|
+
print(f"\nReport saved to: {args.output}")
|
|
144
|
+
|
|
145
|
+
return 0
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _cmd_temporal(args):
|
|
149
|
+
"""Execute the 'temporal' subcommand."""
|
|
150
|
+
# Load alignment and sources
|
|
151
|
+
alignment, source_names = load_alignment_csv(args.alignment_csv)
|
|
152
|
+
source_meta = load_sources_csv(args.sources_csv)
|
|
153
|
+
|
|
154
|
+
# Build temporal source dicts: merge metadata with per-source factor verdicts
|
|
155
|
+
# Alignment is {candidate: [s1_val, s2_val, ...]}, sources are ordered by CSV column
|
|
156
|
+
# TemporalSimulation expects each source dict to have a "factors" key
|
|
157
|
+
candidates = list(alignment.keys())
|
|
158
|
+
temporal_sources = []
|
|
159
|
+
for i, meta in enumerate(source_meta):
|
|
160
|
+
factors = {}
|
|
161
|
+
for candidate in candidates:
|
|
162
|
+
row = alignment[candidate]
|
|
163
|
+
factors[candidate] = row[i] if i < len(row) else "N"
|
|
164
|
+
temporal_sources.append({**meta, "factors": factors})
|
|
165
|
+
|
|
166
|
+
# Load ground truth if provided
|
|
167
|
+
ground_truth = {}
|
|
168
|
+
if args.ground_truth:
|
|
169
|
+
gt_path = os.path.expanduser(args.ground_truth)
|
|
170
|
+
if not os.path.isfile(gt_path):
|
|
171
|
+
print(f"Error: ground-truth file not found: {gt_path}",
|
|
172
|
+
file=sys.stderr)
|
|
173
|
+
return 1
|
|
174
|
+
with open(gt_path, "r", encoding="utf-8") as f:
|
|
175
|
+
ground_truth = json.load(f)
|
|
176
|
+
|
|
177
|
+
# Build and run simulation
|
|
178
|
+
domain = args.domain or _guess_domain(args.alignment_csv)
|
|
179
|
+
sim = TemporalSimulation(
|
|
180
|
+
domain_name=domain,
|
|
181
|
+
sources=temporal_sources,
|
|
182
|
+
ground_truth=ground_truth,
|
|
183
|
+
candidates=candidates,
|
|
184
|
+
)
|
|
185
|
+
result = sim.run()
|
|
186
|
+
|
|
187
|
+
# Print report
|
|
188
|
+
print_temporal_report(result)
|
|
189
|
+
|
|
190
|
+
# Save JSON if requested
|
|
191
|
+
if args.output:
|
|
192
|
+
save_report_json(result, args.output)
|
|
193
|
+
print(f"\nReport saved to: {args.output}")
|
|
194
|
+
|
|
195
|
+
return 0
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _cmd_version():
|
|
199
|
+
"""Execute the 'version' subcommand."""
|
|
200
|
+
print(f"b1-method {__version__}")
|
|
201
|
+
return 0
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _guess_domain(filepath):
|
|
205
|
+
"""Guess the domain name from a file path."""
|
|
206
|
+
basename = os.path.splitext(os.path.basename(filepath))[0]
|
|
207
|
+
# Strip common prefixes/suffixes
|
|
208
|
+
for prefix in ("b1_", "alignment_", "sources_"):
|
|
209
|
+
if basename.lower().startswith(prefix):
|
|
210
|
+
basename = basename[len(prefix):]
|
|
211
|
+
return basename.replace("_", " ").title()
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def main():
|
|
215
|
+
"""CLI entry point for the B1 method package."""
|
|
216
|
+
parser = _build_parser()
|
|
217
|
+
args = parser.parse_args()
|
|
218
|
+
|
|
219
|
+
if args.command is None:
|
|
220
|
+
parser.print_help()
|
|
221
|
+
return 1
|
|
222
|
+
|
|
223
|
+
try:
|
|
224
|
+
if args.command == "run":
|
|
225
|
+
return _cmd_run(args)
|
|
226
|
+
elif args.command == "temporal":
|
|
227
|
+
return _cmd_temporal(args)
|
|
228
|
+
elif args.command == "version":
|
|
229
|
+
return _cmd_version()
|
|
230
|
+
else:
|
|
231
|
+
parser.print_help()
|
|
232
|
+
return 1
|
|
233
|
+
except FileNotFoundError as e:
|
|
234
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
235
|
+
return 1
|
|
236
|
+
except ValueError as e:
|
|
237
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
238
|
+
return 1
|
|
239
|
+
except KeyboardInterrupt:
|
|
240
|
+
print("\nInterrupted.", file=sys.stderr)
|
|
241
|
+
return 130
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
if __name__ == "__main__":
|
|
245
|
+
sys.exit(main() or 0)
|