Skip to content

SQLAlchemy proof-of-concept #1152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 28, 2024
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
9 changes: 9 additions & 0 deletions python/lib/db/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from sqlalchemy.orm import DeclarativeBase


class Base(DeclarativeBase):
"""
Base SQLAlchemy class that must be inherited by all the ORM model classes.
"""

pass
17 changes: 17 additions & 0 deletions python/lib/db/connect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from typing import Any
from sqlalchemy import create_engine
from sqlalchemy.orm import Session


default_port = 3306


def connect_to_db(credentials: dict[str, Any]):
host = credentials['host']
port = credentials['port']
username = credentials['username']
password = credentials['passwd']
database = credentials['database']
port = int(port) if port else default_port
engine = create_engine(f'mariadb+mysqlconnector://{username}:{password}@{host}:{port}/{database}')
return Session(engine)
51 changes: 51 additions & 0 deletions python/lib/db/orm/dicom_archive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from datetime import date, datetime
from typing import List, Optional
from sqlalchemy import String
from sqlalchemy.orm import Mapped, mapped_column, relationship
from lib.db.base import Base
import lib.db.orm.dicom_archive_file as db_dicom_archive_file
import lib.db.orm.dicom_archive_series as db_dicom_archive_series
import lib.db.orm.mri_upload as db_mri_upload


class DbDicomArchive(Base):
__tablename__ = 'tarchive'

id : Mapped[int] = mapped_column('TarchiveID', primary_key=True)
series : Mapped[List['db_dicom_archive_series.DbDicomArchiveSeries']] \
= relationship('DbDicomArchiveSeries', back_populates='archive')
files : Mapped[List['db_dicom_archive_file.DbDicomArchiveFile']] \
= relationship('DbDicomArchiveFile', back_populates='archive')
upload : Mapped[Optional['db_mri_upload.DbMriUpload']] \
= relationship('DbMriUpload', back_populates='dicom_archive')
study_uid : Mapped[str] = mapped_column('DicomArchiveID', type_ = String())
patient_id : Mapped[str] = mapped_column('PatientID')
patient_name : Mapped[str] = mapped_column('PatientName')
patient_birthdate : Mapped[Optional[date]] = mapped_column('PatientDoB')
patient_sex : Mapped[Optional[str]] = mapped_column('PatientSex')
neuro_db_center_name : Mapped[Optional[str]] = mapped_column('neurodbCenterName')
center_name : Mapped[str] = mapped_column('CenterName')
last_update : Mapped[Optional[date]] = mapped_column('LastUpdate')
date_acquired : Mapped[Optional[date]] = mapped_column('DateAcquired')
date_first_archived : Mapped[Optional[datetime]] = mapped_column('DateFirstArchived')
date_last_archived : Mapped[Optional[datetime]] = mapped_column('DateLastArchived')
acquisition_count : Mapped[int] = mapped_column('AcquisitionCount')
dicom_file_count : Mapped[int] = mapped_column('DicomFileCount')
non_dicom_file_count : Mapped[int] = mapped_column('NonDicomFileCount')
md5_sum_dicom_only : Mapped[Optional[str]] = mapped_column('md5sumDicomOnly')
md5_sum_archive : Mapped[Optional[str]] = mapped_column('md5sumArchive')
creating_user : Mapped[str] = mapped_column('CreatingUser')
sum_type_version : Mapped[int] = mapped_column('sumTypeVersion')
tar_type_version : Mapped[Optional[int]] = mapped_column('tarTypeVersion')
source_location : Mapped[str] = mapped_column('SourceLocation')
archive_location : Mapped[Optional[str]] = mapped_column('ArchiveLocation')
scanner_manufacturer : Mapped[str] = mapped_column('ScannerManufacturer')
scanner_model : Mapped[str] = mapped_column('ScannerModel')
scanner_serial_number : Mapped[str] = mapped_column('ScannerSerialNumber')
scanner_software_version : Mapped[str] = mapped_column('ScannerSoftwareVersion')
session_id : Mapped[Optional[int]] = mapped_column('SessionID')
upload_attempt : Mapped[int] = mapped_column('uploadAttempt')
create_info : Mapped[Optional[str]] = mapped_column('CreateInfo')
acquisition_metadata : Mapped[str] = mapped_column('AcquisitionMetadata')
date_sent : Mapped[Optional[datetime]] = mapped_column('DateSent')
pending_transfer : Mapped[int] = mapped_column('PendingTransfer')
25 changes: 25 additions & 0 deletions python/lib/db/orm/dicom_archive_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from typing import Optional
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import ForeignKey
from lib.db.base import Base
import lib.db.orm.dicom_archive as db_dicom_archive
import lib.db.orm.dicom_archive_series as db_dicom_archive_series


class DbDicomArchiveFile(Base):
__tablename__ = 'tarchive_files'

id : Mapped[int] = mapped_column('TarchiveFileID', primary_key=True)
archive_id : Mapped[int] = mapped_column('TarchiveID', ForeignKey('tarchive.TarchiveID'))
archive : Mapped['db_dicom_archive.DbDicomArchive'] \
= relationship('DbDicomArchive', back_populates='files')
series_id : Mapped[Optional[int]] \
= mapped_column('TarchiveSeriesID', ForeignKey('tarchive_series.TarchiveSeriesID'))
series : Mapped[Optional['db_dicom_archive_series.DbDicomArchiveSeries']] \
= relationship('DbDicomArchiveSeries', back_populates="files")
series_number : Mapped[Optional[int]] = mapped_column('SeriesNumber')
series_description : Mapped[Optional[str]] = mapped_column('SeriesDescription')
file_number : Mapped[Optional[int]] = mapped_column('FileNumber')
echo_number : Mapped[Optional[int]] = mapped_column('EchoNumber')
md5_sum : Mapped[str] = mapped_column('Md5Sum')
file_name : Mapped[str] = mapped_column('FileName')
28 changes: 28 additions & 0 deletions python/lib/db/orm/dicom_archive_series.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import List, Optional
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import ForeignKey
from lib.db.base import Base
import lib.db.orm.dicom_archive as db_dicom_archive
import lib.db.orm.dicom_archive_file as db_dicom_archive_file


class DbDicomArchiveSeries(Base):
__tablename__ = 'tarchive_series'

id : Mapped[int] = mapped_column('TarchiveSeriesID', primary_key=True)
archive_id : Mapped[int] = mapped_column('TarchiveID', ForeignKey("tarchive.TarchiveID"))
archive : Mapped['db_dicom_archive.DbDicomArchive'] \
= relationship('DbDicomArchive', back_populates="series")
files : Mapped[List['db_dicom_archive_file.DbDicomArchiveFile']] \
= relationship('DbDicomArchiveFile', back_populates="series")
series_number : Mapped[int] = mapped_column('SeriesNumber')
series_description : Mapped[Optional[str]] = mapped_column('SeriesDescription')
sequence_name : Mapped[Optional[str]] = mapped_column('SequenceName')
echo_time : Mapped[Optional[float]] = mapped_column('EchoTime')
repetition_time : Mapped[Optional[float]] = mapped_column('RepetitionTime')
inversion_time : Mapped[Optional[float]] = mapped_column('InversionTime')
slice_thickness : Mapped[Optional[float]] = mapped_column('SliceThickness')
phase_encoding : Mapped[Optional[str]] = mapped_column('PhaseEncoding')
number_of_files : Mapped[int] = mapped_column('NumberOfFiles')
series_uid : Mapped[Optional[str]] = mapped_column('SeriesUID')
modality : Mapped[Optional[str]] = mapped_column('Modality')
29 changes: 29 additions & 0 deletions python/lib/db/orm/mri_upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from datetime import datetime
from typing import Optional
from sqlalchemy import ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from lib.db.base import Base
import lib.db.orm.dicom_archive as db_dicom_archive


class DbMriUpload(Base):
__tablename__ = 'mri_upload'

id : Mapped[int] = mapped_column('UploadID', primary_key=True)
uploaded_by : Mapped[str] = mapped_column('UploadedBy')
upload_date : Mapped[Optional[datetime]] = mapped_column('UploadDate')
upload_location : Mapped[str] = mapped_column('UploadLocation')
decompressed_location : Mapped[str] = mapped_column('DecompressedLocation')
insertion_complete : Mapped[bool] = mapped_column('InsertionComplete')
inserting : Mapped[Optional[bool]] = mapped_column('Inserting')
patient_name : Mapped[str] = mapped_column('PatientName')
number_of_minc_inserted : Mapped[Optional[int]] = mapped_column('number_of_mincInserted')
number_of_minc_created : Mapped[Optional[int]] = mapped_column('number_of_mincCreated')
dicom_archive_id : Mapped[Optional[int]] \
= mapped_column('TarchiveID', ForeignKey('tarchive.TarchiveID'))
dicom_archive : Mapped[Optional['db_dicom_archive.DbDicomArchive']] \
= relationship('DicomArchive', back_populates='upload')
session_id : Mapped[Optional[int]] = mapped_column('SessionID')
is_candidate_info_validated : Mapped[Optional[bool]] = mapped_column('IsCandidateInfoValidated')
is_dicom_archive_validated : Mapped[bool] = mapped_column('IsTarchiveValidated')
is_phantom : Mapped[str] = mapped_column('IsPhantom')
44 changes: 44 additions & 0 deletions python/lib/db/orm/session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from datetime import date, datetime
from typing import Optional
from sqlalchemy.orm import Mapped, mapped_column
from lib.db.base import Base


class DbSession(Base):
__tablename__ = 'session'

id : Mapped[int] = mapped_column('ID', primary_key=True)
cand_id : Mapped[int] = mapped_column('CandID')
center_id : Mapped[int] = mapped_column('CenterID')
project_id : Mapped[int] = mapped_column('ProjectID')
visit_no : Mapped[Optional[int]] = mapped_column('VisitNo')
visit_label : Mapped[str] = mapped_column('Visit_label')
cohort_id : Mapped[int] = mapped_column('CohortID')
submitted : Mapped[str] = mapped_column('Submitted')
current_stage : Mapped[str] = mapped_column('Current_stage')
date_stage_change : Mapped[Optional[date]] = mapped_column('Date_stage_change')
screening : Mapped[Optional[str]] = mapped_column('Screening')
date_screening : Mapped[date] = mapped_column('Date_screening')
visit : Mapped[Optional[str]] = mapped_column('Visit')
date_visit : Mapped[Optional[date]] = mapped_column('Date_visit')
date_status_change : Mapped[Optional[date]] = mapped_column('Date_status_change')
approval : Mapped[Optional[str]] = mapped_column('Approval')
date_approval : Mapped[Optional[date]] = mapped_column('Date_approval')
active : Mapped[str] = mapped_column('Active')
date_active : Mapped[Optional[date]] = mapped_column('Date_active')
registered_by : Mapped[Optional[str]] = mapped_column('RegisteredBy')
user_id : Mapped[str] = mapped_column('UserID')
date_registered : Mapped[Optional[date]] = mapped_column('Date_registered')
test_date : Mapped[int] = mapped_column('Testdate')
hardcopy_request : Mapped[str] = mapped_column('Hardcopy_request')
bvl_qc_status : Mapped[Optional[str]] = mapped_column('BVLQCStaus')
bvl_qc_type : Mapped[Optional[str]] = mapped_column('BVLQCType')
bvl_qc_exclusion : Mapped[Optional[str]] = mapped_column('BVLQCExclusion')
qcd : Mapped[Optional[str]] = mapped_column('QCd')
scan_done : Mapped[Optional[str]] = mapped_column('Scan_done')
mri_qc_status : Mapped[str] = mapped_column('MRIQCStatus')
mri_qc_pending : Mapped[str] = mapped_column('MRIQCPending')
mri_qc_first_change_time : Mapped[Optional[datetime]] = mapped_column('MRIQCFirstChange')
mri_qc_last_change_time : Mapped[Optional[datetime]] = mapped_column('MRIQCLastChange')
mri_caveat : Mapped[str] = mapped_column('MRICaveat')
language_id : Mapped[Optional[int]] = mapped_column('languageID')
25 changes: 13 additions & 12 deletions python/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
boto3
flake8
google
mat73
matplotlib
mne
mne-bids>=0.6
protobuf>=3.0.0
pybids==0.14.0
mysqlclient
mysql-connector
google
matplotlib
nose
mysqlclient
nilearn
scikit-learn
virtualenv
python-dateutil
nibabel
nose
numpy
protobuf>=3.0.0
pybids==0.17.0
python-dateutil
scikit-learn
scipy
flake8
boto3
mat73
sqlalchemy>=2.0.0
virtualenv
Loading