Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions backend/demo_ttfr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from ttfr_estimator import estimate_ttfr

print("=" * 60)
print("TTFR Estimator Demo")
print("=" * 60)

test_cases = [
{
"name": "OpenNeuro fMRI Dataset",
"datasource_id": "scr_005031_openneuro",
"metadata": {"description": "Large-scale fMRI study with 200 participants investigating cognitive control"},
"content": "BIDS-formatted neuroimaging data"
},
{
"name": "DANDI Electrophysiology",
"datasource_id": "scr_017571_dandi",
"metadata": {"description": "Multi-electrode array recordings from mouse visual cortex"},
"content": "NWB format neural recordings"
},
{
"name": "Multimodal Dataset",
"datasource_id": None,
"metadata": {"description": "Combined fMRI and electrophysiology study of sensory processing"},
"content": "Multimodal neuroimaging and neural recordings"
},
{
"name": "Simple Morphology Database",
"datasource_id": "scr_002145_neuromorpho_modelimage",
"metadata": {"description": "Curated collection of neuron morphology reconstructions"},
"content": "SWC format morphology files"
}
]

for case in test_cases:
print(f"\n{'─' * 60}")
print(f"Dataset: {case['name']}")
print(f"{'─' * 60}")

estimate = estimate_ttfr(
datasource_id=case["datasource_id"],
metadata=case["metadata"],
content=case["content"]
)

print(f"\nTime to First Result: {estimate.total}")
print(f"\nBreakdown:")
print(f" - Access & setup: {estimate.access_setup}")
print(f" - Preprocessing: {estimate.preprocessing}")
print(f" - First output: {estimate.first_output}")
print(f"\nAssumptions:")
for assumption in estimate.assumptions:
print(f" - {assumption}")

print(f"\nJSON format:")
import json
Copy link

Copilot AI Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The json module is imported inside the loop on line 55, which means it will be imported multiple times unnecessarily. Move the import statement to the top of the file with other imports for better performance and following Python best practices.

Copilot uses AI. Check for mistakes.
print(json.dumps(estimate.to_dict(), indent=2))

print(f"\n{'=' * 60}")
print("Demo Complete!")
print("=" * 60)
153 changes: 153 additions & 0 deletions backend/test_ttfr_estimator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import pytest
from ttfr_estimator import (
estimate_ttfr,
AccessType,
ModalityComplexity,
FormatType,
infer_modality_from_keywords,
detect_multimodal,
assess_documentation_quality
)
Comment on lines +2 to +10
Copy link

Copilot AI Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'AccessType' is not used.
Import of 'FormatType' is not used.

Copilot uses AI. Check for mistakes.


class TestModalityInference:
def test_infer_low_complexity(self):
assert infer_modality_from_keywords("computational model simulation") == ModalityComplexity.LOW
assert infer_modality_from_keywords("neuron morphology database") == ModalityComplexity.LOW

def test_infer_medium_complexity(self):
assert infer_modality_from_keywords("microscopy images") == ModalityComplexity.MEDIUM
assert infer_modality_from_keywords("electrophysiology recordings") == ModalityComplexity.MEDIUM

def test_infer_high_complexity(self):
assert infer_modality_from_keywords("fMRI BOLD imaging") == ModalityComplexity.HIGH
assert infer_modality_from_keywords("MRI brain scans") == ModalityComplexity.HIGH

def test_infer_very_high_complexity(self):
assert infer_modality_from_keywords("multimodal neuroimaging dataset") == ModalityComplexity.VERY_HIGH

def test_empty_input(self):
assert infer_modality_from_keywords("") == ModalityComplexity.MEDIUM
assert infer_modality_from_keywords(None) == ModalityComplexity.MEDIUM


class TestMultimodalDetection:
def test_detect_multimodal_positive(self):
assert detect_multimodal("multimodal imaging and electrophysiology") == True
assert detect_multimodal("combined MRI and PET") == True
assert detect_multimodal("fMRI and behavioral data") == True

def test_detect_multimodal_negative(self):
assert detect_multimodal("fMRI imaging only") == False
assert detect_multimodal("microscopy images") == False

def test_empty_input(self):
assert detect_multimodal("") == False
assert detect_multimodal(None) == False


class TestDocumentationQuality:
def test_high_quality(self):
metadata = {
"description": "A" * 150,
"authors": ["Author 1"],
"license": "MIT",
"readme": "README.md"
}
assert assess_documentation_quality(metadata) == "high"

def test_medium_quality(self):
metadata = {
"description": "A" * 150,
"license": "MIT"
}
assert assess_documentation_quality(metadata) == "medium"

def test_low_quality(self):
metadata = {
"description": "Short"
}
assert assess_documentation_quality(metadata) == "low"

def test_empty_metadata(self):
assert assess_documentation_quality({}) == "low"


class TestTTFREstimation:
def test_openneuro_dataset(self):
estimate = estimate_ttfr(
datasource_id="scr_005031_openneuro",
metadata={"description": "fMRI study with 100 subjects"},
content="BIDS-formatted neuroimaging data"
)

assert estimate.total.min_days >= 0
assert estimate.total.max_days > estimate.total.min_days
assert "scr_005031_openneuro" in estimate.assumptions[0]

def test_dandi_dataset(self):
estimate = estimate_ttfr(
datasource_id="scr_017571_dandi",
metadata={"description": "Electrophysiology recordings from mouse cortex"},
content="NWB format neural recordings"
)

assert estimate.total.min_days >= 0
assert estimate.access_setup.min_days == 0.0

def test_unknown_datasource_simple(self):
estimate = estimate_ttfr(
metadata={"description": "Simple morphology database"},
content="Neuron morphology data"
)

assert estimate.total.min_days >= 0
assert "general estimates" in estimate.assumptions[0].lower()

def test_multimodal_dataset(self):
estimate = estimate_ttfr(
metadata={"description": "Combined fMRI and electrophysiology study"},
content="Multimodal neuroimaging and neural recordings"
)

assert any("multimodal" in a.lower() for a in estimate.assumptions)
assert estimate.preprocessing.max_days > 2.0

def test_approval_required(self):
estimate = estimate_ttfr(
datasource_id="scr_005069_brainminds"
)

assert estimate.access_setup.min_days >= 1.0

def test_to_dict_conversion(self):
estimate = estimate_ttfr(datasource_id="scr_007271_modeldb_models")
result = estimate.to_dict()

assert "total" in result
assert "breakdown" in result
assert "assumptions" in result
assert "display" in result["total"]
assert isinstance(result["assumptions"], list)


class TestTimeRangeFormatting:
def test_format_hours(self):
estimate = estimate_ttfr(
datasource_id="scr_002145_neuromorpho_modelimage"
)

total_str = str(estimate.total)
assert "days" in total_str or "hours" in total_str

def test_format_consistency(self):
estimate = estimate_ttfr(
datasource_id="scr_005031_openneuro"
)

result_dict = estimate.to_dict()
assert result_dict["total"]["display"] == str(estimate.total)


if __name__ == "__main__":
pytest.main([__file__, "-v"])
Comment on lines +151 to +153
Copy link

Copilot AI Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using pytest.main() in the main block is unnecessary. Tests should be run using the pytest command directly from the command line. This pattern adds pytest as a runtime import requirement when running the file directly, which is unconventional. Consider removing this block entirely.

Suggested change
if __name__ == "__main__":
pytest.main([__file__, "-v"])

Copilot uses AI. Check for mistakes.
Loading
Loading