Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/bar-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-22.04
strategy:
matrix:
python-version: [3.8, 3.9, 3.10.11, 3.11]
python-version: [3.8, 3.9, 3.10.13, 3.11, 3.12]

services:
redis:
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.11.3-bullseye
FROM python:3.12-bookworm

WORKDIR /usr/src/app

Expand Down
2 changes: 2 additions & 0 deletions api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def create_app():
from api.resources.interactions import itrns
from api.resources.gene_localizations import loc
from api.resources.efp_image import efp_image
from api.resources.fastpheno import fastpheno

bar_api.add_namespace(gene_information)
bar_api.add_namespace(rnaseq_gene_expression)
Expand All @@ -72,6 +73,7 @@ def create_app():
bar_api.add_namespace(itrns)
bar_api.add_namespace(loc)
bar_api.add_namespace(efp_image)
bar_api.add_namespace(fastpheno)
bar_api.init_app(bar_app)
return bar_app

Expand Down
65 changes: 65 additions & 0 deletions api/models/fastpheno.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from api import db
import enum
from sqlalchemy.dialects.mysql import DECIMAL, ENUM
from sqlalchemy.orm import relationship
from sqlalchemy import ForeignKey
from typing import List


class Sites(db.Model):
__bind_key__ = "fastpheno"
__tablename__ = "sites"

sites_pk: db.Mapped[int] = db.mapped_column(db.Integer, nullable=False, primary_key=True)
site_name: db.Mapped[str] = db.mapped_column(db.String(45), nullable=False)
site_desc: db.Mapped[str] = db.mapped_column(db.String(99), nullable=True)
children: db.Mapped[List["Trees"]] = relationship()


class Trees(db.Model):
__bind_key__ = "fastpheno"
__tablename__ = "trees"

trees_pk: db.Mapped[int] = db.mapped_column(db.Integer, nullable=False, primary_key=True)
sites_pk: db.Mapped[int] = db.mapped_column(ForeignKey("sites.sites_pk"))
longitude: db.Mapped[float] = db.mapped_column(db.Float, nullable=False)
latitude: db.Mapped[float] = db.mapped_column(db.Float, nullable=False)
genotype_id: db.Mapped[str] = db.mapped_column(db.String(5), nullable=True)
external_link: db.Mapped[str] = db.mapped_column(db.String(200), nullable=True)
tree_given_id: db.Mapped[str] = db.mapped_column(db.String(25), nullable=True)
children: db.Mapped[List["Band"]] = relationship()


class MonthChoices(enum.Enum):
jan = "1"
feb = "2"
mar = "3"
apr = "4"
may = "5"
jun = "6"
jul = "7"
aug = "8"
sep = "9"
oct = "10"
nov = "11"
dec = "12"


class Band(db.Model):
__bind_key__ = "fastpheno"
__tablename__ = "band"

trees_pk: db.Mapped[int] = db.mapped_column(ForeignKey("trees.trees_pk"), primary_key=True)
month: db.Mapped[str] = db.mapped_column(ENUM(MonthChoices), nullable=False, primary_key=True)
band: db.Mapped[float] = db.mapped_column(db.String(100), nullable=False, primary_key=True)
value: db.Mapped[float] = db.mapped_column(DECIMAL(20, 15), nullable=False)


class Height(db.Model):
__bind_key__ = "fastpheno"
__tablename__ = "height"

trees_pk: db.Mapped[int] = db.mapped_column(ForeignKey("trees.trees_pk"), primary_key=True)
month: db.Mapped[str] = db.mapped_column(ENUM(MonthChoices), nullable=False, primary_key=True)
tree_height_proxy: db.Mapped[float] = db.mapped_column(DECIMAL(20, 15), nullable=False)
ground_height_proxy: db.Mapped[float] = db.mapped_column(DECIMAL(20, 15), nullable=False)
93 changes: 93 additions & 0 deletions api/resources/fastpheno.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""
Date: Aug 2023
Author: Vince L
Fastpheno endpoint for retrieving tree data
"""
from flask_restx import Namespace, Resource
from api import db
from api.models.fastpheno import Sites, Trees, Band, Height
from api.utils.bar_utils import BARUtils
from markupsafe import escape


fastpheno = Namespace("FastPheno", description="FastPheno API service", path="/fastpheno")


@fastpheno.route("/get_bands/<string:site>/<string:month>/<string:band>")
class FastPheno(Resource):
@fastpheno.param("site", _in="path", default="pintendre")
@fastpheno.param("month", _in="path", default="jan")
@fastpheno.param("band", _in="path", default="band_1")
def get(self, site, month, band):
"""This end point returns band values for a specific site AND month-date"""
# Escape input data
site = escape(site).capitalize()
month = escape(month)
band = escape(band)

rows = db.session.execute(
db.select(Sites, Trees, Height, Band)
.select_from(Sites)
.join(Trees, Trees.sites_pk == Sites.sites_pk) # don't need to use 2nd arg, for clarity... I set ORM rel
.join(Height, Height.trees_pk == Trees.trees_pk)
.join(Band, Band.trees_pk == Trees.trees_pk)
.where(Sites.site_name == site, Band.month == month, Height.month == month, Band.band == band)
).all()
res = [
{
"site_name": s.site_name,
"tree_id": t.trees_pk,
"longitude": t.longitude,
"latitutde": t.latitude,
"genotype_id": t.genotype_id,
"tree_given_id": t.tree_given_id,
"external_link": t.external_link,
"band_value": float(b.value),
"tree_height_proxy": float(h.tree_height_proxy),
"ground_height_proxy": float(h.ground_height_proxy),
"band_month": b.month.name,
}
for s, t, h, b in rows
]
if len(rows) == 0:
return (
BARUtils.error_exit("There are no data found for the given parameters"),
400,
)

return BARUtils.success_exit(res)


@fastpheno.route("/get_trees/<string:genotype_id>")
class FastPhenoTrees(Resource):
@fastpheno.param("genotype_id", _in="path", default="C")
def get(self, genotype_id):
"""This end point returns trees for a given genotype_id across sites"""
# Escape input data
genotype_id = escape(genotype_id).capitalize()

rows = db.session.execute(
db.select(Sites, Trees)
.select_from(Sites)
.join(Trees, Trees.sites_pk == Sites.sites_pk)
.where(Trees.genotype_id == genotype_id)
).all()
res = [
{
"site_name": s.site_name,
"tree_id": t.trees_pk,
"longitude": t.longitude,
"latitutde": t.latitude,
"genotype_id": t.genotype_id,
"tree_given_id": t.tree_given_id,
"external_link": t.external_link,
}
for s, t in rows
]
if len(rows) == 0:
return (
BARUtils.error_exit("There are no data found for the given parameters"),
400,
)

return BARUtils.success_exit(res)
1 change: 1 addition & 0 deletions config/BAR_API.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ SQLALCHEMY_BINDS = {
'eplant_rice' : 'mysql://root:root@localhost/eplant_rice',
'eplant_soybean' : 'mysql://root:root@localhost/eplant_soybean',
'eplant_tomato' : 'mysql://root:root@localhost/eplant_tomato',
'fastpheno' : 'mysql://root:root@localhost/fastpheno',
'germination': 'mysql://root:root@localhost/germination',
'kalanchoe': 'mysql://root:root@localhost/kalanchoe',
'klepikova': 'mysql://root:root@localhost/klepikova',
Expand Down
153 changes: 153 additions & 0 deletions config/databases/fastpheno.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
-- MySQL dump 10.13 Distrib 8.0.33, for Linux (x86_64)
--
-- Host: localhost Database: cannabis
-- ------------------------------------------------------
-- Server version 8.0.33

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Current Database: `fastpheno`
--

DROP DATABASE IF EXISTS `fastpheno` ;

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `fastpheno` /*!40100 DEFAULT CHARACTER SET latin1 */ /*!80016 DEFAULT ENCRYPTION='N' */;

USE `fastpheno`;

--
-- Table structure for table `sites`
--

DROP TABLE IF EXISTS `sites` ;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE IF NOT EXISTS `sites` (
`sites_pk` INT NOT NULL AUTO_INCREMENT,
`site_name` VARCHAR(45) UNIQUE NOT NULL,
`site_desc` VARCHAR(999) NULL,
PRIMARY KEY (`sites_pk`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `sites`
--

LOCK TABLES `sites` WRITE;
/*!40000 ALTER TABLE `sites` DISABLE KEYS */;
INSERT INTO `sites` VALUES (1,'Pintendre', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit'),(2,'Pickering','Lorem ipsum dolor sit amet,');
/*!40000 ALTER TABLE `sites` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `trees`
--

DROP TABLE IF EXISTS `trees` ;

CREATE TABLE IF NOT EXISTS `trees` (
`trees_pk` INT NOT NULL AUTO_INCREMENT,
`sites_pk` INT NOT NULL,
`longitude` DECIMAL(10) NOT NULL,
`latitude` DECIMAL(10) NOT NULL,
`genotype_id` VARCHAR(5) NULL,
`external_link` VARCHAR(200) NULL,
`tree_given_id` VARCHAR(25) NULL,
PRIMARY KEY (`trees_pk`),
INDEX `sites_fk_idx` (`sites_pk` ASC),
CONSTRAINT `sites_fk`
FOREIGN KEY (`sites_pk`)
REFERENCES `sites` (`sites_pk`)
ON DELETE RESTRICT
ON UPDATE RESTRICT) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `trees`
--

LOCK TABLES `trees` WRITE;
/*!40000 ALTER TABLE `trees` DISABLE KEYS */;
INSERT INTO `trees` VALUES (1,1,336839,5178557,'C','example','11'),(2,1,336872,5178486,'C','example2','11'),(3,1,346872,5278486,'C','example3','B'),(4,2,330502,5262486,'XZ','example4','K123');
/*!40000 ALTER TABLE `trees` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `band`
--

DROP TABLE IF EXISTS `band` ;

CREATE TABLE IF NOT EXISTS `band` (
`trees_pk` INT NOT NULL,
`month` ENUM('jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec') NOT NULL,
`band` VARCHAR(100) NOT NULL,
`value` DECIMAL(20,15) NOT NULL,
INDEX `trees_fk_idx` (`trees_pk` ASC),
PRIMARY KEY (`trees_pk`, `month`, `band`),
CONSTRAINT `trees_fk`
FOREIGN KEY (`trees_pk`)
REFERENCES `trees` (`trees_pk`)
ON DELETE RESTRICT
ON UPDATE RESTRICT) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `band`
--

LOCK TABLES `band` WRITE;
/*!40000 ALTER TABLE `band` DISABLE KEYS */;
INSERT INTO `band` VALUES (1,'jan','band_1',0.025796278000000),(1,'jan','band_2',0.025796278000000),(1,'feb','band_1',0.025796278000000),(1,'mar','band_1',0.0234423232241),(1,'apr','band_1',0.089900613000000),(2,'feb','band_1',0.183586478000000),(4,'feb','band_1',0.223586478000000);
/*!40000 ALTER TABLE `band` ENABLE KEYS */;
UNLOCK TABLES;


-- -----------------------------------------------------
-- Table `height`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `height` ;

CREATE TABLE IF NOT EXISTS `height` (
`trees_pk` INT NOT NULL,
`month` ENUM('jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec') NOT NULL,
`tree_height_proxy` DECIMAL(20,15) NOT NULL,
`ground_height_proxy` DECIMAL(20,15) NOT NULL,
INDEX `tree_fk_idx` (`trees_pk` ASC),
PRIMARY KEY (`trees_pk`, `month`),
CONSTRAINT `tree_fk`
FOREIGN KEY (`trees_pk`)
REFERENCES `trees` (`trees_pk`)
ON DELETE RESTRICT
ON UPDATE RESTRICT) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `height`
--

LOCK TABLES `height` WRITE;
/*!40000 ALTER TABLE `height` DISABLE KEYS */;
INSERT INTO `height` VALUES (1,'jan',2.23428942871000000,45.106719970000000),(1,'feb',3.478942871000000,49.106719970000000),(1,'mar',2.383630037000000,48.887859340000000),(1,'apr',1.376412749000000,49.052417760000000),(2,'feb',2.383630037000000,48.12341242131163),(4,'feb',2.623630037000000,45.22341242131163);
/*!40000 ALTER TABLE `height` ENABLE KEYS */;
UNLOCK TABLES;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2023-06-07 14:37:50
1 change: 1 addition & 0 deletions config/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mysql -u $DB_USER -p$DB_PASS < ./config/databases/eplant_poplar.sql
mysql -u $DB_USER -p$DB_PASS < ./config/databases/eplant_rice.sql
mysql -u $DB_USER -p$DB_PASS < ./config/databases/eplant_soybean.sql
mysql -u $DB_USER -p$DB_PASS < ./config/databases/eplant_tomato.sql
mysql -u $DB_USER -p$DB_PASS < ./config/databases/fastpheno.sql
mysql -u $DB_USER -p$DB_PASS < ./config/databases/germination.sql
mysql -u $DB_USER -p$DB_PASS < ./config/databases/kalanchoe.sql
mysql -u $DB_USER -p$DB_PASS < ./config/databases/klepikova.sql
Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: "3.7"
services:

mysqldb:
image: mysql:8.0.33
image: mysql:8.1.0
container_name: BAR_mysqldb
# Must use this for mariadb client to connect
command: --default-authentication-plugin=mysql_native_password
Expand All @@ -12,7 +12,7 @@ services:
- MYSQL_ROOT_PASSWORD=root

redis:
image: redis:7.0.11
image: redis:7.2.1
container_name: BAR_redis
restart: always
ports:
Expand Down
Loading