#include "medContoursReader.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // ------------------------------------------------------------------------- // // ------------------------ Contour Reader Private -------------------------- // // ------------------------------------------------------------------------- // class ContoursReaderPrivate { public: qint64 fileVersion; bool isBinary; }; // ------------------------------------------------------------------------- // // ---------------------------- Contour Reader ------------------------------ // // ------------------------------------------------------------------------- // medContoursReader::medContoursReader() : medAbstractDataReader(), d(new ContoursReaderPrivate()) { d->isBinary = true; d->fileVersion = medContoursWriter::NUMBER_OF_EXPORT_VERSIONS; } medContoursReader::~medContoursReader() { delete d; } bool medContoursReader::registered() { return medAbstractDataFactory::instance()->registerDataReaderType("ContoursReader", medContoursReader::s_handled(), createMedContoursReader); } QString medContoursReader::identifier() const { return QString("ContoursReader"); } QString medContoursReader::description() const { return QString("Reader for Contours (Polygon ROI)"); } QStringList medContoursReader::handled() const { return s_handled(); } QStringList medContoursReader::s_handled() { return QStringList() << "medContours"; } QStringList medContoursReader::supportedFileExtensions() const { return QStringList() << ".ctrb"; } bool medContoursReader::canRead(const QString& path) { return path.endsWith(".ctrb"); } bool medContoursReader::canRead(const QStringList& paths) { if (paths.empty()) { return false; } return canRead(qPrintable(paths.first())); } bool medContoursReader::readInformation(const QString& path) { bool bRes = true; QFile file(path); if (path.endsWith(".ctrb")) { d->isBinary = true; // binary format, read only the header if (file.open(QFile::ReadOnly)) { QDataStream in(&file); qint64 dummy = 0; in >> d->fileVersion >> dummy >> dummy >> dummy; file.close(); if ((d->fileVersion < medContoursWriter::EXPORT_VERSION_1) || (d->fileVersion >= medContoursWriter::NUMBER_OF_EXPORT_VERSIONS)) { qDebug() << metaObject()->className() << ":: readInformation - unknown contours binary export version."; bRes = false; } this->setData(medAbstractDataFactory::instance()->create(QString("medContours"))); } } else { d->isBinary = false; // Debug ASCII format vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName(qPrintable(path)); if (reader->OpenVTKFile() == 0) { qDebug()<< metaObject()->className() << "::readInformation - failed to open underlying vtk file."; bRes = false; } reader->ReadHeader(); QString header(reader->GetHeader()); if (!header.contains(medContoursWriter::header)) { qDebug()<< metaObject()->className() << "::readInformation - file does not have the correct header."; bRes = false; } this->setData(medAbstractDataFactory::instance()->create(QString("medContours"))); } return bRes; } bool medContoursReader::readInformation(const QStringList& paths) { if (paths.empty()) { return false; } return readInformation(qPrintable(paths.first())); } bool medContoursReader::read(const QString& path) { setProgress(0); if (readInformation(path)) { setProgress(10); if (d->isBinary) { return readBinaryFile(path); } else { // TODO ==> Read ASCII File to implement // TODO ==> operator >> to implement in medTagContours return false;//readASCIIFile(path); } } return false; } bool medContoursReader::readBinaryFile(QString path) { bool bRes = true; QFile file(path); if (file.open(QFile::ReadOnly)) { if (d->fileVersion == medContoursWriter::EXPORT_VERSION_1) { QDataStream in(&file); qint64 dummy = 0, startMeshPos = 0, endMeshPos = 0, fileEndPos; // skip header in >> dummy >> startMeshPos >> endMeshPos >> fileEndPos; // the VTK mesh part starts here. Determine size of the // mesh block qint64 meshLen = endMeshPos - startMeshPos; // hopefully this cast goes well... int len = static_cast(meshLen); char* inputString = new char[len]; if (in.readRawData(inputString, len) == -1) { qDebug() << metaObject()->className() << ":: read - failed to read binary mesh data."; delete[] inputString; file.close(); bRes = false; } setProgress(25); vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetReadFromInputString(1); reader->SetBinaryInputString(inputString, len); vtkSmartPointer dataSet = retrieveMeshFromReader(reader); if (!dataSet) { qDebug() << metaObject()->className() << ":: readBinaryFile - failure to read Contours."; bRes = false; } setProgress(60); // retrieve contours with label qint32 *size = new qint32(); in >> *size; QVector contoursSet; for (int i=0; i<*size; i++) { medTagContours contours; in >> contours; contoursSet.append(contours); } setProgress(90); if (file.pos() != fileEndPos) { qDebug() << metaObject()->className() << ":: wrong pos :" << file.pos() << "instead of" << fileEndPos; } // set the mesh then the EP data this->data()->setData(dataSet); this->data()->setData(&contoursSet, 1); file.close(); } else { qDebug() << metaObject()->className() << ":: unsupported binary file."; file.close(); bRes = false; } } setProgress(100); return bRes; } vtkSmartPointer medContoursReader::retrieveMeshFromReader(vtkSmartPointer reader) { vtkSmartPointer dataSet = nullptr; try { reader->Update(); vtkDataSet* readerOutput = nullptr; if (reader->IsFilePolyData() != 0) { dataSet = vtkSmartPointer::New(); readerOutput = reader->GetPolyDataOutput(); } else { // not a surface . Abort qDebug()<< metaObject()->className() << ":: labeled contours not a surface nor a volume."; return nullptr; } dataSet->SetDataSet(readerOutput); // Allocate the medAbstractData this->setData(medAbstractDataFactory::instance()->create(QString("medContours"))); if (!extractMetaDataFromFieldData(dataSet)) { // not a critical error qDebug() << metaObject()->className() <<":: no metadata found in mesh."; } } catch (vtkErrorCode::ErrorIds error) { qDebug()<< metaObject()->className() <<"::read - "<< vtkErrorCode::GetStringFromErrorCode(error); return nullptr; } catch (...) { qDebug() << metaObject()->className() << "::read - error reading mesh."; return nullptr; } return dataSet; } bool medContoursReader::extractMetaDataFromFieldData(vtkMetaDataSet* dataSet) { bool foundMetaData = false; vtkFieldData* fieldData = dataSet->GetDataSet()->GetFieldData(); vtkSmartPointer newFieldData = vtkSmartPointer::New(); for (int i = 0; i < fieldData->GetNumberOfArrays(); i++) { QString arrayName = fieldData->GetArrayName(i); if (arrayName.startsWith(medContoursWriter::metaDataFieldPrefix)) { foundMetaData = true; vtkStringArray* array = static_cast(fieldData->GetAbstractArray(i)); QString metaDataKey = arrayName.remove(0, medContoursWriter::metaDataFieldPrefix.length()); for (int j = 0; j < array->GetSize(); j++) { data()->addMetaData(metaDataKey, QString(array->GetValue(j))); } } else { newFieldData->AddArray(fieldData->GetAbstractArray(i)); } } dataSet->GetDataSet()->SetFieldData(newFieldData); return foundMetaData; } bool medContoursReader::read(const QStringList& paths) { bool bRes; if (paths.empty()) { bRes = false; } else { bRes = read(qPrintable(paths.first())); } return bRes; } void medContoursReader::setProgress(int value) { emit progressed(value); } // ///////////////////////////////////////////////////////////////// // Type instantiation // ///////////////////////////////////////////////////////////////// dtkAbstractDataReader *createMedContoursReader() { return new medContoursReader; }