Skip to content
David Sarrut edited this page Jun 23, 2015 · 23 revisions

Simplified API documentation.


Core

In the following code, we omit the namespace, use:

    using namespace syd;

Database manager

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);

Functions common to all databases (CRUD)

Basics operations are 'CRUD': Create, Read, Update and Delete.

Get information:

    // 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();

Create

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

Query:

    // 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:

Update a record in the database.

    db->Update<Patient>(patient);
    db->Update<Patient>(vector_of_patients);

Delete:

    // 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.

Exceptions

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();

StandardDatabase

List of tables: TODO

Some functions related to tables

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);

Records deletion

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

DicomSerieBuilder

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();

ImageBuilder

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);

TimepointBuilder

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);
Clone this wiki locally