Skip to content

Commit 607378b

Browse files
Robbie1977claude
andcommitted
Wire FindStocks and FindComboPublications into term_info Query system
FlyBase Feature terms (FBgn/FBal/FBti/FBtp/FBco/FBst) now show "Find fly stocks" as an available query in term_info. FBco terms additionally show "Find publications". Both are available via /run_query?query_type=FindStocks|FindComboPublications and are registered in QUERY_TYPE_MAP for the Docker server. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bbd2be3 commit 607378b

4 files changed

Lines changed: 135 additions & 2 deletions

File tree

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
here = path.abspath(path.dirname(__file__))
55

6-
__version__ = "1.7.0"
6+
__version__ = "1.7.1"
77

88
# Get the long description from the README file
99
with open(path.join(here, 'README.md')) as f:

src/vfbquery/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,4 @@ def clear_solr_cache(query_type: str, term_id: str) -> bool:
9898
__solr_caching_available__ = False
9999

100100
# Version information
101-
__version__ = "1.7.0"
101+
__version__ = "1.7.1"

src/vfbquery/ha_api.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ async def security_middleware(request, handler):
275275

276276
# Publications
277277
"TermsForPub": "get_terms_for_pub",
278+
279+
# FlyBase integration
280+
"FindStocks": "get_flybase_stocks",
281+
"FindComboPublications": "get_flybase_combo_pubs",
278282
}
279283

280284

src/vfbquery/vfb_queries.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,17 @@ def term_info_parse_object(results, short_form):
942942
q = UpstreamClassConnectivity_to_schema(termInfo["Name"], {"short_form": vfbTerm.term.core.short_form})
943943
queries.append(q)
944944

945+
# FlyBase stock finder — for Feature terms (FBgn/FBal/FBti/FBtp/FBco/FBst)
946+
sf = vfbTerm.term.core.short_form
947+
if sf.startswith(("FBgn", "FBal", "FBti", "FBtp", "FBco", "FBst")):
948+
q = FindStocks_to_schema(termInfo["Name"], {"short_form": sf})
949+
queries.append(q)
950+
951+
# FlyBase combination publications — for FBco terms
952+
if sf.startswith("FBco"):
953+
q = FindComboPublications_to_schema(termInfo["Name"], {"short_form": sf})
954+
queries.append(q)
955+
945956
# For individuals that are painted domains of anatomical regions, add parent class queries
946957
if termInfo["IsIndividual"] and termInfo["Technique"] and any('computer' in t.lower() for t in termInfo["Technique"]):
947958
anatomical_classes = []
@@ -1806,6 +1817,30 @@ def TransgeneExpressionHere_to_schema(name, take_default):
18061817
return Query(query="TransgeneExpressionHere", label=f"Transgene expression in {name}", function="get_transgene_expression_here", takes={"short_form": {"$and": ["Class", "Nervous_system", "Anatomy"]}, "default": take_default}, preview=5, preview_columns=["id", "name", "tags"])
18071818

18081819

1820+
def FindStocks_to_schema(name, take_default):
1821+
"""Schema for FindStocks query — find available fly stocks from FlyBase."""
1822+
return Query(
1823+
query="FindStocks",
1824+
label=f"Find fly stocks for {name}",
1825+
function="get_flybase_stocks",
1826+
takes={"short_form": {"$and": ["Feature"]}, "default": take_default},
1827+
preview=5,
1828+
preview_columns=["stock_id", "stock_number", "genotype", "collection"],
1829+
)
1830+
1831+
1832+
def FindComboPublications_to_schema(name, take_default):
1833+
"""Schema for FindComboPublications query — find publications for a split system combination."""
1834+
return Query(
1835+
query="FindComboPublications",
1836+
label=f"Find publications for {name}",
1837+
function="get_flybase_combo_pubs",
1838+
takes={"short_form": {"$and": ["Feature"]}, "default": take_default},
1839+
preview=5,
1840+
preview_columns=["fbrf", "title", "year", "pub_type"],
1841+
)
1842+
1843+
18091844
def serialize_solr_output(results):
18101845
# Create a copy of the document and remove Solr-specific fields
18111846
doc = dict(results.docs[0])
@@ -3140,6 +3175,100 @@ def get_upstream_class_connectivity(short_form: str, return_dataframe=True, limi
31403175
return {'headers': headers, 'rows': rows, 'count': total_count}
31413176

31423177

3178+
def get_flybase_stocks(short_form: str, return_dataframe=True, limit: int = -1):
3179+
"""Find available fly stocks from FlyBase for a Feature term.
3180+
3181+
:param short_form: FlyBase feature ID (FBgn/FBal/FBti/FBco/FBst)
3182+
:param return_dataframe: Returns pandas DataFrame if True, otherwise formatted dict
3183+
:param limit: maximum number of results (-1 for all)
3184+
:return: Stock records from FlyBase
3185+
"""
3186+
from .flybase_stocks import find_stocks
3187+
3188+
try:
3189+
stocks = find_stocks(short_form)
3190+
except Exception as e:
3191+
print(f"Error querying FlyBase stocks for {short_form}: {e}")
3192+
if return_dataframe:
3193+
return pd.DataFrame()
3194+
return {'headers': {}, 'rows': [], 'count': 0}
3195+
3196+
rows = []
3197+
for s in stocks:
3198+
rows.append({
3199+
'stock_id': s.get('stock_id', ''),
3200+
'stock_number': s.get('stock_number', ''),
3201+
'genotype': s.get('genotype', ''),
3202+
'collection': s.get('collection', ''),
3203+
})
3204+
3205+
total_count = len(rows)
3206+
if limit != -1:
3207+
rows = rows[:limit]
3208+
3209+
if return_dataframe:
3210+
return pd.DataFrame(rows)
3211+
3212+
headers = {
3213+
'stock_id': {'title': 'Stock ID', 'type': 'text', 'order': 0},
3214+
'stock_number': {'title': 'Stock Number', 'type': 'text', 'order': 1},
3215+
'genotype': {'title': 'Genotype', 'type': 'text', 'order': 2},
3216+
'collection': {'title': 'Collection', 'type': 'text', 'order': 3},
3217+
}
3218+
return {'headers': headers, 'rows': rows, 'count': total_count}
3219+
3220+
3221+
def get_flybase_combo_pubs(short_form: str, return_dataframe=True, limit: int = -1):
3222+
"""Find publications for a FlyBase split system combination.
3223+
3224+
:param short_form: FlyBase combination ID (FBco...)
3225+
:param return_dataframe: Returns pandas DataFrame if True, otherwise formatted dict
3226+
:param limit: maximum number of results (-1 for all)
3227+
:return: Publication records from FlyBase
3228+
"""
3229+
from .flybase_combo_pubs import find_combo_publications
3230+
3231+
try:
3232+
pubs = find_combo_publications(short_form)
3233+
except Exception as e:
3234+
print(f"Error querying FlyBase publications for {short_form}: {e}")
3235+
if return_dataframe:
3236+
return pd.DataFrame()
3237+
return {'headers': {}, 'rows': [], 'count': 0}
3238+
3239+
rows = []
3240+
for p in pubs:
3241+
rows.append({
3242+
'fbrf': p.get('fbrf', ''),
3243+
'title': p.get('title', ''),
3244+
'year': p.get('year', ''),
3245+
'miniref': p.get('miniref', ''),
3246+
'pub_type': p.get('pub_type', ''),
3247+
'doi': p.get('doi', ''),
3248+
'pmid': p.get('pmid', ''),
3249+
'pmcid': p.get('pmcid', ''),
3250+
})
3251+
3252+
total_count = len(rows)
3253+
if limit != -1:
3254+
rows = rows[:limit]
3255+
3256+
if return_dataframe:
3257+
return pd.DataFrame(rows)
3258+
3259+
headers = {
3260+
'fbrf': {'title': 'FBrf', 'type': 'text', 'order': 0},
3261+
'title': {'title': 'Title', 'type': 'text', 'order': 1},
3262+
'year': {'title': 'Year', 'type': 'text', 'order': 2},
3263+
'miniref': {'title': 'Reference', 'type': 'text', 'order': 3},
3264+
'pub_type': {'title': 'Type', 'type': 'text', 'order': 4},
3265+
'doi': {'title': 'DOI', 'type': 'text', 'order': 5},
3266+
'pmid': {'title': 'PMID', 'type': 'text', 'order': 6},
3267+
'pmcid': {'title': 'PMCID', 'type': 'text', 'order': 7},
3268+
}
3269+
return {'headers': headers, 'rows': rows, 'count': total_count}
3270+
3271+
31433272
@with_solr_cache('images_neurons')
31443273
def get_images_neurons(short_form: str, return_dataframe=True, limit: int = -1):
31453274
"""

0 commit comments

Comments
 (0)