Skip to content
Open
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
Empty file added .gitignore
Empty file.
Empty file added __init__.py
Empty file.
11 changes: 11 additions & 0 deletions dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from fastapi import Header, HTTPException


async def get_token_header(x_token: str = Header()):
if x_token != "test-token":
raise HTTPException(status_code=400, detail="X-Token header invalid")


async def get_query_token(token: str):
if token != "sooyoung":
raise HTTPException(status_code=400, detail="No Sooyoung token provided")
Empty file added internal/__init__.py
Empty file.
Empty file added internal/admin.py
Empty file.
37 changes: 37 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from fastapi import Depends, FastAPI

from dependencies import get_query_token, get_token_header
# from internal import admin
from routers import biosamples, participants

import uvicorn
from fastapi_sqlalchemy import DBSessionMiddleware, db
import os
from dotenv import load_dotenv

load_dotenv('.env')

app = FastAPI(dependencies=[Depends(get_query_token)])


app.include_router(participants.router)
app.include_router(biosamples.router)
# app.include_router(
# admin.router,
# prefix="/admin",
# tags=["admin"],
# dependencies=[Depends(get_token_header)],
# responses={418: {"description": "I'm a teapot"}},
# )

# to avoid csrftokenError
app.add_middleware(DBSessionMiddleware, db_url=os.environ['DATABASE_URL'])

@app.get("/")
async def root():
return {"message": "Knowledge Graph API"}


# To run locally
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
Empty file added models/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions models/annotations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class Annotations(BaseModel):
name: str
5 changes: 5 additions & 0 deletions models/assay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class Assay(BaseModel):
name: str
5 changes: 5 additions & 0 deletions models/atlas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class Atlas(BaseModel):
type: Spatial, Dimensional
39 changes: 39 additions & 0 deletions models/biosample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from dandischema import DandiBaseModel


class BioSample(DandiBaseModel):
"""Description of the sample that was studied"""

identifier: Identifier = Field(nskey="schema")
sampleType: SampleType = Field(
description="Identifier for the sample characteristics (e.g., from OBI, Encode).",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 'characteristics' is too broad here -- better to have 'Identifier for the type of sample (e.g., from OBI, Encode).'

nskey="dandi",
)
assayType: Optional[List[AssayType]] = Field(
None, description="Identifier for the assay(s) used (e.g., OBI).", nskey="dandi"
)
anatomy: Optional[List[Anatomy]] = Field(
None,
description="Identifier for what organ the sample belongs "

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'Identifier for the organ from which the sample derives.' maybe?

"to. Use the most specific descriptor from sources such as UBERON.",
nskey="dandi",
)

wasDerivedFrom: Optional[List["BioSample"]] = Field(
None,
description="Describes the hierarchy of sample derivation or aggregation.",
nskey="prov",
)
wasAttributedTo: Optional[List[Participant]] = Field(
None,
description="Participant(s) or Subject(s) associated with this sample.",
nskey="prov",
)
sameAs: Optional[List[Identifier]] = Field(None, nskey="schema")
hasMember: Optional[List[Identifier]] = Field(None, nskey="prov")

_ldmeta = {
"rdfs:subClassOf": ["schema:Thing", "prov:Entity"],
"rdfs:label": "Information about the biosample.",
"nskey": "dandi",
}
6 changes: 6 additions & 0 deletions models/cell.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from pydantic import BaseModel


class Cell(BaseModel):
location: str
cellType: CellType
5 changes: 5 additions & 0 deletions models/cellbygene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class CellbyGene(BaseModel):
cell: Cell
5 changes: 5 additions & 0 deletions models/celltype.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class CellType(BaseModel):
name: str
5 changes: 5 additions & 0 deletions models/instrument.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class Instrument(BaseModel):
name: str
9 changes: 9 additions & 0 deletions models/location.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from pydantic import BaseModel


class Location(BaseModel):
photo: Photo
coordinates: [str, str]
atlasMap: dict(Atlas)
atlas: Atlas
overlappingLabels: [str, str]
74 changes: 74 additions & 0 deletions models/participant.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from dandischema import DandiBaseModel


class Participant(DandiBaseModel):
"""Description about the Participant or Subject studied.
The Participant or Subject can be any individual or synthesized Agent. The
properties of the Participant or Subject refers to information at the timepoint
when the Participant or Subject engaged in the production of data being described.
"""

identifier: Identifier = Field(nskey="schema")
altName: Optional[List[Identifier]] = Field(None, nskey="dandi")

strain: Optional[StrainType] = Field(
None,
description="Identifier for the strain of the participant or subject.",
nskey="dandi",
)
cellLine: Optional[Identifier] = Field(
None,
description="Cell line associated with the participant or subject.",
nskey="dandi",
)
vendor: Optional[Organization] = Field(None, nskey="dandi")
age: Optional[PropertyValue] = Field(
None,
description="A representation of age using ISO 8601 duration. This "
"should include a valueReference if anything other than "
"date of birth is used.",
nskey="dandi",
rangeIncludes="schema:Duration",
)

sex: Optional[SexType] = Field(
None,
description="Identifier for sex of the participant or subject if "
"available. (e.g. from OBI)",
nskey="dandi",
)
genotype: Optional[Union[List[GenotypeInfo], Identifier]] = Field(
None,
description="Genotype descriptor of participant or subject if available",
nskey="dandi",
)
species: Optional[SpeciesType] = Field(
None,
description="An identifier indicating the taxonomic classification of "
"the participant or subject.",
nskey="dandi",
)
disorder: Optional[List[Disorder]] = Field(
None,
description="Any current diagnosed disease or disorder associated with "
"the participant or subject.",
nskey="dandi",
)

relatedParticipant: Optional[List[RelatedParticipant]] = Field(
None,
description="Information about related participants or subjects in a "
"study or across studies.",
nskey="dandi",
)
sameAs: Optional[List[Identifier]] = Field(
None,
description="An identifier to link participants or subjects across datasets.",
nskey="schema",
)

_ldmeta = {
"rdfs:subClassOf": ["prov:Agent"],
"rdfs:label": "Information about the participant or subject.",
"nskey": "dandi",
}
23 changes: 23 additions & 0 deletions models/participant.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
id: https://bican.org/examples/participant
name: participant
prefixes:
linkml: https://w3id.org/linkml/
imports:
- linkml:types
default_range: string

classes:
Participant:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i had a chance to discus this with a few folks and there are couple of considerations that should be added to this.

  • age concepts vary by species
  • there are some components that should not change (datetime of birth) and some that could change (sex, weight, family, etc.,.)
  • we need to add concepts like littermates not just lineage, which is what relatedparticiant was focusing on. this could be a role added to relatedparticipant.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, some ages are measured from conception, some from birth -- some measured in days, some in weeks, some in years, etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@patrick-lloyd-ray - we think date of birth should capture most scenarios but is a sensitive field for humans. in dandi we use gestational reference and birth reference as two reference frames, and we are using the duration format for ISO8601 to allow for any age representation.

however age as a duration is also limited across species which have stages. also, we had to invent a format for age range (based on ISO8601), when precise age is not available. age is a complicated concept ;)

attributes:
identifier:
altName:
strain:
cellLine:
vendor:
age:
sex:
genotype:
species:
disorder:
relatedParticipant:
sameAs:
5 changes: 5 additions & 0 deletions models/protocol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class Protocol(BaseModel):
name: str
5 changes: 5 additions & 0 deletions models/provenance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class Provenance(BaseModel):
name: str
Empty file added models/semantic/__init__.py
Empty file.
Loading