vfbquery 0.4.0__py3-none-any.whl → 0.5.0__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 +35 -1
- test/term_info_queries_test.py +11 -11
- test/test_dataset_template_queries.py +138 -0
- test/test_default_caching.py +15 -11
- 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 +204 -0
- test/test_new_owlery_queries.py +282 -0
- test/test_publication_transgene_queries.py +101 -0
- test/test_query_performance.py +743 -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 +22 -1
- vfbquery/neo4j_client.py +120 -0
- vfbquery/owlery_client.py +463 -0
- vfbquery/solr_fetcher.py +1 -1
- vfbquery/solr_result_cache.py +238 -53
- vfbquery/vfb_queries.py +2969 -638
- {vfbquery-0.4.0.dist-info → vfbquery-0.5.0.dist-info}/METADATA +1023 -65
- vfbquery-0.5.0.dist-info/RECORD +39 -0
- vfbquery-0.4.0.dist-info/RECORD +0 -19
- {vfbquery-0.4.0.dist-info → vfbquery-0.5.0.dist-info}/LICENSE +0 -0
- {vfbquery-0.4.0.dist-info → vfbquery-0.5.0.dist-info}/WHEEL +0 -0
- {vfbquery-0.4.0.dist-info → vfbquery-0.5.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,204 @@
|
|
|
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
|
+
# Allowing tolerance for data updates
|
|
19
|
+
self.expected_count = 471
|
|
20
|
+
self.count_tolerance = 5 # Allow ±5 for data updates
|
|
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 = abs(actual_count - self.expected_count)
|
|
53
|
+
|
|
54
|
+
print(f"Expected: {self.expected_count} results")
|
|
55
|
+
print(f"Actual: {actual_count} results")
|
|
56
|
+
print(f"Difference: {count_diff}")
|
|
57
|
+
|
|
58
|
+
# Allow some tolerance for data updates
|
|
59
|
+
self.assertLessEqual(
|
|
60
|
+
count_diff,
|
|
61
|
+
self.count_tolerance,
|
|
62
|
+
f"Result count {actual_count} differs from expected {self.expected_count} by more than {self.count_tolerance}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
if count_diff > 0:
|
|
66
|
+
print(f"⚠ Count differs by {count_diff} (within tolerance of {self.count_tolerance})")
|
|
67
|
+
else:
|
|
68
|
+
print(f"✓ Exact count match: {actual_count}")
|
|
69
|
+
|
|
70
|
+
def test_neurons_part_here_result_structure(self):
|
|
71
|
+
"""Test that results have the expected structure with required columns"""
|
|
72
|
+
print("\n" + "=" * 80)
|
|
73
|
+
print("Testing NeuronsPartHere result structure")
|
|
74
|
+
print("=" * 80)
|
|
75
|
+
|
|
76
|
+
results_df = get_neurons_with_part_in(
|
|
77
|
+
self.medulla_id,
|
|
78
|
+
return_dataframe=True,
|
|
79
|
+
limit=5
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Check required columns
|
|
83
|
+
required_columns = ['id', 'label', 'tags', 'thumbnail']
|
|
84
|
+
for col in required_columns:
|
|
85
|
+
self.assertIn(col, results_df.columns, f"Column '{col}' should be present")
|
|
86
|
+
|
|
87
|
+
print(f"✓ All required columns present: {', '.join(required_columns)}")
|
|
88
|
+
|
|
89
|
+
# Check that we have data in the columns
|
|
90
|
+
first_row = results_df.iloc[0]
|
|
91
|
+
self.assertIsNotNone(first_row['id'], "ID should not be None")
|
|
92
|
+
self.assertIsNotNone(first_row['label'], "Label should not be None")
|
|
93
|
+
|
|
94
|
+
print(f"✓ Sample result: {first_row['label']}")
|
|
95
|
+
|
|
96
|
+
def test_neurons_part_here_has_examples(self):
|
|
97
|
+
"""Test that neuron class results include example images (thumbnails)"""
|
|
98
|
+
print("\n" + "=" * 80)
|
|
99
|
+
print("Testing NeuronsPartHere includes example images")
|
|
100
|
+
print("=" * 80)
|
|
101
|
+
|
|
102
|
+
results_df = get_neurons_with_part_in(
|
|
103
|
+
self.medulla_id,
|
|
104
|
+
return_dataframe=True,
|
|
105
|
+
limit=10
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Count how many results have thumbnails
|
|
109
|
+
has_thumbnails = results_df['thumbnail'].notna().sum()
|
|
110
|
+
total_results = len(results_df)
|
|
111
|
+
|
|
112
|
+
print(f"Results with thumbnails: {has_thumbnails}/{total_results}")
|
|
113
|
+
|
|
114
|
+
# At least some results should have thumbnails (example instances)
|
|
115
|
+
self.assertGreater(
|
|
116
|
+
has_thumbnails,
|
|
117
|
+
0,
|
|
118
|
+
"At least some neuron classes should have example images"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Show example thumbnails
|
|
122
|
+
sample_with_thumbnail = results_df[results_df['thumbnail'].notna()].iloc[0]
|
|
123
|
+
print(f"\n✓ Example with thumbnail:")
|
|
124
|
+
print(f" {sample_with_thumbnail['label']}")
|
|
125
|
+
print(f" Thumbnail: {sample_with_thumbnail['thumbnail'][:100]}...")
|
|
126
|
+
|
|
127
|
+
def test_neurons_part_here_preview_in_term_info(self):
|
|
128
|
+
"""Test that NeuronsPartHere query appears with preview results in term_info"""
|
|
129
|
+
print("\n" + "=" * 80)
|
|
130
|
+
print("Testing NeuronsPartHere preview results in term_info")
|
|
131
|
+
print("=" * 80)
|
|
132
|
+
|
|
133
|
+
term_info = get_term_info(self.medulla_id, preview=True)
|
|
134
|
+
|
|
135
|
+
self.assertIsNotNone(term_info, "term_info should not be None")
|
|
136
|
+
self.assertIn('Queries', term_info, "term_info should have Queries")
|
|
137
|
+
|
|
138
|
+
# Find NeuronsPartHere query
|
|
139
|
+
neurons_part_here_query = None
|
|
140
|
+
for query in term_info.get('Queries', []):
|
|
141
|
+
if query.get('query') == 'NeuronsPartHere':
|
|
142
|
+
neurons_part_here_query = query
|
|
143
|
+
break
|
|
144
|
+
|
|
145
|
+
self.assertIsNotNone(
|
|
146
|
+
neurons_part_here_query,
|
|
147
|
+
"NeuronsPartHere query should be present in term_info"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
print(f"✓ NeuronsPartHere query found")
|
|
151
|
+
print(f" Label: {neurons_part_here_query.get('label', 'Unknown')}")
|
|
152
|
+
print(f" Preview limit: {neurons_part_here_query.get('preview', 0)}")
|
|
153
|
+
|
|
154
|
+
# Check preview results
|
|
155
|
+
preview_results = neurons_part_here_query.get('preview_results', {})
|
|
156
|
+
preview_rows = preview_results.get('rows', [])
|
|
157
|
+
|
|
158
|
+
self.assertGreater(
|
|
159
|
+
len(preview_rows),
|
|
160
|
+
0,
|
|
161
|
+
"Preview results should be populated"
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
print(f" Preview results: {len(preview_rows)} items")
|
|
165
|
+
|
|
166
|
+
# Check that preview results include thumbnails
|
|
167
|
+
with_thumbnails = sum(1 for row in preview_rows if row.get('thumbnail', ''))
|
|
168
|
+
print(f" Results with example images: {with_thumbnails}/{len(preview_rows)}")
|
|
169
|
+
|
|
170
|
+
self.assertGreater(
|
|
171
|
+
with_thumbnails,
|
|
172
|
+
0,
|
|
173
|
+
"At least some preview results should have example images"
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
print(f"\n✓ Preview includes example images")
|
|
177
|
+
|
|
178
|
+
def test_neurons_part_here_limit_parameter(self):
|
|
179
|
+
"""Test that the limit parameter works correctly"""
|
|
180
|
+
print("\n" + "=" * 80)
|
|
181
|
+
print("Testing NeuronsPartHere limit parameter")
|
|
182
|
+
print("=" * 80)
|
|
183
|
+
|
|
184
|
+
limit = 10
|
|
185
|
+
results_df = get_neurons_with_part_in(
|
|
186
|
+
self.medulla_id,
|
|
187
|
+
return_dataframe=True,
|
|
188
|
+
limit=limit
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
actual_count = len(results_df)
|
|
192
|
+
|
|
193
|
+
self.assertLessEqual(
|
|
194
|
+
actual_count,
|
|
195
|
+
limit,
|
|
196
|
+
f"Result count {actual_count} should not exceed limit {limit}"
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
print(f"✓ Limit parameter working: requested {limit}, got {actual_count}")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
if __name__ == '__main__':
|
|
203
|
+
# Run tests with verbose output
|
|
204
|
+
unittest.main(verbosity=2)
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for newly implemented Owlery-based queries:
|
|
3
|
+
- NeuronsSynaptic
|
|
4
|
+
- NeuronsPresynapticHere
|
|
5
|
+
- NeuronsPostsynapticHere
|
|
6
|
+
- ComponentsOf
|
|
7
|
+
- PartsOf
|
|
8
|
+
- SubclassesOf
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import unittest
|
|
12
|
+
from vfbquery.vfb_queries import (
|
|
13
|
+
get_neurons_with_synapses_in,
|
|
14
|
+
get_neurons_with_presynaptic_terminals_in,
|
|
15
|
+
get_neurons_with_postsynaptic_terminals_in,
|
|
16
|
+
get_components_of,
|
|
17
|
+
get_parts_of,
|
|
18
|
+
get_subclasses_of,
|
|
19
|
+
get_term_info
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TestNeuronsSynaptic(unittest.TestCase):
|
|
24
|
+
"""Tests for NeuronsSynaptic query"""
|
|
25
|
+
|
|
26
|
+
def setUp(self):
|
|
27
|
+
self.medulla_id = 'FBbt_00003748' # medulla - synaptic neuropil
|
|
28
|
+
|
|
29
|
+
def test_neurons_synaptic_returns_results(self):
|
|
30
|
+
"""Test that NeuronsSynaptic query returns results for medulla"""
|
|
31
|
+
result = get_neurons_with_synapses_in(
|
|
32
|
+
self.medulla_id,
|
|
33
|
+
return_dataframe=False
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
self.assertIsNotNone(result)
|
|
37
|
+
self.assertIn('headers', result)
|
|
38
|
+
self.assertIn('rows', result)
|
|
39
|
+
self.assertIn('count', result)
|
|
40
|
+
|
|
41
|
+
def test_neurons_synaptic_has_expected_columns(self):
|
|
42
|
+
"""Test that result has expected column structure"""
|
|
43
|
+
result = get_neurons_with_synapses_in(
|
|
44
|
+
self.medulla_id,
|
|
45
|
+
return_dataframe=False
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
headers = result['headers']
|
|
49
|
+
self.assertIn('id', headers)
|
|
50
|
+
self.assertIn('label', headers)
|
|
51
|
+
self.assertIn('tags', headers)
|
|
52
|
+
self.assertIn('thumbnail', headers)
|
|
53
|
+
|
|
54
|
+
def test_neurons_synaptic_in_term_info(self):
|
|
55
|
+
"""Test that NeuronsSynaptic appears in term_info queries"""
|
|
56
|
+
term_info = get_term_info(self.medulla_id, preview=True)
|
|
57
|
+
|
|
58
|
+
self.assertIn('Queries', term_info) # Note: Capital 'Q'
|
|
59
|
+
query_labels = [q['label'] for q in term_info['Queries']]
|
|
60
|
+
|
|
61
|
+
# Check if our query is present
|
|
62
|
+
expected_label = f"Neurons with synaptic terminals in {term_info['Name']}"
|
|
63
|
+
self.assertIn(expected_label, query_labels)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class TestNeuronsPresynapticHere(unittest.TestCase):
|
|
67
|
+
"""Tests for NeuronsPresynapticHere query"""
|
|
68
|
+
|
|
69
|
+
def setUp(self):
|
|
70
|
+
self.medulla_id = 'FBbt_00003748' # medulla - synaptic neuropil
|
|
71
|
+
|
|
72
|
+
def test_neurons_presynaptic_returns_results(self):
|
|
73
|
+
"""Test that NeuronsPresynapticHere query returns results for medulla"""
|
|
74
|
+
result = get_neurons_with_presynaptic_terminals_in(
|
|
75
|
+
self.medulla_id,
|
|
76
|
+
return_dataframe=False
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
self.assertIsNotNone(result)
|
|
80
|
+
self.assertIn('headers', result)
|
|
81
|
+
self.assertIn('rows', result)
|
|
82
|
+
self.assertIn('count', result)
|
|
83
|
+
|
|
84
|
+
def test_neurons_presynaptic_has_expected_columns(self):
|
|
85
|
+
"""Test that result has expected column structure"""
|
|
86
|
+
result = get_neurons_with_presynaptic_terminals_in(
|
|
87
|
+
self.medulla_id,
|
|
88
|
+
return_dataframe=False
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
headers = result['headers']
|
|
92
|
+
self.assertIn('id', headers)
|
|
93
|
+
self.assertIn('label', headers)
|
|
94
|
+
self.assertIn('tags', headers)
|
|
95
|
+
self.assertIn('thumbnail', headers)
|
|
96
|
+
|
|
97
|
+
def test_neurons_presynaptic_in_term_info(self):
|
|
98
|
+
"""Test that NeuronsPresynapticHere appears in term_info queries"""
|
|
99
|
+
term_info = get_term_info(self.medulla_id, preview=True)
|
|
100
|
+
|
|
101
|
+
self.assertIn('Queries', term_info) # Note: Capital 'Q'
|
|
102
|
+
query_labels = [q['label'] for q in term_info['Queries']]
|
|
103
|
+
|
|
104
|
+
# Check if our query is present
|
|
105
|
+
expected_label = f"Neurons with presynaptic terminals in {term_info['Name']}"
|
|
106
|
+
self.assertIn(expected_label, query_labels)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class TestNeuronsPostsynapticHere(unittest.TestCase):
|
|
110
|
+
"""Tests for NeuronsPostsynapticHere query"""
|
|
111
|
+
|
|
112
|
+
def setUp(self):
|
|
113
|
+
self.medulla_id = 'FBbt_00003748' # medulla - synaptic neuropil
|
|
114
|
+
|
|
115
|
+
def test_neurons_postsynaptic_returns_results(self):
|
|
116
|
+
"""Test that NeuronsPostsynapticHere query returns results for medulla"""
|
|
117
|
+
result = get_neurons_with_postsynaptic_terminals_in(
|
|
118
|
+
self.medulla_id,
|
|
119
|
+
return_dataframe=False
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
self.assertIsNotNone(result)
|
|
123
|
+
self.assertIn('headers', result)
|
|
124
|
+
self.assertIn('rows', result)
|
|
125
|
+
self.assertIn('count', result)
|
|
126
|
+
|
|
127
|
+
def test_neurons_postsynaptic_has_expected_columns(self):
|
|
128
|
+
"""Test that result has expected column structure"""
|
|
129
|
+
result = get_neurons_with_postsynaptic_terminals_in(
|
|
130
|
+
self.medulla_id,
|
|
131
|
+
return_dataframe=False
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
headers = result['headers']
|
|
135
|
+
self.assertIn('id', headers)
|
|
136
|
+
self.assertIn('label', headers)
|
|
137
|
+
self.assertIn('tags', headers)
|
|
138
|
+
self.assertIn('thumbnail', headers)
|
|
139
|
+
|
|
140
|
+
def test_neurons_postsynaptic_in_term_info(self):
|
|
141
|
+
"""Test that NeuronsPostsynapticHere appears in term_info queries"""
|
|
142
|
+
term_info = get_term_info(self.medulla_id, preview=True)
|
|
143
|
+
|
|
144
|
+
self.assertIn('Queries', term_info) # Note: Capital 'Q'
|
|
145
|
+
query_labels = [q['label'] for q in term_info['Queries']]
|
|
146
|
+
|
|
147
|
+
# Check if our query is present
|
|
148
|
+
expected_label = f"Neurons with postsynaptic terminals in {term_info['Name']}"
|
|
149
|
+
self.assertIn(expected_label, query_labels)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class TestComponentsOf(unittest.TestCase):
|
|
153
|
+
"""Tests for ComponentsOf query"""
|
|
154
|
+
|
|
155
|
+
def setUp(self):
|
|
156
|
+
self.clone_id = 'FBbt_00110369' # adult SLPpm4 lineage clone
|
|
157
|
+
|
|
158
|
+
def test_components_of_returns_results(self):
|
|
159
|
+
"""Test that ComponentsOf query returns results for clone"""
|
|
160
|
+
result = get_components_of(
|
|
161
|
+
self.clone_id,
|
|
162
|
+
return_dataframe=False
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
self.assertIsNotNone(result)
|
|
166
|
+
self.assertIn('headers', result)
|
|
167
|
+
self.assertIn('rows', result)
|
|
168
|
+
self.assertIn('count', result)
|
|
169
|
+
|
|
170
|
+
def test_components_of_has_expected_columns(self):
|
|
171
|
+
"""Test that result has expected column structure"""
|
|
172
|
+
result = get_components_of(
|
|
173
|
+
self.clone_id,
|
|
174
|
+
return_dataframe=False
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
headers = result['headers']
|
|
178
|
+
self.assertIn('id', headers)
|
|
179
|
+
self.assertIn('label', headers)
|
|
180
|
+
self.assertIn('tags', headers)
|
|
181
|
+
self.assertIn('thumbnail', headers)
|
|
182
|
+
|
|
183
|
+
def test_components_of_in_term_info(self):
|
|
184
|
+
"""Test that ComponentsOf appears in term_info queries"""
|
|
185
|
+
term_info = get_term_info(self.clone_id, preview=True)
|
|
186
|
+
|
|
187
|
+
self.assertIn('Queries', term_info) # Note: Capital 'Q'
|
|
188
|
+
query_labels = [q['label'] for q in term_info['Queries']]
|
|
189
|
+
|
|
190
|
+
# Check if our query is present
|
|
191
|
+
expected_label = f"Components of {term_info['Name']}"
|
|
192
|
+
self.assertIn(expected_label, query_labels)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class TestPartsOf(unittest.TestCase):
|
|
196
|
+
"""Tests for PartsOf query"""
|
|
197
|
+
|
|
198
|
+
def setUp(self):
|
|
199
|
+
self.medulla_id = 'FBbt_00003748' # medulla - any Class
|
|
200
|
+
|
|
201
|
+
def test_parts_of_returns_results(self):
|
|
202
|
+
"""Test that PartsOf query returns results for medulla"""
|
|
203
|
+
result = get_parts_of(
|
|
204
|
+
self.medulla_id,
|
|
205
|
+
return_dataframe=False
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
self.assertIsNotNone(result)
|
|
209
|
+
self.assertIn('headers', result)
|
|
210
|
+
self.assertIn('rows', result)
|
|
211
|
+
self.assertIn('count', result)
|
|
212
|
+
|
|
213
|
+
def test_parts_of_has_expected_columns(self):
|
|
214
|
+
"""Test that result has expected column structure"""
|
|
215
|
+
result = get_parts_of(
|
|
216
|
+
self.medulla_id,
|
|
217
|
+
return_dataframe=False
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
headers = result['headers']
|
|
221
|
+
self.assertIn('id', headers)
|
|
222
|
+
self.assertIn('label', headers)
|
|
223
|
+
self.assertIn('tags', headers)
|
|
224
|
+
self.assertIn('thumbnail', headers)
|
|
225
|
+
|
|
226
|
+
def test_parts_of_in_term_info(self):
|
|
227
|
+
"""Test that PartsOf appears in term_info queries"""
|
|
228
|
+
term_info = get_term_info(self.medulla_id, preview=True)
|
|
229
|
+
|
|
230
|
+
self.assertIn('Queries', term_info) # Note: Capital 'Q'
|
|
231
|
+
query_labels = [q['label'] for q in term_info['Queries']]
|
|
232
|
+
|
|
233
|
+
# Check if our query is present
|
|
234
|
+
expected_label = f"Parts of {term_info['Name']}"
|
|
235
|
+
self.assertIn(expected_label, query_labels)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class TestSubclassesOf(unittest.TestCase):
|
|
239
|
+
"""Tests for SubclassesOf query"""
|
|
240
|
+
|
|
241
|
+
def setUp(self):
|
|
242
|
+
self.wedge_pn_id = 'FBbt_00048516' # wedge projection neuron (>45 subclasses)
|
|
243
|
+
|
|
244
|
+
def test_subclasses_of_returns_results(self):
|
|
245
|
+
"""Test that SubclassesOf query returns results for wedge projection neuron"""
|
|
246
|
+
result = get_subclasses_of(
|
|
247
|
+
self.wedge_pn_id,
|
|
248
|
+
return_dataframe=False
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
self.assertIsNotNone(result)
|
|
252
|
+
self.assertIn('headers', result)
|
|
253
|
+
self.assertIn('rows', result)
|
|
254
|
+
self.assertIn('count', result)
|
|
255
|
+
|
|
256
|
+
def test_subclasses_of_has_expected_columns(self):
|
|
257
|
+
"""Test that result has expected column structure"""
|
|
258
|
+
result = get_subclasses_of(
|
|
259
|
+
self.wedge_pn_id,
|
|
260
|
+
return_dataframe=False
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
headers = result['headers']
|
|
264
|
+
self.assertIn('id', headers)
|
|
265
|
+
self.assertIn('label', headers)
|
|
266
|
+
self.assertIn('tags', headers)
|
|
267
|
+
self.assertIn('thumbnail', headers)
|
|
268
|
+
|
|
269
|
+
def test_subclasses_of_in_term_info(self):
|
|
270
|
+
"""Test that SubclassesOf appears in term_info queries"""
|
|
271
|
+
term_info = get_term_info(self.wedge_pn_id, preview=True)
|
|
272
|
+
|
|
273
|
+
self.assertIn('Queries', term_info) # Note: Capital 'Q'
|
|
274
|
+
query_labels = [q['label'] for q in term_info['Queries']]
|
|
275
|
+
|
|
276
|
+
# Check if our query is present
|
|
277
|
+
expected_label = f"Subclasses of {term_info['Name']}"
|
|
278
|
+
self.assertIn(expected_label, query_labels)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
if __name__ == '__main__':
|
|
282
|
+
unittest.main()
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unit tests for publication and transgene queries.
|
|
3
|
+
|
|
4
|
+
This tests:
|
|
5
|
+
1. get_terms_for_pub - Terms referencing a publication
|
|
6
|
+
2. get_transgene_expression_here - Complex transgene expression query
|
|
7
|
+
|
|
8
|
+
Test terms:
|
|
9
|
+
- DOI_10_7554_eLife_04577 - Example publication
|
|
10
|
+
- FBbt_00003748 - mushroom body (for transgene expression)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import unittest
|
|
14
|
+
import sys
|
|
15
|
+
import os
|
|
16
|
+
|
|
17
|
+
# Add src directory to path
|
|
18
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
|
|
19
|
+
|
|
20
|
+
from vfbquery.vfb_queries import (
|
|
21
|
+
get_terms_for_pub,
|
|
22
|
+
get_transgene_expression_here,
|
|
23
|
+
TermsForPub_to_schema,
|
|
24
|
+
TransgeneExpressionHere_to_schema
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class PublicationTransgeneQueriesTest(unittest.TestCase):
|
|
29
|
+
"""Test cases for publication and transgene queries"""
|
|
30
|
+
|
|
31
|
+
def setUp(self):
|
|
32
|
+
"""Set up test fixtures"""
|
|
33
|
+
self.pub_term = 'DOI_10_7554_eLife_04577' # Example publication
|
|
34
|
+
self.anatomy_term = 'FBbt_00003748' # mushroom body
|
|
35
|
+
|
|
36
|
+
def test_get_terms_for_pub(self):
|
|
37
|
+
"""Test get_terms_for_pub query"""
|
|
38
|
+
result = get_terms_for_pub(self.pub_term, return_dataframe=True, limit=10)
|
|
39
|
+
self.assertIsNotNone(result, "Result should not be None")
|
|
40
|
+
|
|
41
|
+
import pandas as pd
|
|
42
|
+
if isinstance(result, pd.DataFrame) and len(result) > 0:
|
|
43
|
+
print(f"\n✓ Found {len(result)} terms for publication {self.pub_term}")
|
|
44
|
+
self.assertIn('id', result.columns)
|
|
45
|
+
self.assertIn('label', result.columns)
|
|
46
|
+
|
|
47
|
+
def test_get_terms_for_pub_formatted(self):
|
|
48
|
+
"""Test get_terms_for_pub with formatted output"""
|
|
49
|
+
result = get_terms_for_pub(self.pub_term, return_dataframe=False, limit=5)
|
|
50
|
+
self.assertIsNotNone(result)
|
|
51
|
+
|
|
52
|
+
if isinstance(result, dict):
|
|
53
|
+
self.assertIn('headers', result)
|
|
54
|
+
self.assertIn('rows', result)
|
|
55
|
+
|
|
56
|
+
def test_get_transgene_expression_here(self):
|
|
57
|
+
"""Test get_transgene_expression_here query"""
|
|
58
|
+
result = get_transgene_expression_here(self.anatomy_term, return_dataframe=True, limit=10)
|
|
59
|
+
self.assertIsNotNone(result, "Result should not be None")
|
|
60
|
+
|
|
61
|
+
import pandas as pd
|
|
62
|
+
if isinstance(result, pd.DataFrame) and len(result) > 0:
|
|
63
|
+
print(f"\n✓ Found {len(result)} transgene expressions in {self.anatomy_term}")
|
|
64
|
+
self.assertIn('id', result.columns)
|
|
65
|
+
|
|
66
|
+
def test_get_transgene_expression_formatted(self):
|
|
67
|
+
"""Test get_transgene_expression_here with formatted output"""
|
|
68
|
+
result = get_transgene_expression_here(self.anatomy_term, return_dataframe=False, limit=5)
|
|
69
|
+
self.assertIsNotNone(result)
|
|
70
|
+
|
|
71
|
+
if isinstance(result, dict):
|
|
72
|
+
self.assertIn('headers', result)
|
|
73
|
+
self.assertIn('rows', result)
|
|
74
|
+
|
|
75
|
+
def test_schema_functions_exist(self):
|
|
76
|
+
"""Test that publication/transgene schema functions exist and are callable"""
|
|
77
|
+
schema_functions = [
|
|
78
|
+
TermsForPub_to_schema,
|
|
79
|
+
TransgeneExpressionHere_to_schema
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
for func in schema_functions:
|
|
83
|
+
self.assertTrue(callable(func), f"{func.__name__} should be callable")
|
|
84
|
+
|
|
85
|
+
def test_limit_parameter(self):
|
|
86
|
+
"""Test that limit parameter works correctly"""
|
|
87
|
+
result = get_terms_for_pub(self.pub_term, return_dataframe=True, limit=3)
|
|
88
|
+
|
|
89
|
+
import pandas as pd
|
|
90
|
+
if isinstance(result, pd.DataFrame) and len(result) > 0:
|
|
91
|
+
self.assertLessEqual(len(result), 3, "Result should respect limit parameter")
|
|
92
|
+
|
|
93
|
+
def test_empty_results_handling(self):
|
|
94
|
+
"""Test that queries handle empty results gracefully"""
|
|
95
|
+
# Use a term unlikely to have references
|
|
96
|
+
result = get_terms_for_pub('INVALID_PUB_123', return_dataframe=True, limit=5)
|
|
97
|
+
self.assertIsNotNone(result)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if __name__ == '__main__':
|
|
101
|
+
unittest.main()
|