vfbquery 0.4.1__py3-none-any.whl → 0.5.1__py3-none-any.whl
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.
- test/readme_parser.py +29 -27
- test/term_info_queries_test.py +46 -34
- test/test_dataset_template_queries.py +138 -0
- test/test_default_caching.py +89 -84
- test/test_examples_code.py +7 -0
- test/test_examples_diff.py +95 -172
- test/test_expression_overlaps.py +183 -0
- test/test_expression_pattern_fragments.py +123 -0
- test/test_images_neurons.py +152 -0
- test/test_images_that_develop_from.py +112 -0
- test/test_lineage_clones_in.py +190 -0
- test/test_nblast_queries.py +124 -0
- test/test_neuron_classes_fasciculating.py +187 -0
- test/test_neuron_inputs.py +193 -0
- test/test_neuron_neuron_connectivity.py +89 -0
- test/test_neuron_region_connectivity.py +117 -0
- test/test_neurons_part_here.py +203 -0
- test/test_new_owlery_queries.py +282 -0
- test/test_publication_transgene_queries.py +101 -0
- test/test_query_performance.py +739 -0
- test/test_similar_morphology.py +177 -0
- test/test_tracts_nerves_innervating.py +188 -0
- test/test_transcriptomics.py +223 -0
- vfbquery/__init__.py +47 -35
- vfbquery/cached_functions.py +772 -131
- vfbquery/neo4j_client.py +120 -0
- vfbquery/owlery_client.py +463 -0
- vfbquery/solr_cache_integration.py +34 -30
- vfbquery/solr_fetcher.py +1 -1
- vfbquery/solr_result_cache.py +338 -36
- vfbquery/term_info_queries.py +1 -1
- vfbquery/vfb_queries.py +2969 -627
- vfbquery-0.5.1.dist-info/METADATA +2806 -0
- vfbquery-0.5.1.dist-info/RECORD +40 -0
- vfbquery-0.4.1.dist-info/METADATA +0 -1315
- vfbquery-0.4.1.dist-info/RECORD +0 -19
- {vfbquery-0.4.1.dist-info → vfbquery-0.5.1.dist-info}/LICENSE +0 -0
- {vfbquery-0.4.1.dist-info → vfbquery-0.5.1.dist-info}/WHEEL +0 -0
- {vfbquery-0.4.1.dist-info → vfbquery-0.5.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Test suite for NeuronInputsTo query.
|
|
4
|
+
|
|
5
|
+
Tests the query that finds neurons with synapses into a specified neuron.
|
|
6
|
+
This implements the NeuronInputsTo query from the VFB XMI specification.
|
|
7
|
+
|
|
8
|
+
Test cases:
|
|
9
|
+
1. Query execution with known neuron
|
|
10
|
+
2. Schema generation and validation
|
|
11
|
+
3. Term info integration
|
|
12
|
+
4. Preview results validation (ribbon format)
|
|
13
|
+
5. Neurotransmitter information validation
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import unittest
|
|
17
|
+
import sys
|
|
18
|
+
import os
|
|
19
|
+
|
|
20
|
+
# Add the src directory to the path
|
|
21
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
|
22
|
+
|
|
23
|
+
from vfbquery.vfb_queries import (
|
|
24
|
+
get_individual_neuron_inputs,
|
|
25
|
+
NeuronInputsTo_to_schema,
|
|
26
|
+
get_term_info
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
class NeuronInputsTest(unittest.TestCase):
|
|
30
|
+
"""Test suite for NeuronInputsTo query"""
|
|
31
|
+
|
|
32
|
+
def setUp(self):
|
|
33
|
+
"""Set up test fixtures"""
|
|
34
|
+
# Test neuron: LPC1 (FlyEM-HB:1775513344) [VFB_jrchk00s]
|
|
35
|
+
self.test_neuron = "VFB_jrchk00s"
|
|
36
|
+
|
|
37
|
+
def test_query_execution(self):
|
|
38
|
+
"""Test that the query executes successfully"""
|
|
39
|
+
print(f"\n=== Testing NeuronInputsTo execution ===")
|
|
40
|
+
result = get_individual_neuron_inputs(
|
|
41
|
+
self.test_neuron,
|
|
42
|
+
return_dataframe=False,
|
|
43
|
+
limit=5
|
|
44
|
+
)
|
|
45
|
+
self.assertIsNotNone(result, "Query should return a result")
|
|
46
|
+
self.assertIsInstance(result, dict, "Result should be a dictionary")
|
|
47
|
+
print(f"Query returned {result.get('count', 0)} total results")
|
|
48
|
+
|
|
49
|
+
if 'rows' in result and len(result['rows']) > 0:
|
|
50
|
+
first_result = result['rows'][0]
|
|
51
|
+
self.assertIn('id', first_result, "Result should contain 'id' field")
|
|
52
|
+
self.assertIn('Neurotransmitter', first_result, "Result should contain 'Neurotransmitter' field")
|
|
53
|
+
self.assertIn('Weight', first_result, "Result should contain 'Weight' field")
|
|
54
|
+
print(f"First result: {first_result.get('Neurotransmitter', 'N/A')} (weight: {first_result.get('Weight', 0)})")
|
|
55
|
+
else:
|
|
56
|
+
print("No input neurons found (this is OK if none exist)")
|
|
57
|
+
|
|
58
|
+
def test_schema_generation(self):
|
|
59
|
+
"""Test that the schema function works correctly"""
|
|
60
|
+
print(f"\n=== Testing NeuronInputsTo schema generation ===")
|
|
61
|
+
|
|
62
|
+
# Get term info for the test neuron
|
|
63
|
+
term_info = get_term_info(self.test_neuron)
|
|
64
|
+
if term_info:
|
|
65
|
+
neuron_name = term_info.get('Name', self.test_neuron)
|
|
66
|
+
else:
|
|
67
|
+
neuron_name = self.test_neuron
|
|
68
|
+
|
|
69
|
+
# Generate schema
|
|
70
|
+
schema = NeuronInputsTo_to_schema(neuron_name, self.test_neuron)
|
|
71
|
+
|
|
72
|
+
# Validate schema structure
|
|
73
|
+
self.assertIsNotNone(schema, "Schema should not be None")
|
|
74
|
+
self.assertEqual(schema.query, "NeuronInputsTo", "Query name should match")
|
|
75
|
+
self.assertEqual(schema.function, "get_individual_neuron_inputs", "Function name should match")
|
|
76
|
+
# NeuronInputsTo uses ribbon format with preview=-1 (all results)
|
|
77
|
+
self.assertEqual(schema.preview, -1, "Preview should show all results (ribbon format)")
|
|
78
|
+
self.assertIn("Neurotransmitter", schema.preview_columns, "Preview should include 'Neurotransmitter' column")
|
|
79
|
+
self.assertIn("Weight", schema.preview_columns, "Preview should include 'Weight' column")
|
|
80
|
+
|
|
81
|
+
print(f"Schema label: {schema.label}")
|
|
82
|
+
print(f"Preview columns: {schema.preview_columns}")
|
|
83
|
+
print(f"Output format: ribbon (preview={schema.preview})")
|
|
84
|
+
|
|
85
|
+
def test_term_info_integration(self):
|
|
86
|
+
"""Test that term info lookup works for the test neuron"""
|
|
87
|
+
print(f"\n=== Testing term_info integration ===")
|
|
88
|
+
term_info = get_term_info(self.test_neuron)
|
|
89
|
+
|
|
90
|
+
self.assertIsNotNone(term_info, "Term info should not be None")
|
|
91
|
+
if term_info:
|
|
92
|
+
# get_term_info returns a dict with 'Name', 'Id', 'Tags', etc.
|
|
93
|
+
self.assertIn('Name', term_info, "Term info should contain 'Name'")
|
|
94
|
+
self.assertIn('Id', term_info, "Term info should contain 'Id'")
|
|
95
|
+
print(f"Neuron name: {term_info.get('Name', 'N/A')}")
|
|
96
|
+
print(f"Neuron tags: {term_info.get('Tags', [])}")
|
|
97
|
+
else:
|
|
98
|
+
print(f"Note: Term info not found for {self.test_neuron} (may not be in SOLR)")
|
|
99
|
+
|
|
100
|
+
def test_preview_validation(self):
|
|
101
|
+
"""Test that preview results are properly formatted"""
|
|
102
|
+
print(f"\n=== Testing preview results ===")
|
|
103
|
+
result = get_individual_neuron_inputs(
|
|
104
|
+
self.test_neuron,
|
|
105
|
+
return_dataframe=False,
|
|
106
|
+
limit=5
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if 'rows' in result and len(result['rows']) > 0:
|
|
110
|
+
# Check that all expected columns exist in the results
|
|
111
|
+
expected_columns = ['id', 'Neurotransmitter', 'Weight', 'Name']
|
|
112
|
+
for item in result['rows']:
|
|
113
|
+
for col in expected_columns:
|
|
114
|
+
self.assertIn(col, item, f"Result should contain '{col}' field")
|
|
115
|
+
|
|
116
|
+
print(f"✓ All {len(result['rows'])} results have required columns")
|
|
117
|
+
|
|
118
|
+
# Print sample results
|
|
119
|
+
for i, item in enumerate(result['rows'][:3], 1):
|
|
120
|
+
print(f"{i}. {item.get('Name', 'N/A')} - {item.get('Neurotransmitter', 'N/A')} (weight: {item.get('Weight', 0)})")
|
|
121
|
+
else:
|
|
122
|
+
print("No preview data available (query returned no results)")
|
|
123
|
+
|
|
124
|
+
def test_neurotransmitter_info(self):
|
|
125
|
+
"""Test that neurotransmitter information is included"""
|
|
126
|
+
print(f"\n=== Testing neurotransmitter information ===")
|
|
127
|
+
result = get_individual_neuron_inputs(
|
|
128
|
+
self.test_neuron,
|
|
129
|
+
return_dataframe=False,
|
|
130
|
+
limit=10
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if 'rows' in result and len(result['rows']) > 0:
|
|
134
|
+
# Check that neurotransmitter field exists and has values
|
|
135
|
+
neurotransmitters = set()
|
|
136
|
+
for row in result['rows']:
|
|
137
|
+
nt = row.get('Neurotransmitter', '')
|
|
138
|
+
if nt:
|
|
139
|
+
neurotransmitters.add(nt)
|
|
140
|
+
|
|
141
|
+
print(f"✓ Found {len(neurotransmitters)} different neurotransmitter type(s)")
|
|
142
|
+
if neurotransmitters:
|
|
143
|
+
print(f" Types: {', '.join(list(neurotransmitters)[:5])}")
|
|
144
|
+
else:
|
|
145
|
+
print("No results to check neurotransmitter information")
|
|
146
|
+
|
|
147
|
+
def test_summary_mode(self):
|
|
148
|
+
"""Test that summary mode works correctly"""
|
|
149
|
+
print(f"\n=== Testing summary mode ===")
|
|
150
|
+
result = get_individual_neuron_inputs(
|
|
151
|
+
self.test_neuron,
|
|
152
|
+
return_dataframe=False,
|
|
153
|
+
summary_mode=True
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
self.assertIsNotNone(result, "Summary mode should return a result")
|
|
157
|
+
self.assertIsInstance(result, dict, "Result should be a dictionary")
|
|
158
|
+
|
|
159
|
+
if 'rows' in result and len(result['rows']) > 0:
|
|
160
|
+
# In summary mode, results are grouped by neurotransmitter type
|
|
161
|
+
print(f"✓ Summary mode returned {len(result['rows'])} neurotransmitter types")
|
|
162
|
+
for i, item in enumerate(result['rows'][:3], 1):
|
|
163
|
+
print(f"{i}. {item.get('Neurotransmitter', 'N/A')} - Total weight: {item.get('Weight', 0)}")
|
|
164
|
+
else:
|
|
165
|
+
print("No summary data available")
|
|
166
|
+
|
|
167
|
+
def test_dataframe_output(self):
|
|
168
|
+
"""Test that DataFrame output format works"""
|
|
169
|
+
print(f"\n=== Testing DataFrame output ===")
|
|
170
|
+
result = get_individual_neuron_inputs(
|
|
171
|
+
self.test_neuron,
|
|
172
|
+
return_dataframe=True,
|
|
173
|
+
limit=5
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
# Should return a pandas DataFrame
|
|
177
|
+
import pandas as pd
|
|
178
|
+
self.assertIsInstance(result, pd.DataFrame, "Should return DataFrame when return_dataframe=True")
|
|
179
|
+
|
|
180
|
+
if not result.empty:
|
|
181
|
+
# Check for expected columns
|
|
182
|
+
expected_columns = ['id', 'Neurotransmitter', 'Weight']
|
|
183
|
+
for col in expected_columns:
|
|
184
|
+
self.assertIn(col, result.columns, f"DataFrame should contain '{col}' column")
|
|
185
|
+
|
|
186
|
+
print(f"✓ DataFrame has {len(result)} rows and {len(result.columns)} columns")
|
|
187
|
+
print(f" Columns: {list(result.columns)}")
|
|
188
|
+
else:
|
|
189
|
+
print("DataFrame is empty (no input neurons found)")
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
if __name__ == '__main__':
|
|
193
|
+
unittest.main(verbosity=2)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Test suite for NeuronNeuronConnectivityQuery.
|
|
4
|
+
|
|
5
|
+
Tests the query that finds neurons connected to a given neuron.
|
|
6
|
+
This implements the neuron_neuron_connectivity_query from the VFB XMI specification.
|
|
7
|
+
|
|
8
|
+
Test cases:
|
|
9
|
+
1. Query execution with known neuron
|
|
10
|
+
2. Schema generation and validation
|
|
11
|
+
3. Term info integration (if applicable)
|
|
12
|
+
4. Preview results validation
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import unittest
|
|
16
|
+
import sys
|
|
17
|
+
import os
|
|
18
|
+
|
|
19
|
+
# Add the src directory to the path
|
|
20
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
|
21
|
+
|
|
22
|
+
from vfbquery.vfb_queries import (
|
|
23
|
+
get_neuron_neuron_connectivity,
|
|
24
|
+
NeuronNeuronConnectivityQuery_to_schema,
|
|
25
|
+
get_term_info
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
class NeuronNeuronConnectivityTest(unittest.TestCase):
|
|
29
|
+
"""Test suite for neuron_neuron_connectivity_query"""
|
|
30
|
+
|
|
31
|
+
def setUp(self):
|
|
32
|
+
"""Set up test fixtures"""
|
|
33
|
+
# Test neuron: LPC1 (FlyEM-HB:1775513344) [VFB_jrchk00s]
|
|
34
|
+
self.test_neuron = "VFB_jrchk00s"
|
|
35
|
+
|
|
36
|
+
def test_query_execution(self):
|
|
37
|
+
"""Test that the query executes successfully"""
|
|
38
|
+
print(f"\n=== Testing neuron_neuron_connectivity_query execution ===")
|
|
39
|
+
result = get_neuron_neuron_connectivity(self.test_neuron, return_dataframe=False, limit=5)
|
|
40
|
+
self.assertIsNotNone(result, "Query should return a result")
|
|
41
|
+
self.assertIsInstance(result, dict, "Result should be a dictionary")
|
|
42
|
+
print(f"Query returned {result.get('count', 0)} results")
|
|
43
|
+
if 'data' in result and len(result['data']) > 0:
|
|
44
|
+
first_result = result['data'][0]
|
|
45
|
+
self.assertIn('id', first_result, "Result should contain 'id' field")
|
|
46
|
+
self.assertIn('label', first_result, "Result should contain 'label' field")
|
|
47
|
+
print(f"First result: {first_result.get('label', 'N/A')} ({first_result.get('id', 'N/A')})")
|
|
48
|
+
else:
|
|
49
|
+
print("No connected neurons found (this is OK if none exist)")
|
|
50
|
+
|
|
51
|
+
def test_schema_generation(self):
|
|
52
|
+
"""Test schema function generates correct structure"""
|
|
53
|
+
print(f"\n=== Testing neuron_neuron_connectivity_query schema generation ===")
|
|
54
|
+
test_name = "LPC1"
|
|
55
|
+
test_takes = {"short_form": self.test_neuron}
|
|
56
|
+
schema = NeuronNeuronConnectivityQuery_to_schema(test_name, test_takes)
|
|
57
|
+
self.assertIsNotNone(schema, "Schema should not be None")
|
|
58
|
+
self.assertEqual(schema.query, "NeuronNeuronConnectivityQuery", "Query name should match")
|
|
59
|
+
self.assertEqual(schema.label, f"Neurons connected to {test_name}", "Label should be formatted correctly")
|
|
60
|
+
self.assertEqual(schema.function, "get_neuron_neuron_connectivity", "Function name should match")
|
|
61
|
+
self.assertEqual(schema.preview, 5, "Preview should be 5")
|
|
62
|
+
expected_columns = ["id", "label", "outputs", "inputs", "tags"]
|
|
63
|
+
self.assertEqual(schema.preview_columns, expected_columns, f"Preview columns should be {expected_columns}")
|
|
64
|
+
print(f"Schema generated successfully: {schema.label}")
|
|
65
|
+
|
|
66
|
+
def test_preview_results(self):
|
|
67
|
+
"""Test that preview results are properly formatted"""
|
|
68
|
+
print(f"\n=== Testing preview results ===")
|
|
69
|
+
result = get_neuron_neuron_connectivity(self.test_neuron, return_dataframe=False, limit=3)
|
|
70
|
+
self.assertIsNotNone(result, "Query should return a result")
|
|
71
|
+
if 'data' in result and len(result['data']) > 0:
|
|
72
|
+
first_result = result['data'][0]
|
|
73
|
+
self.assertIn('id', first_result, "Preview result should have 'id'")
|
|
74
|
+
self.assertIn('label', first_result, "Preview result should have 'label'")
|
|
75
|
+
print(f"First preview result: {first_result.get('label', 'N/A')}")
|
|
76
|
+
else:
|
|
77
|
+
print("No preview results available (this is OK if no connected neurons exist)")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def run_tests():
|
|
81
|
+
"""Run the test suite"""
|
|
82
|
+
suite = unittest.TestLoader().loadTestsFromTestCase(NeuronNeuronConnectivityTest)
|
|
83
|
+
runner = unittest.TextTestRunner(verbosity=2)
|
|
84
|
+
result = runner.run(suite)
|
|
85
|
+
return result.wasSuccessful()
|
|
86
|
+
|
|
87
|
+
if __name__ == '__main__':
|
|
88
|
+
success = run_tests()
|
|
89
|
+
sys.exit(0 if success else 1)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Test suite for NeuronRegionConnectivityQuery.
|
|
4
|
+
|
|
5
|
+
Tests the query that shows connectivity to regions from a given neuron.
|
|
6
|
+
This implements the neuron_region_connectivity_query from the VFB XMI specification.
|
|
7
|
+
|
|
8
|
+
Test cases:
|
|
9
|
+
1. Query execution with known neuron
|
|
10
|
+
2. Schema generation and validation
|
|
11
|
+
3. Term info integration (if applicable)
|
|
12
|
+
4. Preview results validation
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import unittest
|
|
16
|
+
import sys
|
|
17
|
+
import os
|
|
18
|
+
|
|
19
|
+
# Add the src directory to the path
|
|
20
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
|
21
|
+
|
|
22
|
+
from vfbquery.vfb_queries import (
|
|
23
|
+
get_neuron_region_connectivity,
|
|
24
|
+
NeuronRegionConnectivityQuery_to_schema,
|
|
25
|
+
get_term_info
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
class NeuronRegionConnectivityTest(unittest.TestCase):
|
|
29
|
+
"""Test suite for neuron_region_connectivity_query"""
|
|
30
|
+
|
|
31
|
+
def setUp(self):
|
|
32
|
+
"""Set up test fixtures"""
|
|
33
|
+
# Test neuron: LPC1 (FlyEM-HB:1775513344) [VFB_jrchk00s]
|
|
34
|
+
self.test_neuron = "VFB_jrchk00s"
|
|
35
|
+
|
|
36
|
+
def test_query_execution(self):
|
|
37
|
+
"""Test that the query executes successfully"""
|
|
38
|
+
print(f"\n=== Testing neuron_region_connectivity_query execution ===")
|
|
39
|
+
result = get_neuron_region_connectivity(self.test_neuron, return_dataframe=False, limit=5)
|
|
40
|
+
self.assertIsNotNone(result, "Query should return a result")
|
|
41
|
+
self.assertIsInstance(result, dict, "Result should be a dictionary")
|
|
42
|
+
print(f"Query returned {result.get('count', 0)} results")
|
|
43
|
+
if 'data' in result and len(result['data']) > 0:
|
|
44
|
+
first_result = result['data'][0]
|
|
45
|
+
self.assertIn('id', first_result, "Result should contain 'id' field")
|
|
46
|
+
self.assertIn('region', first_result, "Result should contain 'region' field")
|
|
47
|
+
self.assertIn('presynaptic_terminals', first_result, "Result should contain 'presynaptic_terminals' field")
|
|
48
|
+
self.assertIn('postsynaptic_terminals', first_result, "Result should contain 'postsynaptic_terminals' field")
|
|
49
|
+
print(f"First result: {first_result.get('region', 'N/A')} ({first_result.get('id', 'N/A')})")
|
|
50
|
+
print(f" Pre: {first_result.get('presynaptic_terminals', 0)}, Post: {first_result.get('postsynaptic_terminals', 0)}")
|
|
51
|
+
else:
|
|
52
|
+
print("No regions with connectivity found (this is OK if none exist)")
|
|
53
|
+
|
|
54
|
+
def test_schema_generation(self):
|
|
55
|
+
"""Test that the schema function works correctly"""
|
|
56
|
+
print(f"\n=== Testing NeuronRegionConnectivityQuery schema generation ===")
|
|
57
|
+
|
|
58
|
+
# Get term info for the test neuron
|
|
59
|
+
term_info = get_term_info(self.test_neuron)
|
|
60
|
+
if term_info:
|
|
61
|
+
neuron_name = term_info.get('Name', self.test_neuron)
|
|
62
|
+
else:
|
|
63
|
+
neuron_name = self.test_neuron
|
|
64
|
+
|
|
65
|
+
# Generate schema
|
|
66
|
+
schema = NeuronRegionConnectivityQuery_to_schema(neuron_name, self.test_neuron)
|
|
67
|
+
|
|
68
|
+
# Validate schema structure
|
|
69
|
+
self.assertIsNotNone(schema, "Schema should not be None")
|
|
70
|
+
self.assertEqual(schema.query, "NeuronRegionConnectivityQuery", "Query name should match")
|
|
71
|
+
self.assertEqual(schema.function, "get_neuron_region_connectivity", "Function name should match")
|
|
72
|
+
self.assertEqual(schema.preview, 5, "Preview should show 5 results")
|
|
73
|
+
self.assertIn("region", schema.preview_columns, "Preview should include 'region' column")
|
|
74
|
+
self.assertIn("presynaptic_terminals", schema.preview_columns, "Preview should include 'presynaptic_terminals' column")
|
|
75
|
+
self.assertIn("postsynaptic_terminals", schema.preview_columns, "Preview should include 'postsynaptic_terminals' column")
|
|
76
|
+
|
|
77
|
+
print(f"Schema label: {schema.label}")
|
|
78
|
+
print(f"Preview columns: {schema.preview_columns}")
|
|
79
|
+
|
|
80
|
+
def test_term_info_integration(self):
|
|
81
|
+
"""Test that term info lookup works for the test neuron"""
|
|
82
|
+
print(f"\n=== Testing term_info integration ===")
|
|
83
|
+
term_info = get_term_info(self.test_neuron)
|
|
84
|
+
|
|
85
|
+
self.assertIsNotNone(term_info, "Term info should not be None")
|
|
86
|
+
if term_info:
|
|
87
|
+
# get_term_info returns a dict with 'Name', 'Id', 'Tags', etc.
|
|
88
|
+
self.assertIn('Name', term_info, "Term info should contain 'Name'")
|
|
89
|
+
self.assertIn('Id', term_info, "Term info should contain 'Id'")
|
|
90
|
+
print(f"Neuron name: {term_info.get('Name', 'N/A')}")
|
|
91
|
+
print(f"Neuron tags: {term_info.get('Tags', [])}")
|
|
92
|
+
else:
|
|
93
|
+
print(f"Note: Term info not found for {self.test_neuron} (may not be in SOLR)")
|
|
94
|
+
|
|
95
|
+
def test_preview_validation(self):
|
|
96
|
+
"""Test that preview results are properly formatted"""
|
|
97
|
+
print(f"\n=== Testing preview results ===")
|
|
98
|
+
result = get_neuron_region_connectivity(self.test_neuron, return_dataframe=False, limit=5)
|
|
99
|
+
|
|
100
|
+
if 'data' in result and len(result['data']) > 0:
|
|
101
|
+
# Check that all preview columns exist in the results
|
|
102
|
+
expected_columns = ['id', 'region', 'presynaptic_terminals', 'postsynaptic_terminals', 'tags']
|
|
103
|
+
for item in result['data']:
|
|
104
|
+
for col in expected_columns:
|
|
105
|
+
self.assertIn(col, item, f"Result should contain '{col}' field")
|
|
106
|
+
|
|
107
|
+
print(f"✓ All {len(result['data'])} results have required preview columns")
|
|
108
|
+
|
|
109
|
+
# Print sample results
|
|
110
|
+
for i, item in enumerate(result['data'][:3], 1):
|
|
111
|
+
print(f"{i}. {item.get('region', 'N/A')} - Pre:{item.get('presynaptic_terminals', 0)}, Post:{item.get('postsynaptic_terminals', 0)}")
|
|
112
|
+
else:
|
|
113
|
+
print("No preview data available (query returned no results)")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
if __name__ == '__main__':
|
|
117
|
+
unittest.main(verbosity=2)
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
import sys
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
# Add src to path for imports
|
|
6
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'src'))
|
|
7
|
+
|
|
8
|
+
from vfbquery.vfb_queries import get_neurons_with_part_in, get_term_info
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class NeuronsPartHereTest(unittest.TestCase):
|
|
12
|
+
"""Test suite for NeuronsPartHere query implementation"""
|
|
13
|
+
|
|
14
|
+
def setUp(self):
|
|
15
|
+
"""Set up test fixtures"""
|
|
16
|
+
self.medulla_id = 'FBbt_00003748'
|
|
17
|
+
# Expected count based on VFB data (as of test creation)
|
|
18
|
+
# Data can grow over time, so we test for minimum expected count
|
|
19
|
+
self.expected_count = 470 # Minimum expected count (actual was 472)
|
|
20
|
+
self.count_tolerance = 5 # Allow some tolerance for variations
|
|
21
|
+
|
|
22
|
+
def test_neurons_part_here_returns_results(self):
|
|
23
|
+
"""Test that NeuronsPartHere query returns results for medulla"""
|
|
24
|
+
print("\n" + "=" * 80)
|
|
25
|
+
print("Testing NeuronsPartHere query - Basic functionality")
|
|
26
|
+
print("=" * 80)
|
|
27
|
+
|
|
28
|
+
results_df = get_neurons_with_part_in(
|
|
29
|
+
self.medulla_id,
|
|
30
|
+
return_dataframe=True,
|
|
31
|
+
limit=-1
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
self.assertIsNotNone(results_df, "Results should not be None")
|
|
35
|
+
self.assertGreater(len(results_df), 0, "Should return at least one result")
|
|
36
|
+
|
|
37
|
+
print(f"✓ Query returned {len(results_df)} neuron classes")
|
|
38
|
+
|
|
39
|
+
def test_neurons_part_here_result_count(self):
|
|
40
|
+
"""Test that NeuronsPartHere returns expected number of results for medulla"""
|
|
41
|
+
print("\n" + "=" * 80)
|
|
42
|
+
print(f"Testing NeuronsPartHere result count (expected ~{self.expected_count})")
|
|
43
|
+
print("=" * 80)
|
|
44
|
+
|
|
45
|
+
results_df = get_neurons_with_part_in(
|
|
46
|
+
self.medulla_id,
|
|
47
|
+
return_dataframe=True,
|
|
48
|
+
limit=-1
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
actual_count = len(results_df)
|
|
52
|
+
count_diff = actual_count - self.expected_count
|
|
53
|
+
|
|
54
|
+
print(f"Expected: at least {self.expected_count} results")
|
|
55
|
+
print(f"Actual: {actual_count} results")
|
|
56
|
+
|
|
57
|
+
# Data can grow over time, so we require at least the expected minimum
|
|
58
|
+
self.assertGreaterEqual(
|
|
59
|
+
actual_count,
|
|
60
|
+
self.expected_count,
|
|
61
|
+
f"Result count {actual_count} is less than expected minimum {self.expected_count}"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if count_diff > 0:
|
|
65
|
+
print(f"✓ Count increased by {count_diff} (data growth)")
|
|
66
|
+
else:
|
|
67
|
+
print(f"✓ Minimum count met: {actual_count}")
|
|
68
|
+
|
|
69
|
+
def test_neurons_part_here_result_structure(self):
|
|
70
|
+
"""Test that results have the expected structure with required columns"""
|
|
71
|
+
print("\n" + "=" * 80)
|
|
72
|
+
print("Testing NeuronsPartHere result structure")
|
|
73
|
+
print("=" * 80)
|
|
74
|
+
|
|
75
|
+
results_df = get_neurons_with_part_in(
|
|
76
|
+
self.medulla_id,
|
|
77
|
+
return_dataframe=True,
|
|
78
|
+
limit=5
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Check required columns
|
|
82
|
+
required_columns = ['id', 'label', 'tags', 'thumbnail']
|
|
83
|
+
for col in required_columns:
|
|
84
|
+
self.assertIn(col, results_df.columns, f"Column '{col}' should be present")
|
|
85
|
+
|
|
86
|
+
print(f"✓ All required columns present: {', '.join(required_columns)}")
|
|
87
|
+
|
|
88
|
+
# Check that we have data in the columns
|
|
89
|
+
first_row = results_df.iloc[0]
|
|
90
|
+
self.assertIsNotNone(first_row['id'], "ID should not be None")
|
|
91
|
+
self.assertIsNotNone(first_row['label'], "Label should not be None")
|
|
92
|
+
|
|
93
|
+
print(f"✓ Sample result: {first_row['label']}")
|
|
94
|
+
|
|
95
|
+
def test_neurons_part_here_has_examples(self):
|
|
96
|
+
"""Test that neuron class results include example images (thumbnails)"""
|
|
97
|
+
print("\n" + "=" * 80)
|
|
98
|
+
print("Testing NeuronsPartHere includes example images")
|
|
99
|
+
print("=" * 80)
|
|
100
|
+
|
|
101
|
+
results_df = get_neurons_with_part_in(
|
|
102
|
+
self.medulla_id,
|
|
103
|
+
return_dataframe=True,
|
|
104
|
+
limit=10
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Count how many results have thumbnails
|
|
108
|
+
has_thumbnails = results_df['thumbnail'].notna().sum()
|
|
109
|
+
total_results = len(results_df)
|
|
110
|
+
|
|
111
|
+
print(f"Results with thumbnails: {has_thumbnails}/{total_results}")
|
|
112
|
+
|
|
113
|
+
# At least some results should have thumbnails (example instances)
|
|
114
|
+
self.assertGreater(
|
|
115
|
+
has_thumbnails,
|
|
116
|
+
0,
|
|
117
|
+
"At least some neuron classes should have example images"
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Show example thumbnails
|
|
121
|
+
sample_with_thumbnail = results_df[results_df['thumbnail'].notna()].iloc[0]
|
|
122
|
+
print(f"\n✓ Example with thumbnail:")
|
|
123
|
+
print(f" {sample_with_thumbnail['label']}")
|
|
124
|
+
print(f" Thumbnail: {sample_with_thumbnail['thumbnail'][:100]}...")
|
|
125
|
+
|
|
126
|
+
def test_neurons_part_here_preview_in_term_info(self):
|
|
127
|
+
"""Test that NeuronsPartHere query appears with preview results in term_info"""
|
|
128
|
+
print("\n" + "=" * 80)
|
|
129
|
+
print("Testing NeuronsPartHere preview results in term_info")
|
|
130
|
+
print("=" * 80)
|
|
131
|
+
|
|
132
|
+
term_info = get_term_info(self.medulla_id, preview=True)
|
|
133
|
+
|
|
134
|
+
self.assertIsNotNone(term_info, "term_info should not be None")
|
|
135
|
+
self.assertIn('Queries', term_info, "term_info should have Queries")
|
|
136
|
+
|
|
137
|
+
# Find NeuronsPartHere query
|
|
138
|
+
neurons_part_here_query = None
|
|
139
|
+
for query in term_info.get('Queries', []):
|
|
140
|
+
if query.get('query') == 'NeuronsPartHere':
|
|
141
|
+
neurons_part_here_query = query
|
|
142
|
+
break
|
|
143
|
+
|
|
144
|
+
self.assertIsNotNone(
|
|
145
|
+
neurons_part_here_query,
|
|
146
|
+
"NeuronsPartHere query should be present in term_info"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
print(f"✓ NeuronsPartHere query found")
|
|
150
|
+
print(f" Label: {neurons_part_here_query.get('label', 'Unknown')}")
|
|
151
|
+
print(f" Preview limit: {neurons_part_here_query.get('preview', 0)}")
|
|
152
|
+
|
|
153
|
+
# Check preview results
|
|
154
|
+
preview_results = neurons_part_here_query.get('preview_results', {})
|
|
155
|
+
preview_rows = preview_results.get('rows', [])
|
|
156
|
+
|
|
157
|
+
self.assertGreater(
|
|
158
|
+
len(preview_rows),
|
|
159
|
+
0,
|
|
160
|
+
"Preview results should be populated"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
print(f" Preview results: {len(preview_rows)} items")
|
|
164
|
+
|
|
165
|
+
# Check that preview results include thumbnails
|
|
166
|
+
with_thumbnails = sum(1 for row in preview_rows if row.get('thumbnail', ''))
|
|
167
|
+
print(f" Results with example images: {with_thumbnails}/{len(preview_rows)}")
|
|
168
|
+
|
|
169
|
+
self.assertGreater(
|
|
170
|
+
with_thumbnails,
|
|
171
|
+
0,
|
|
172
|
+
"At least some preview results should have example images"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
print(f"\n✓ Preview includes example images")
|
|
176
|
+
|
|
177
|
+
def test_neurons_part_here_limit_parameter(self):
|
|
178
|
+
"""Test that the limit parameter works correctly"""
|
|
179
|
+
print("\n" + "=" * 80)
|
|
180
|
+
print("Testing NeuronsPartHere limit parameter")
|
|
181
|
+
print("=" * 80)
|
|
182
|
+
|
|
183
|
+
limit = 10
|
|
184
|
+
results_df = get_neurons_with_part_in(
|
|
185
|
+
self.medulla_id,
|
|
186
|
+
return_dataframe=True,
|
|
187
|
+
limit=limit
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
actual_count = len(results_df)
|
|
191
|
+
|
|
192
|
+
self.assertLessEqual(
|
|
193
|
+
actual_count,
|
|
194
|
+
limit,
|
|
195
|
+
f"Result count {actual_count} should not exceed limit {limit}"
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
print(f"✓ Limit parameter working: requested {limit}, got {actual_count}")
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
if __name__ == '__main__':
|
|
202
|
+
# Run tests with verbose output
|
|
203
|
+
unittest.main(verbosity=2)
|