Spaces:
Sleeping
Sleeping
Download server.py from elya5/ojs-dashboard: direct link, hf CLI and curl.
- Browser
- Download file 6.28 kB
-
https://huggingface.co/spaces/elya5/ojs-dashboard/resolve/main/server.py
- Command line
-
hf download hf://spaces/elya5/ojs-dashboard/server.py
-
curl -L -o server.py https://huggingface.co/spaces/elya5/ojs-dashboard/resolve/main/server.py
6.28 kB
| import asyncio | |
| from contextlib import asynccontextmanager | |
| from pathlib import Path | |
| from cashews import cache | |
| from fastapi import FastAPI, Query | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import FileResponse | |
| from api import ( | |
| author_countries, | |
| get_openalex_countries, | |
| get_ror_suggestions, | |
| get_tops_table_country, | |
| ojs_all_languages, | |
| ojs_all_metadata, | |
| ojs_all_topics, | |
| ojs_article_for_institution, | |
| ojs_articles_by_year, | |
| ojs_articles_for_journal, | |
| publication_per_discipline_country, | |
| publication_to_journal_location_country, | |
| publications_per_institutions_locations, | |
| publications_per_year_country, | |
| share_of_ojs_articles, | |
| share_of_ojs_articles_country, | |
| ) | |
| from data_processing import ( | |
| articles_to_author_countries, | |
| articles_to_disciplines_count, | |
| articles_to_institution_count, | |
| articles_to_languages, | |
| articles_to_ojs_locations, | |
| articles_to_publication_year_stats, | |
| get_journal_options, | |
| get_tops_table, | |
| journal_countries, | |
| ojs_journals_stats, | |
| ) | |
| async def lifespan(app: FastAPI): | |
| cache.setup('mem://') | |
| yield | |
| await cache.close() | |
| app = FastAPI( | |
| title='OJS Dashboard API', | |
| description='JSON API for the OJS publication analytics dashboard.', | |
| version='1.0.0', | |
| lifespan=lifespan, | |
| ) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=['*'], | |
| allow_methods=['GET'], | |
| allow_headers=['*'], | |
| ) | |
| async def list_journals(): | |
| return get_journal_options() | |
| async def get_index(): | |
| yearly_articles, stats, topics, languages, countries = await asyncio.gather( | |
| asyncio.to_thread(ojs_articles_by_year), | |
| asyncio.to_thread(ojs_journals_stats), | |
| asyncio.to_thread(ojs_all_topics), | |
| asyncio.to_thread(ojs_all_languages), | |
| asyncio.to_thread(journal_countries), | |
| ) | |
| return { | |
| 'yearly_articles': yearly_articles.to_dicts(), | |
| 'stats': stats, | |
| 'topics': topics.to_dicts(), | |
| 'languages': languages.to_dicts(), | |
| 'countries': countries.to_dicts(), | |
| } | |
| async def get_metadata_quality(): | |
| return ojs_all_metadata() | |
| async def list_countries(): | |
| return get_openalex_countries() | |
| async def country_analsis(country_code: str): | |
| table_authors, table_institutions = get_tops_table_country(country_code) | |
| return { | |
| 'ojs_share': share_of_ojs_articles_country(country_code).to_dicts(), | |
| 'yearly_articles': publications_per_year_country(country_code).to_dicts(), | |
| 'disciplines': publication_per_discipline_country(country_code).to_dicts(), | |
| 'institutions': publications_per_institutions_locations( | |
| country_code | |
| ).to_dicts(), | |
| 'journal_locations': publication_to_journal_location_country( | |
| country_code | |
| ).to_dicts(), | |
| 'top_authors': table_authors.to_dicts(), | |
| 'top_institutions': table_institutions.to_dicts(), | |
| 'countries': author_countries(country_code).to_dicts(), | |
| } | |
| async def institution_analsis( | |
| fractional: bool = Query(..., description='Whether fractional or full counting'), | |
| institution: str = Query(..., description='Institution to analyse'), | |
| ): | |
| articles = ojs_article_for_institution(institution) | |
| ojs_share = None | |
| if not fractional: | |
| ojs_share = share_of_ojs_articles(institution).to_dicts() | |
| return { | |
| 'yearly_stats': articles_to_publication_year_stats( | |
| articles, fractional, institution | |
| ).to_dicts(), | |
| 'disciplines': articles_to_disciplines_count( | |
| articles, institution, fractional | |
| ).to_dicts(), | |
| 'journal_locations': articles_to_ojs_locations( | |
| articles, fractional, institution | |
| ).to_dicts(), | |
| 'countries': articles_to_author_countries(articles, False).to_dicts(), | |
| 'languages': articles_to_languages(articles).to_dicts(), | |
| 'institutions': articles_to_institution_count(articles, fractional=fractional)[ | |
| :1000 | |
| ].to_dicts(), | |
| 'ojs_share': ojs_share, | |
| } | |
| async def suggest_institutions( | |
| q: str = Query(..., min_length=3, description='Partial institution name'), | |
| ): | |
| """Returns ROR suggestions for a partial institution name string.""" | |
| return get_ror_suggestions(q) | |
| async def journal_analsis( | |
| fractional: bool = Query(..., description='Whether fractional or full counting'), | |
| journal: str = Query(..., description='ISSNs of journals to analyse'), | |
| ): | |
| articles = ojs_articles_for_journal(journal.replace('\\n', '\n').split('\n')) | |
| table_authors, table_institutions = get_tops_table(articles, fractional=fractional) | |
| return { | |
| 'yearly_stats': articles_to_publication_year_stats( | |
| articles, False, None | |
| ).to_dicts(), | |
| 'top_authors': table_authors.to_dicts(), | |
| 'top_institutions': table_institutions.to_dicts(), | |
| 'author_countries': articles_to_author_countries( | |
| articles, fractional | |
| ).to_dicts(), | |
| 'institutions': articles_to_institution_count(articles, fractional).to_dicts(), | |
| } | |
| async def serve_frontend(full_path: str): | |
| dist = Path(__file__).parent / 'frontend' / 'dist' | |
| candidate = (dist / full_path).resolve() | |
| if full_path and candidate.is_file() and candidate.is_relative_to(dist.resolve()): | |
| return FileResponse(candidate) | |
| return FileResponse(dist / 'index.html') # SPA fallback | |