Beispiel #1
0
bool medDatabaseController::createConnection(void)
{
    medStorage::mkpath(medStorage::dataLocation() + "/");

    if (this->m_database.databaseName().isEmpty())
        this->m_database = QSqlDatabase::addDatabase("QSQLITE");
    this->m_database.setDatabaseName(medStorage::dataLocation() + "/" + "db");

    if (!m_database.open()) {
        dtkDebug() << DTK_COLOR_FG_RED << "Cannot open database: Unable to establish a database connection." << DTK_NO_COLOR;
        return false;
    }
    else
    {
        dtkDebug() << "Database opened at: " << m_database.databaseName();
        d->isConnected = true;
    }

    createPatientTable();
    createStudyTable();
    createSeriesTable();
    createImageTable();

    // optimize speed of sqlite db
    QSqlQuery query(m_database);
    if ( !query.exec( QLatin1String( "PRAGMA synchronous = 0" ) ) ) {
        dtkDebug() << "Could not set sqlite synchronous mode to asynchronous mode.";
    }
    if ( !query.exec( QLatin1String( "PRAGMA journal_mode=wal" ) ) ) {
        dtkDebug() << "Could not set sqlite write-ahead-log journal mode";
    }


    return true;
}
Beispiel #2
0
medDataIndex medDatabaseController::indexForSeries(int id)
{
    QSqlQuery query(m_database);

    QVariant patientId = -1;
    QVariant   studyId = -1;

    query.prepare("SELECT study FROM series WHERE id = :id");
    query.bindValue(":id", id);
    if(!query.exec())
    {
        dtkDebug() << DTK_COLOR_FG_RED << query.lastError() << DTK_NO_COLOR;
    }

    if(query.first())
        studyId = query.value(0);

    query.prepare("SELECT patient FROM study WHERE id = :id");
    query.bindValue(":id", studyId);
    if(!query.exec())
    {
        dtkDebug() << DTK_COLOR_FG_RED << query.lastError() << DTK_NO_COLOR;
    }

    if(query.first())
        patientId = query.value(0);

    return medDataIndex::makeSeriesIndex(this->dataSourceId(), patientId.toInt(), studyId.toInt(), id);
}
Beispiel #3
0
    void run(void) {
        QTime time;
        dtkDistributedCommunicator *comm = dtkDistributed::communicator::instance();
        dtkDebug() << comm->wid();
        dtkDebug() << comm->size();
        dtkDistributedSlave slave;

        if (comm->rank() == 0) {
            slave.connectFromJob(server);
        }

        QThread::sleep(5);

        if (comm->rank() == 0) {
            QString hello = "I'm the master slave, we are " + QString::number(comm->size())+ " slaves";
            QVariant v(hello);
            dtkDistributedMessage msg(dtkDistributedMessage::DATA,slave.jobId(),dtkDistributedMessage::CONTROLLER_RANK, v);

            msg.send(slave.socket());
            slave.socket()->flush();
            qDebug() << "message sent to controller";
        }

        QThread::sleep(5);

        slave.disconnectFromJob(server);
    }
void hdf5IoDataModel::fileClose(void)
{
    //close all the open datasets
    {
        QHash<QString, hid_t>::iterator it;
        for(it = d->dataset_hash.begin(); it != d->dataset_hash.end(); ++it) {
            dtkDebug() << "closing dataset" << it.key();
            H5Dclose(it.value());
        }
        d->dataset_hash.clear();
    }

    //close all the open groups
    {
        QHash<QString, hid_t>::iterator it;
        for(it = d->group_hash.begin(); it != d->group_hash.end(); ++it) {
            dtkDebug() << "closing group" << it.key();
            H5Gclose(it.value());
        }
        d->group_hash.clear();
    }

    H5Fclose(d->file_id);
    d->file_is_open=false;

}
Beispiel #5
0
bool itkDataSHImageReader::read (const QString &path)
{
    this->readInformation ( path );
	
    dtkDebug() << "Read with: " << this->description();

    if (medAbstractData *medData = dynamic_cast<medAbstractData*>(this->data()) ) {

        if (medData->identifier()=="itkDataSHImageDouble3") {
            typedef itk::VectorImage<double, 3> SHImageType;

            typedef itk::ImageFileReader<SHImageType> ReaderType;

            SHImageType::Pointer image = 0;

            ReaderType::Pointer reader = ReaderType::New();
            reader->SetFileName ( path.toLatin1().constData() );
            try {
                reader->Update();
            }
            catch (itk::ExceptionObject &e) {
                dtkDebug() << e.GetDescription();
                return false;
            }
            image = reader->GetOutput();
            medData->setData (image);
        }
        else if (medData->identifier()=="itkDataSHImageFloat3") {
            typedef itk::VectorImage<float, 3> SHImageType;

            typedef itk::ImageFileReader<SHImageType> ReaderType;

            SHImageType::Pointer image = 0;

            ReaderType::Pointer reader = ReaderType::New();
            reader->SetFileName ( path.toLatin1().constData() );
            try {
                reader->Update();
            }
            catch (itk::ExceptionObject &e) {
                dtkDebug() << e.GetDescription();
                return false;
            }
            image = reader->GetOutput();
            medData->setData (image);

        }
        else {
            dtkDebug() << "Unsupported data type";
            return false;
        }
    }
    else {
        dtkDebug() << "No data set or could not create one";
        return false;
    }

    return true;
    
}
void dtkComposerEvaluatorProcess::run(void)
{

    d->status = 0;
    if (!d->factory) {
        dtkFatal() << "No factory set ! abort process execution";
        d->status = 1;
        return;
    }

    // int rank = d->comm->rank();
    // int size = d->comm->size();
    bool new_composition;

    QByteArray data;

    d->parent_comm->broadcast(data,0);

    dtkDebug() << "Ok, composition received, parse" ;

    QString composition(data);

    if (composition == "not-modified") {
        dtkInfo() << "composition hasn't changed";
        new_composition = false;
    } else {
        new_composition = true;
    }

    if (new_composition && composition.isEmpty()) {
        dtkFatal() << "Empty composition, abort" ;
        d->status = 1;
        return;
    }

    if (new_composition) {
        dtkDebug() << "parse composition" ;
        d->reader->readString(composition);

        // if (dtkComposerNodeSpawn *spawn = dynamic_cast<dtkComposerNodeSpawn *>(d->scene->root()->nodes().first()->wrapee())) {
        //     spawn->setCommunicator(d->parent_comm);
        //     spawn->setInternalCommunicator(d->comm);
        //     spawn->setApplication(d->application);
        // } else {
        //     dtkFatal() <<  "Can't find spawn node in composition, abort";
        //     return 1;
        // }
    }
    dtkDebug() << "run composition" ;
    d->evaluator->run();
    dtkDebug() << "finished" ;

}
Beispiel #7
0
medDataIndex medDatabaseController::indexForStudy(const QString &patientName, const QString &studyName)
{
    medDataIndex index = this->indexForPatient(patientName);
    if (!index.isValid())
        return index;

    QSqlQuery query(m_database);

    QVariant patientId = index.patientId();
    QVariant studyId   = -1;

    query.prepare("SELECT id FROM study WHERE patient = :id AND name = :name");
    query.bindValue(":id",   patientId);
    query.bindValue(":name", studyName);

    if(!query.exec())
    {
        dtkDebug() << DTK_COLOR_FG_RED << query.lastError() << DTK_NO_COLOR;
    }

    if(query.first()) {
        studyId = query.value(0);
        index.setStudyId(studyId.toInt());
        return index;
    }

    return medDataIndex();
}
bool medQtDataImageWriter::canWrite( const QString& path )
{
    QFileInfo fi ( path );
    QString suffix = fi.suffix();

    QByteArray fmtString;
    const QString lowerSuffix = suffix.toLower();
    FormatInfoList::const_iterator formatToUse = m_supportedExtensionList.begin();
    for ( ; formatToUse != m_supportedExtensionList.end() ; ++formatToUse ){
        if (formatToUse->fileExtension == suffix )
            break;
    }
    if ( formatToUse != m_supportedExtensionList.end() ) {
        fmtString = formatToUse->formatName;
    } else {
        dtkDebug() << "Filename does not have a supported extension";
        return false;
    }

    QScopedPointer<QImageWriter> writer(new QImageWriter( path ) );
    if ( fmtString.size() ) {
        writer->setFormat( fmtString );
    }
    
    return writer->canWrite();
}
Beispiel #9
0
medDataIndex medDatabaseController::indexForImage(const QString &patientName, const QString &studyName,
                                                  const QString &seriesName,  const QString &imageName)
{
    medDataIndex index = this->indexForSeries(patientName, studyName, seriesName);
    if (!index.isValid())
        return index;

    QSqlQuery query(m_database);

    QVariant seriesId = index.seriesId();

    query.prepare("SELECT id FROM image WHERE series = :id AND name = :name");
    query.bindValue(":id",   seriesId);
    query.bindValue(":name", imageName);

    if(!query.exec())
    {
        dtkDebug() << DTK_COLOR_FG_RED << query.lastError() << DTK_NO_COLOR;
    }

    if(query.first()) {
        QVariant imageId = query.value(0);
        index.setImageId(imageId .toInt());
        return index;
    }

    return medDataIndex();
}
void medJobRunner::run()
{
    emit m_job->running(true);
    medAbstractJob::medJobExitStatus jobExitStatus = medAbstractJob::MED_JOB_EXIT_FAILURE;
    try
    {
        jobExitStatus = m_job->run();
        if(jobExitStatus == medAbstractJob::MED_JOB_EXIT_CANCELLED)
        {
            dtkDebug() << "job aborted (cancelled)"
                       << m_job->caption() << m_job;
        }
    }
    catch(std::exception &err)
    {
        QString errorMessage = QString::fromLatin1(err.what());
        dtkWarn() << "Error occured while runing job"
                  << m_job->caption() << m_job
                  << "\n\t" <<errorMessage;

        emit exceptionCaught(errorMessage);
    }
    catch(...)
    {
        dtkWarn() << "Error occured while runing job"
                  << m_job->caption() << m_job;
    }
    emit m_job->finished(jobExitStatus);
    emit m_job->running(false);
}
void itkDataSHImageVtkViewInteractor::setInputData(medAbstractData *data)
{
    medAbstractInteractor::setInputData(data);

    if (!data || !data->data())
        return;

    //  Two itk SH image formats are supported
    //  we need to convert them to vtkStructuredPoints so it's understood by the SH manager

    const QString& identifier = data->identifier();
    if (identifier=="itkDataSHImageFloat3")
        d->setVTKFilter<itk::VectorImage<float,3> >(data,d->filterFloat);
    else if (identifier=="itkDataSHImageDouble3")
        d->setVTKFilter<itk::VectorImage<double,3> >(data,d->filterDouble);
    else
    {
        dtkDebug() << "Unrecognized SH data type: " << identifier;
        return;
    }

    d->actorProperty = itkDataSHImageVtkViewInteractorPrivate::PropertySmartPointer::New();
    d->manager->GetSHVisuManagerAxial()->GetActor()->SetProperty( d->actorProperty );
    d->manager->GetSHVisuManagerSagittal()->GetActor()->SetProperty( d->actorProperty );
    d->manager->GetSHVisuManagerCoronal()->GetActor()->SetProperty( d->actorProperty );

    setupParameters();
}
Beispiel #12
0
void dtkDistributedSlave::disconnect(const QUrl& server)
{
    dtkDebug() << "disconnect from connect" << server.toString();
    d->socket->disconnectFromHost();

    emit disconnected(server);
}
Beispiel #13
0
void dtkAbstractObject::setProperty(const QString& key, const QString& value)
{
    if(!d_ptr->values.contains(key)) {
    	dtkDebug() << this->metaObject()->className() << " has no such property:" << key;
    	return;
    }

    if(!d_ptr->values.value(key).contains(value)) {
    	dtkDebug() << this->metaObject()->className() << " has no such value:" << value << " for key: " << key;
    	return;
    }

    d_ptr->properties.insert(key, value);

    onPropertySet(key, value);

    emit propertySet(key, value);
}
Beispiel #14
0
QStringList dtkAbstractObject::metadatas(const QString& key) const
{
    if(!d_ptr->metadatas.contains(key)) {
	dtkDebug() << this->metaObject()->className() << "has no such property:" << key;
	return QStringList();
    }

    return d_ptr->metadatas.value(key);
}
void dtkDistributedServerDaemon::discard(void)
{
    dtkDebug() << DTK_PRETTY_FUNCTION << "-- Disconnection --";

    dtkDistributedSocket *socket = (dtkDistributedSocket *)sender();
    socket->deleteLater();

    dtkDistributedServiceBase::instance()->logMessage("Connection closed");
}
Beispiel #16
0
 bool envString (const QString &var, QString &value)
 {
     value = qgetenv (var.toLatin1().constData()).constData();
     if (value.isEmpty()) {
         return false;
         dtkDebug() << var + " is not defined";
     }
     return true;
 }
Beispiel #17
0
bool itkDataSHImageReader::readInformation (const QString &path)
{
    itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(path.toLatin1().constData(),
                                                                           itk::ImageIOFactory::ReadMode);
    
    imageIO->SetFileName ( path.toLatin1().constData() );
    try {
        imageIO->ReadImageInformation();
    }
    catch (itk::ExceptionObject &e) {
        dtkDebug() << e.GetDescription();
        return false;
    }
    
    medAbstractData* medData = dynamic_cast<medAbstractData*>(this->data());

    if (!medData) {

        switch (imageIO->GetComponentType()) {
        //            dtkDebug() << imageIO->GetPixelTypeAsString() << imageIO->GetComponentTypeAsString();

        case itk::ImageIOBase::FLOAT:
            medData = medAbstractDataFactory::instance()->create ("itkDataSHImageFloat3");
            if (medData)
                this->setData ( medData );
            break;

	    case itk::ImageIOBase::DOUBLE:
            medData = medAbstractDataFactory::instance()->create ("itkDataSHImageDouble3");
            if (medData)
                this->setData ( medData );
			break;

	    default:
	        dtkDebug() << "Unsupported component type";
			return false ;
		}
    }

    if (medData) {
        medData->addMetaData ("FilePath", QStringList() << path);
    }
    return true;
}
Beispiel #18
0
/*!
 *  The reference count is checked, and a warning message is output if the reference count is not valid.
 *  There are two valid reference count values at destruction time :<br>
 *  0 : The object used reference counting, and is no longer referred by any object.<br>
 *  1 : This occurs if the object was never reference counted, and delete(Later) was manually called.<br>
 */
dtkAbstractObject::~dtkAbstractObject(void)
{
    if ( d_ptr->count.load() != 0){
        dtkDebug() << "Warning : deleting object of type " << this->metaObject()->className() << " with non-zero reference count";
    }

    delete d_ptr;

    d_ptr = NULL;
}
Beispiel #19
0
void itkDataSHImageFloat3::setData(void *data)
{
    typedef itkDataSHImageFloat3Private::SHImageType SHImageType;

    if( SHImageType* shs = dynamic_cast<SHImageType*>( (itk::Object*)(data) ) ){
        d->shs = shs;
    }
    else
      dtkDebug() << "Cannot cast pointer to correct SH float type";
}
void medVtkViewItkDataImage4DInteractor::setInputData(medAbstractData *data)
{
    d->imageData = dynamic_cast<medAbstractImageData *>(data);
    if(!d->imageData)
        return;

    if( data->identifier().contains("itkDataImage") &&  d->imageData->Dimension() == 4 )
    {
        int layer = d->view->layer(data);

        if (SetViewInput(data, layer) )
        {
            d->imageData->addMetaData("SequenceDuration", QString::number(m_poConv->getTotalTime()));
            d->imageData->addMetaData("SequenceFrameRate", QString::number((double)(m_poConv->getNumberOfVolumes() -1 )/ (double)m_poConv->getTotalTime()));

            dtkDebug() << "SequenceDuration" << m_poConv->getTotalTime();
            dtkDebug() << "SequenceFrameRate" <<(double)(m_poConv->getNumberOfVolumes() -1)/ m_poConv->getTotalTime();

            d->view2d->GetImageActor(d->view2d->GetCurrentLayer())->GetProperty()->SetInterpolationTypeToCubic();
            initParameters(d->imageData);

            double* range = m_poConv->getCurrentScalarRange();
            d->view2d->SetColorRange(range);
            this->initWindowLevelParameters(range);

            if(d->view->layer(d->imageData) == 0)
            {
                switch(d->view2d->GetViewOrientation())
                {
                case vtkImageView2D::VIEW_ORIENTATION_AXIAL:
                    d->view->setOrientation(medImageView::VIEW_ORIENTATION_AXIAL);
                    break;
                case vtkImageView2D::VIEW_ORIENTATION_SAGITTAL:
                    d->view->setOrientation(medImageView::VIEW_ORIENTATION_SAGITTAL);
                    break;
                case vtkImageView2D::VIEW_ORIENTATION_CORONAL:
                    d->view->setOrientation(medImageView::VIEW_ORIENTATION_CORONAL);
                    break;
                }
            }
        }
    }
}
Beispiel #21
0
void itkDataTensorImageFloat3::setData(void *data)
{
    typedef itkDataTensorImageFloat3Private::TensorImageType TensorImageType;

    if( TensorImageType* tensors = dynamic_cast<TensorImageType*>( (itk::Object*)(data) ) ){
        d->tensors = tensors;
    }
    else
      dtkDebug() << "Cannot cast pointer to correct tensor type";
}
bool vtkDataMeshReader::read(const QString& path) {
    setProgress(0);
    readInformation(path);
    setProgress(50);

    dtkDebug() << "Can read with: " << identifier();

    if (medAbstractData * medData = dynamic_cast<medAbstractData*>(data()))
    {
        if (!(medData->identifier() == "vtkDataMesh"))
            return false;

        vtkMetaDataSet * dataSet = NULL;
        if (vtkMetaVolumeMesh::CanReadFile(path.toLocal8Bit().constData()) != 0)
        {
            dataSet = vtkMetaVolumeMesh::New();
        }
        else if ( vtkMetaSurfaceMesh::CanReadFile(path.toLocal8Bit().constData()) != 0)
        {
            dataSet = vtkMetaSurfaceMesh::New();
        }
        else
        {
            dtkDebug() << "Loading the vtkDataMesh failed, it's neither a surface or volume mesh !";
            return false;
        }

        try
        {
            dataSet->Read(path.toLocal8Bit().constData());
        } catch (...)
        {
            dtkDebug() << "Loading the vtkDataMesh failed, error while parsing !";
            return false;
        }

        medData->setData(dataSet);
    }

    setProgress(100);
    return true;
}
Beispiel #23
0
void dtkDistributedSlave::connectFromJob(const QUrl& server)
{
    dtkDistributedCommunicator *comm = dtkDistributed::communicator::instance();

    if (comm->rank() == 0) {
        // the server waits for the jobid in stdout
        std::cout << QString("DTK_JOBID="+jobId()).toStdString() << std::endl << std::flush;

        QUrl url(server);

        dtkDebug() << "Running on master, connect to remote server" << server;
        connect(url);
        dtkDebug() << "slave connected to server " << isConnected();

        if (isConnected()) {
            dtkDistributedMessage msg(dtkDistributedMessage::SETRANK,jobId(),dtkDistributedMessage::SLAVE_RANK);
            msg.send(socket());
        }
    }
}
void dtkDistributedServerDaemon::incomingConnection(qintptr descriptor)
{
    dtkDebug() << DTK_PRETTY_FUNCTION << "-- Connection -- " << descriptor ;

    dtkDistributedSocket *socket = new dtkDistributedSocket(this);
    connect(socket, SIGNAL(readyRead()), this, SLOT(read()));
    connect(socket, SIGNAL(disconnected()), this, SLOT(discard()));
    socket->setSocketDescriptor(descriptor);

    dtkDistributedServiceBase::instance()->logMessage("New connection");
}
dtkDistributedServerDaemon::dtkDistributedServerDaemon(quint16 port, QObject *parent) : QTcpServer(parent), d(new dtkDistributedServerDaemonPrivate)
{
    d->manager = NULL;

    if (!this->listen(QHostAddress::Any, port)) {
        dtkError() << "Can't listen on port"  << port << ", aborting";
        exit(1);
    } else {
        dtkDebug() << "OK, server is waiting for incoming connection on port"  << port ;
    }

    dtkDistributedServiceBase::instance()->logMessage("Server daemon listening on port " + QString::number(port));
}
Beispiel #26
0
bool itkDataImageWriterBase::write(const QString& path)
{
    if (!this->data())
        return false;

    if (this->io.IsNull())
        return false;

    try {

        if (!(write_image<3,unsigned char>(path,"itkDataImageUChar3")   ||
              write_image<3,char>(path,"itkDataImageChar3")             ||
              write_image<3,unsigned short>(path,"itkDataImageUShort3") ||
              write_image<4,unsigned short>(path,"itkDataImageUShort4") ||
              write_image<4,unsigned int>(path,"itkDataImageUInt4")     ||
              write_image<4,unsigned long>(path,"itkDataImageULong4")   ||
              write_image<4,unsigned char>(path,"itkDataImageUChar4")   ||
              write_image<4,char>(path,"itkDataImageChar4")             ||
              write_image<4,long>(path,"itkDataImageLong4")             ||
              write_image<4,int>(path,"itkDataImageInt4")               ||
              write_image<3,short>(path,"itkDataImageShort3")           ||
              write_image<4,short>(path,"itkDataImageShort4")           ||
              write_image<3,unsigned int>(path,"itkDataImageUInt3")     ||
              write_image<3,int>(path,"itkDataImageInt3")               ||
              write_image<3,unsigned long>(path,"itkDataImageULong3")   ||
              write_image<3,long>(path,"itkDataImageLong3")             ||
              write_image<3,float>(path,"itkDataImageFloat3")           ||
              write_image<4,float>(path,"itkDataImageFloat4")           ||
              write_image<3,double>(path,"itkDataImageDouble3")         ||
              write_image<4,double>(path,"itkDataImageDouble4")         ||
              write_image<3,itk::Vector<unsigned char,3> >(path,"itkDataImageVectorUChar3") || //    Added by Theo.
              write_image<3,itk::Vector<float,3> >(path,"itkDataImageVectorFloat3") ||
              write_image<3,itk::Vector<double,3> >(path,"itkDataImageVectorDouble3") ||
              write_image<3,itk::RGBAPixel<unsigned char> >(path,"itkDataImageRGBA3") ||
              write_image<3,itk::RGBPixel<unsigned char> >(path,"itkDataImageRGB3")))
        {
            dtkWarn() << "Unrecognized pixel type";
            return false;
        }

    } catch(itk::ExceptionObject &e) {
        dtkDebug() << e.GetDescription();
        return false;
    }


    return true;
}
Beispiel #27
0
void medTractographyProcessNode::run()
{
    if (d->input.isEmpty())
    {
        dtkDebug() << Q_FUNC_INFO << "Missing inputs. Aborting.";
        return;
    }

    medAbstractTractographyProcess *filter = this->object();
    if (this->object())
    {
        filter->setInput(d->input.data());
        filter->run();
        d->output.setData(filter->output());
    }
}
Beispiel #28
0
/**
* Returns the index of a data given patient, study, series and image name
*/
medDataIndex medDatabaseController::indexForPatient (const QString &patientName)
{
    QSqlQuery query(m_database);
    QVariant patientId = -1;

    query.prepare("SELECT id FROM patient WHERE name = :name");
    query.bindValue(":name", patientName);
    if(!query.exec())
    {
        dtkDebug() << DTK_COLOR_FG_RED << query.lastError() << DTK_NO_COLOR;
    }

    if(query.first()) {
        patientId = query.value(0);
        return medDataIndex::makePatientIndex(this->dataSourceId(), patientId.toInt());
    }

    return medDataIndex();
}
Beispiel #29
0
bool itkDataSHImageWriterBase::write(const QString& path, PixelType dummyArgument)
{
    typedef typename itk::VectorImage<PixelType, 3>     SHImageType;

    typedef typename SHImageType::Pointer SHImageTypePointer;
    SHImageTypePointer image = dynamic_cast< SHImageType* >( (itk::Object*)(this->data()->output()) );

    typedef typename itk::ImageFileWriter<SHImageType>::Pointer ImageFileWriterPointer;
    ImageFileWriterPointer myWriter = itk::ImageFileWriter<SHImageType>::New();
    myWriter->SetFileName(path.toLatin1().constData());
    myWriter->SetInput(/*mySH*/image);
    try {
        myWriter->Write();
    }
    catch(itk::ExceptionObject &e) {
        dtkDebug() << e.GetDescription();
        return false;
    }

    return true;
}
bool medQtDataImageWriter::writeOrTest( const QString& path, bool dryRun /*= true*/ )
{
    dtkAbstractData * dtkdata = this->data();

    if ( !dtkdata )
        return false;

    if (dtkdata->identifier() != medQtDataImage::s_identifier() ) {
        return false;
    }

    QFileInfo fi ( path );
    QString suffix = fi.suffix();

    QByteArray fmtString;
    const QString lowerSuffix = suffix.toLower();
    FormatInfoList::const_iterator formatToUse = m_supportedExtensionList.begin();
    for ( ; formatToUse != m_supportedExtensionList.end() ; ++formatToUse ){
        if (formatToUse->fileExtension == suffix )
            break;
    }
    if ( formatToUse != m_supportedExtensionList.end() ) {
        fmtString = formatToUse->formatName;
    } else {
        dtkDebug() << "Filename does not have a supported extension";
        return false;
    }

    QScopedPointer<QImageWriter> writer(new QImageWriter( path ) );
    if ( fmtString.size() ) {
        writer->setFormat( fmtString );
    }

    medAbstractDataImage * dtkdataIm = dynamic_cast< medAbstractDataImage *>( dtkdata );

    // Set metadata
    const QStringList keys = dtkdata->metaDataList();
    foreach( const QString key, keys) {
        writer->setText( key, dtkdata->metadata(key) );
    }