diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8f5fe6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +*.egg-info/ +dist/ +build/ + +# Virtual environments +venv/ +env/ +ENV/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log +logs/ + +# Model checkpoints and data (large files) +*.ckpt +*.pth +*.pt diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..8a18bdc --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,245 @@ +# Deployment Guide - Text2Trait Frontend + +This guide explains how to deploy the Text2Trait frontend application using Gunicorn and the provided WSGI entry point. + +## Prerequisites + +1. Python 3.12 or higher +2. Install dependencies from `text2trait_forntend_app/src/pyproject.toml`: + (Note: The directory name contains a typo 'forntend' - this is the actual name in the repository) + ```bash + cd text2trait_forntend_app/src + pip install -r pyproject.toml + # or with poetry: + poetry install + ``` + +3. Install Gunicorn: + ```bash + pip install gunicorn + ``` + +## WSGI Entry Point + +The `wsgi_t2tfe.py` file at the root of the repository provides a Gunicorn-compatible WSGI entry point for the Text2Trait frontend Dash application. + +## Usage + +### Local Development + +For local development and testing: + +```bash +python wsgi_t2tfe.py +``` + +The application will be available at `http://localhost:8051/` + +### Production Deployment with Gunicorn + +For production deployment, use Gunicorn: + +```bash +gunicorn wsgi_t2tfe:server --bind 0.0.0.0:8051 --workers 4 +``` + +#### Recommended Gunicorn Configuration + +```bash +gunicorn wsgi_t2tfe:server \ + --bind 127.0.0.1:8051 \ + --workers 4 \ + --timeout 120 \ + --access-logfile /var/log/text2trait/access.log \ + --error-logfile /var/log/text2trait/error.log \ + --log-level info +``` + +#### Configuration Options Explained + +- `--bind 127.0.0.1:8051` - Bind only to localhost on port 8051 +- `--workers 4` - Use 4 worker processes (adjust based on CPU cores: 2-4 × CPU cores) +- `--timeout 120` - Worker timeout in seconds (adjust based on your needs) +- `--access-logfile` - Path for access logs +- `--error-logfile` - Path for error logs +- `--log-level` - Logging level (debug, info, warning, error, critical) + +### Running as a Systemd Service + +Create a systemd service file `/etc/systemd/system/text2trait-frontend.service`: + +```ini +[Unit] +Description=Text2Trait Frontend Application +After=network.target + +[Service] +Type=simple +User=harvest +Group=harvest +WorkingDirectory=/path/to/Text2Trait +Environment="PATH=/path/to/venv/bin" +ExecStart=/path/to/venv/bin/gunicorn wsgi_t2tfe:server \ + --bind 127.0.0.1:8051 \ + --workers 4 \ + --timeout 120 \ + --access-logfile /var/log/text2trait/access.log \ + --error-logfile /var/log/text2trait/error.log +ExecReload=/bin/kill -s HUP $MAINPID +KillMode=mixed +TimeoutStopSec=5 +PrivateTmp=true + +[Install] +WantedBy=multi-user.target +``` + +Enable and start the service: + +```bash +sudo systemctl daemon-reload +sudo systemctl enable text2trait-frontend +sudo systemctl start text2trait-frontend +sudo systemctl status text2trait-frontend +``` + +### Using with Nginx (Reverse Proxy) + +Create an Nginx configuration `/etc/nginx/sites-available/text2trait`: + +```nginx +server { + listen 80; + server_name your-domain.com; + + location / { + proxy_pass http://127.0.0.1:8051; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support (if needed by Dash) + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Increase timeouts for long-running requests + proxy_connect_timeout 120s; + proxy_send_timeout 120s; + proxy_read_timeout 120s; + } +} +``` + +Enable the site: + +```bash +sudo ln -s /etc/nginx/sites-available/text2trait /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl reload nginx +``` + +## Environment Variables + +If your application requires environment variables, set them before running: + +```bash +export DATA_PATH=/path/to/data +export LOG_LEVEL=INFO +gunicorn wsgi_t2tfe:server --bind 127.0.0.1:8051 --workers 4 +``` + +## Monitoring and Logs + +Monitor the application: + +```bash +# View logs +tail -f /var/log/text2trait/access.log +tail -f /var/log/text2trait/error.log + +# Check service status +sudo systemctl status text2trait-frontend + +# View systemd logs +sudo journalctl -u text2trait-frontend -f +``` + +## Performance Tuning + +### Worker Count + +The optimal number of workers depends on your server: + +- CPU-bound applications: `(2 × CPU cores) + 1` +- I/O-bound applications: `(4 × CPU cores) + 1` + +For the Dash application (mostly I/O-bound): + +```bash +# For a 4-core server: +gunicorn wsgi_t2tfe:server --bind 127.0.0.1:8051 --workers 17 +``` + +### Worker Class + +For better async support, use the gevent worker class: + +```bash +pip install gevent +gunicorn wsgi_t2tfe:server \ + --bind 127.0.0.1:8051 \ + --workers 4 \ + --worker-class gevent \ + --worker-connections 1000 +``` + +## Troubleshooting + +### Application won't start + +1. Check Python path and dependencies: + ```bash + python -c "from wsgi_t2tfe import server; print('OK')" + ``` + +2. Check Gunicorn syntax: + ```bash + gunicorn --check-config wsgi_t2tfe:server + ``` + +3. Check logs for errors: + ```bash + tail -f /var/log/text2trait/error.log + ``` + +### High memory usage + +Reduce the number of workers: + +```bash +gunicorn wsgi_t2tfe:server --bind 127.0.0.1:8051 --workers 2 +``` + +### Timeout errors + +Increase the timeout: + +```bash +gunicorn wsgi_t2tfe:server --bind 127.0.0.1:8051 --timeout 300 +``` + +## Security Considerations + +1. **Never expose Gunicorn directly to the internet** - Always use a reverse proxy like Nginx +2. **Use HTTPS** - Configure SSL/TLS in Nginx +3. **Firewall rules** - Restrict access to port 8051 to localhost only +4. **Keep dependencies updated** - Regularly update Python packages +5. **Use a dedicated user** - Don't run as root + +## Additional Resources + +- [Gunicorn Documentation](https://docs.gunicorn.org/) +- [Dash Deployment Guide](https://dash.plotly.com/deployment) +- [Nginx Documentation](https://nginx.org/en/docs/) diff --git a/text2trait_forntend_app/src/app.py b/text2trait_forntend_app/src/app.py index b38a243..fca5c51 100644 --- a/text2trait_forntend_app/src/app.py +++ b/text2trait_forntend_app/src/app.py @@ -123,4 +123,4 @@ # Application Entry Point # ─────────────────────────────── if __name__ == "__main__": - app.run(host="0.0.0.0", port=8050, debug=False) \ No newline at end of file + app.run(host="127.0.0.1", port=8051, debug=False) diff --git a/text2trait_forntend_app/src/pages/home.py b/text2trait_forntend_app/src/pages/home.py index 21cfdd0..3f2080a 100644 --- a/text2trait_forntend_app/src/pages/home.py +++ b/text2trait_forntend_app/src/pages/home.py @@ -1,8 +1,8 @@ """ -Home Page – GWAS-P ------------------- +Home Page – Text2Trait +---------------------- -This is the landing page for the GWAS-P application. +This is the landing page for the Text2Trait application. It provides: - An introductory description of the app. - Search inputs for traits and (optionally) specific genes. @@ -22,7 +22,7 @@ __name__, path="/", name="Home", - title="GWAS-P", + title="Text2Trait", ) @@ -38,7 +38,7 @@ [ html.Img( src=dash.get_asset_url("text2trait_logo.png"), - alt="GWAS-P logo", + alt="Text2Trait logo", style={ "width": "200px", "height": "200px", diff --git a/text2trait_forntend_app/src/pages/index.py b/text2trait_forntend_app/src/pages/index.py index 8151b0d..c6b0b6e 100644 --- a/text2trait_forntend_app/src/pages/index.py +++ b/text2trait_forntend_app/src/pages/index.py @@ -1,6 +1,6 @@ """ -Index Page – GWAS-P -------------------- +Index Page – Text2Trait +------------------------ This page provides a browsable index of: - All traits in the knowledge graph. @@ -186,7 +186,7 @@ def generate_trait_gene_tab() -> dash_table.DataTable: # Page Layout # ─────────────────────────────── layout = dbc.Container([ - html.H2("GWAS-P Knowledge Graph Explorer", className="my-4"), + html.H2("Text2Trait Knowledge Graph Explorer", className="my-4"), dbc.Row([ dbc.Col([ dbc.Tabs([ diff --git a/text2trait_forntend_app/src/pages/questions.py b/text2trait_forntend_app/src/pages/questions.py index b3f0770..94c55e7 100644 --- a/text2trait_forntend_app/src/pages/questions.py +++ b/text2trait_forntend_app/src/pages/questions.py @@ -1,9 +1,9 @@ """ -Questions Page – GWAS-P ------------------------ +Questions Page – Text2Trait +---------------------------- This page contains an FAQ section for common user questions -about the GWAS-P application. +about the Text2Trait application. """ import dash diff --git a/text2trait_forntend_app/src/pages/results.py b/text2trait_forntend_app/src/pages/results.py index 8cc6503..e190b6f 100644 --- a/text2trait_forntend_app/src/pages/results.py +++ b/text2trait_forntend_app/src/pages/results.py @@ -1,8 +1,8 @@ """ -Results Page – GWAS-P ----------------------- +Results Page – Text2Trait +-------------------------- -This page displays the GWAS-P results, including a trait-gene interaction +This page displays the Text2Trait results, including a trait-gene interaction graph using Cytoscape, interactive tables for matched genes, and a side panel for detailed gene information retrieved from NCBI. """ @@ -41,7 +41,7 @@ __name__, path="/results", name="Results", - title="GWAS-P Results" + title="Text2Trait Results" ) # ─────────────────────────────── diff --git a/text2trait_forntend_app/src/pyproject.toml b/text2trait_forntend_app/src/pyproject.toml index 39b5351..184d89d 100644 --- a/text2trait_forntend_app/src/pyproject.toml +++ b/text2trait_forntend_app/src/pyproject.toml @@ -1,7 +1,7 @@ [project] -name = "gwas-frontend-project" +name = "text2trait-frontend-project" version = "0.1.0" -description = "Requirments for the frontend" +description = "Requirements for the frontend" authors = [ ] readme = "README.md" @@ -21,3 +21,4 @@ dependencies = [ [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] build-backend = "poetry.core.masonry.api" +package-mode = false diff --git a/text2trait_forntend_app/src/utils/requirements.txt b/text2trait_forntend_app/src/utils/requirements.txt new file mode 100644 index 0000000..4dd2210 --- /dev/null +++ b/text2trait_forntend_app/src/utils/requirements.txt @@ -0,0 +1,46 @@ +anyio==4.11.0 ; python_version >= "3.12" and python_version < "3.14" +bio==1.8.1 ; python_version >= "3.12" and python_version < "3.14" +biopython==1.86 ; python_version >= "3.12" and python_version < "3.14" +biothings-client==0.4.1 ; python_version >= "3.12" and python_version < "3.14" +blinker==1.9.0 ; python_version >= "3.12" and python_version < "3.14" +certifi==2025.10.5 ; python_version >= "3.12" and python_version < "3.14" +charset-normalizer==3.4.4 ; python_version >= "3.12" and python_version < "3.14" +click==8.3.0 ; python_version >= "3.12" and python_version < "3.14" +colorama==0.4.6 ; python_version >= "3.12" and python_version < "3.14" and platform_system == "Windows" +dash-bootstrap-components==2.0.4 ; python_version >= "3.12" and python_version < "3.14" +dash-cytoscape==1.0.2 ; python_version >= "3.12" and python_version < "3.14" +dash==3.2.0 ; python_version >= "3.12" and python_version < "3.14" +flask==3.1.2 ; python_version >= "3.12" and python_version < "3.14" +gprofiler-official==1.0.0 ; python_version >= "3.12" and python_version < "3.14" +h11==0.16.0 ; python_version >= "3.12" and python_version < "3.14" +httpcore==1.0.9 ; python_version >= "3.12" and python_version < "3.14" +httpx==0.28.1 ; python_version >= "3.12" and python_version < "3.14" +idna==3.11 ; python_version >= "3.12" and python_version < "3.14" +importlib-metadata==8.7.0 ; python_version >= "3.12" and python_version < "3.14" +itsdangerous==2.2.0 ; python_version >= "3.12" and python_version < "3.14" +jinja2==3.1.6 ; python_version >= "3.12" and python_version < "3.14" +markupsafe==3.0.3 ; python_version >= "3.12" and python_version < "3.14" +mygene==3.2.2 ; python_version >= "3.12" and python_version < "3.14" +narwhals==2.10.1 ; python_version >= "3.12" and python_version < "3.14" +nest-asyncio==1.6.0 ; python_version >= "3.12" and python_version < "3.14" +networkx==3.5 ; python_version >= "3.12" and python_version < "3.14" +numpy==2.3.4 ; python_version >= "3.12" and python_version < "3.14" +packaging==25.0 ; python_version >= "3.12" and python_version < "3.14" +pandas==2.3.3 ; python_version >= "3.12" and python_version < "3.14" +platformdirs==4.5.0 ; python_version >= "3.12" and python_version < "3.14" +plotly==6.3.1 ; python_version >= "3.12" and python_version < "3.14" +pooch==1.8.2 ; python_version >= "3.12" and python_version < "3.14" +python-dateutil==2.9.0.post0 ; python_version >= "3.12" and python_version < "3.14" +pytz==2025.2 ; python_version >= "3.12" and python_version < "3.14" +rapidfuzz==3.14.3 ; python_version >= "3.12" and python_version < "3.14" +requests==2.32.5 ; python_version >= "3.12" and python_version < "3.14" +retrying==1.4.2 ; python_version >= "3.12" and python_version < "3.14" +setuptools==80.9.0 ; python_version >= "3.12" and python_version < "3.14" +six==1.17.0 ; python_version >= "3.12" and python_version < "3.14" +sniffio==1.3.1 ; python_version >= "3.12" and python_version < "3.14" +tqdm==4.67.1 ; python_version >= "3.12" and python_version < "3.14" +typing-extensions==4.15.0 ; python_version >= "3.12" and python_version < "3.14" +tzdata==2025.2 ; python_version >= "3.12" and python_version < "3.14" +urllib3==2.5.0 ; python_version >= "3.12" and python_version < "3.14" +werkzeug==3.1.3 ; python_version >= "3.12" and python_version < "3.14" +zipp==3.23.0 ; python_version >= "3.12" and python_version < "3.14" diff --git a/utils/data_processing/main.py b/utils/data_processing/main.py index 8d5b2fd..7b0278e 100644 --- a/utils/data_processing/main.py +++ b/utils/data_processing/main.py @@ -1,5 +1,5 @@ """ -Main pipeline script for processing GWAS and literature data. +Main pipeline script for processing Text2Trait and literature data. Workflow: 1. Process Excel files → master_triplets.jsonl diff --git a/wsgi_t2tfe.py b/wsgi_t2tfe.py new file mode 100644 index 0000000..7275916 --- /dev/null +++ b/wsgi_t2tfe.py @@ -0,0 +1,39 @@ +""" +WSGI Entry Point for Text2Trait Frontend Application +====================================================== + +This module provides a Gunicorn-compatible WSGI entry point for the Text2Trait +frontend Dash application. + +Usage with Gunicorn: + gunicorn wsgi_t2tfe:server --bind 127.0.0.1:8050 --workers 4 + +Environment Setup: + 1. Install dependencies from text2trait_forntend_app/src/pyproject.toml + (Note: directory name has typo 'forntend' - this is intentional, matching repo structure) + 2. Ensure all data files are in place + 3. Set appropriate environment variables if needed + +The application is a Dash-based frontend that provides: + - Multi-page navigation + - Text2Trait data visualization + - Interactive search functionality + - Results visualization with Cytoscape graphs +""" + +import sys +from pathlib import Path + +# Add the frontend source directory to Python path +frontend_src = Path(__file__).parent / "text2trait_forntend_app" / "src" +sys.path.insert(0, str(frontend_src)) + +# Import the Dash app and expose the Flask server +from app import app + +# Expose the WSGI server for Gunicorn +server = app.server + +# For local testing only +if __name__ == "__main__": + app.run(host="127.0.0.1", port=8051, debug=False)