-
Notifications
You must be signed in to change notification settings - Fork 0
Simplified API documentation.
In the following code, we omit the namespace, use:
using namespace syd;
Get instance:
DatabaseManager * m = DatabaseManager::GetInstance();
auto & list = m->GetDatabaseSchemas();
Create a database:
Database * db = m->Create("StandardDatabase", dbname, folder);
Read a database:
Database * db = m->Read(dbname);
StandardDatabase * db = m->Read<StandardDatabase>(dbname);
Basics operations are 'CRUD': Create, Read, Update and Delete.
// Get the name of the sql schema, i.e. "StandardDatabase"
std::string s = db->GetDatabaseSchema();
// Get the filename i.e. test.db
std::string s = db->GetFilename();
// Get the image folder of the db, relative to the test.db folder
std::string s = db->GetDBFolder();
// Get the image folder (absolute path)
std::string s = db->GetAbsoluteDBFolder();
Insert an element (with table Patient as example but could be other tables):
db->Insert<Patient>(patient);
db->Insert<Patient>(vector_of_patients); // vector of elements
TableElement * e = db->InsertFromArg("Patient", string_vector); //FIXME
// Get all patients
db->Query<Patient>(vector_of_patients);
// Get all patients matching a query
typedef odb::query<Patient> QueryType;
QueryType q = (QueryType::name == "toto" and QueryType::age < 20)
db->Query<Patient>(q, vector_of_patients);
// Get only one patient matching the query
patient = db->QueryOne(q);
// Get only one patient with its id
patient = db->QueryOne(id);
// Others functions
int n = db->Count(q);
if (db->IfExist<Patient>(id)) { ... }
Update a record in the database.
db->Update<Patient>(patient);
db->Update<Patient>(vector_of_patients);
// Delete by knowing the type of the table
db->Delete<Patient>(patient);
db->Delete<Patient>(vector_of_patients);
// Delete with the name of the table and id
db->Delete("Patient", id);
db->Delete("Patient", vector_of_ids);
Deleting a record can be complicated due to foreign keys (FK) in some tables. Two mecanisms are provided:
- On cascade delete. When a table has a FK, it is possible to choose to delete the record if the record corresponding to the FK is deleted. This is done with the following pragma :
#pragma db on_delete(cascade)
. See table Injection in standard database for example. - In other circumstance, additional tasks must be performed when a record is deleted (for example removing the file on disk when an image is deleted). This is done with the following virtual function:
virtual void OnDelete(const std::string & table_name, TableElementBase * e);
This callback is called every time a record (e) from the table table_name is deleted. See StandardDatabase for example.
Every access to a database can fail for one reason, you can test the result with a try/catch. See here:
try {
// Here, access to the database (insert, query etc)
}
catch (const Exception & e) {
std::cout << e->what(); // Go here if something wrong
}
For debug, you can access to the last SQL query with:
std::string s = db->GetLastSQLQuery();
List of tables: TODO
Convenient functions for common queries (to retrieve a patient from his name for example):
// Let db be a syd::Database
Patient patient;
FindPatientByNameOrStudyId(patient, db, "toto");
std::vector<Tag> tags;
std::string tag_names; // separated by space
FindTags(tags, db, tag_names);
When records are delete, a mecanism takes care about dependencies.
Policy:
- Image: also delete Files.
- Files: also delete the files on disk, the Image and the DicomFile
- DicomFile: also delete the File, the DicomSerie
- DicomSerie: also delete the DicomFiles
- Injection: also delete DicomSeries and Timepoint
- Radionuclide: also delete the Injection
- Patient: also delete the Injection
- Tag : TODO
- Timepoint: TODO
Create an object DicomSerieBuilder and set the basics informations:
DicomSerieBuilder b(db);
b.SetInjection(injection);
b.SetForcePatientFlag(true);
b.SearchForFilesInFolder(folder, files);
Main function to create a DicomSerie from a file. Checks if the file is not already in the db, guess if the file should be added to an existing DicomSerie or if a new DicomSerie. The DicomSerie is not yet inserted into the db. See next function.
for(auto f:files) b.CreateDicomSerieFromFile(f.c_str());
Once the files have been created (previous function), insert all created series in the db.
b.InsertDicomSeries();
The class ImageBuilder allow to to create record in the Image table and the associated mhd/raw files.
Convert a dicom image to a mhd (and insert an Image)
ImageBuilder b(db);
syd::Image image = builder.InsertImage(d);
Create and insert a ROI as a binary mask: RoiMaskImage. Need a filename (mhd) and a DicomSerie to be linked with.
ImageBuilder b(db);
syd::Image image = b.InsertRoiMaskImage(dicom, roitype, filename);
It is also possible to create an image by stitching two dicom together:
ImageBuilder b(db);
syd::Image image = builder.InsertStitchedImage(tag, dicom1, dicom2);
It is recommended to add tag to images:
Tag t; // get a tag somehow
image.AddTag(t);
db->Update(image);
Create an object TimepointBuilder and set the basics informations:
TimepointBuilder b(db);
b.SetTag(tag);
b.SetIntraTimepointMaxHourDiff(1); // 1 hour max difference between
Consider some DicomSerie and create the corresponding Timepoints. Guess that two dicoms with more than 1 hour acquisition time difference are not in the same Timepoint.
for(auto d:dicom_series) b.InsertDicomSerie(d);
Other functions:
GuessState s = b.GuessTimepointForThisDicomSerie(dicom_serie, vector_of_timepoints);
GuessState s = b.GuessIfDicomCanBeInThisTimepoint(dicom_serie, timepoint);
timepoint = b.CreateTimepoint(dicom_serie);
b.AddDicom(timepoint, dicom_serie);