void MGPWorkitem::import(const MDomainObject& o) { SOPInstanceUID(o.value("sopinsuid")); SOPClassUID(o.value("sopclassuid")); status(o.value("status")); inputAvailabilityFlag(o.value("inputavailflag")); priority(o.value("priority")); procedureStepID(o.value("procstepid")); startDateTime(o.value("startdattim")); endDateTime(o.value("enddattim")); resultStudyInstanceUID(o.value("resultstuinsuid")); inputStudyInstanceUID(o.value("inputstuinsuid")); multipleCopiesFlag(o.value("multcopyflag")); description(o.value("description")); patientID(o.value("patientid")); patientName(o.value("patientname")); patientBirthDate(o.value("birthdate")); patientSex(o.value("sex")); workItemCodeValue(o.value("workitemcodevalue")); workItemCodeScheme(o.value("workitemcodescheme")); workItemCodeMeaning(o.value("workitemcodemeaning")); requestedProcAccessionNum(o.value("reqprocAccessionNum")); requestedProcID(o.value("reqprocID")); requestedProcDesc(o.value("reqprocDesc")); requestedProcCodevalue(o.value("reqprocCodevalue")); requestedProcCodemeaning(o.value("reqprocCodemeaning")); requestedProcCodescheme(o.value("reqprocCodescheme")); requestingPhysician(o.value("requestingPhys")); transactionUID(o.value("transactionUID")); }
void MDBImageManager::setCriteria(const MPlacerOrder& order, MCriteriaVector& cv) { MCriteria c; MString patientID(order.patientID()); if (patientID.size()) { c.attribute = "patid"; c.oper = TBL_EQUAL; c.value = order.patientID(); cv.push_back(c); } #if 0 MString issuer(order.issuerOfPatientID()); if (issuer.size()) { c.attribute = "issuer"; c.oper = TBL_EQUAL; c.value = order.issuerOfPatientID(); cv.push_back(c); } #endif c.attribute = "plaordnum"; c.oper = TBL_EQUAL; c.value = order.placerOrderNumber(); cv.push_back(c); }
void MDBImageManager::setCriteria(const MFillerOrder& order, MCriteriaVector& cv) { MCriteria c; MString patientID(order.patientID()); if (patientID.size()) { c.attribute = "patid"; c.oper = TBL_EQUAL; c.value = order.patientID(); cv.push_back(c); } #if 0 MString issuer(order.issuerOfPatientID()); if (issuer.size()) { c.attribute = "issuer"; c.oper = TBL_EQUAL; c.value = order.issuerOfPatientID(); cv.push_back(c); } #endif MString poNum(order.placerOrderNumber()); if (poNum.size()) { c.attribute = "plaordnum"; c.oper = TBL_EQUAL; c.value = order.placerOrderNumber(); cv.push_back(c); } c.attribute = "filordnum"; c.oper = TBL_EQUAL; c.value = order.fillerOrderNumber(); cv.push_back(c); // may include accession number also /* MString accNum(order.accessionNumber()); if (accNum.size()) { c.attribute = "accnum"; c.oper = TBL_EQUAL; c.value = order.accessionNumber(); cv.push_back(c); } */ }
//------------------------------------------------------------------------------ void ctkDICOMDatabasePrivate::insert( const ctkDICOMDataset& ctkDataset, const QString& filePath, bool storeFile, bool generateThumbnail) { Q_Q(ctkDICOMDatabase); // Check to see if the file has already been loaded // TODO: // It could make sense to actually remove the dataset and re-add it. This needs the remove // method we still have to write. // QString sopInstanceUID ( ctkDataset.GetElementAsString(DCM_SOPInstanceUID) ); QSqlQuery fileExists ( Database ); fileExists.prepare("SELECT InsertTimestamp,Filename FROM Images WHERE SOPInstanceUID == :sopInstanceUID"); fileExists.bindValue(":sopInstanceUID",sopInstanceUID); bool success = fileExists.exec(); if (!success) { logger.error("SQLITE ERROR: " + fileExists.lastError().driverText()); return; } qDebug() << "filename is: " << fileExists.value(1).toString(); qDebug() << "modified date is: " << QFileInfo(fileExists.value(1).toString()).lastModified(); qDebug() << "db mod date is: " << QDateTime::fromString(fileExists.value(0).toString(),Qt::ISODate); if ( fileExists.next() && QFileInfo(fileExists.value(1).toString()).lastModified() < QDateTime::fromString(fileExists.value(0).toString(),Qt::ISODate) ) { logger.debug ( "File " + fileExists.value(1).toString() + " already added" ); return; } //If the following fields can not be evaluated, cancel evaluation of the DICOM file QString patientsName(ctkDataset.GetElementAsString(DCM_PatientName) ); QString studyInstanceUID(ctkDataset.GetElementAsString(DCM_StudyInstanceUID) ); QString seriesInstanceUID(ctkDataset.GetElementAsString(DCM_SeriesInstanceUID) ); QString patientID(ctkDataset.GetElementAsString(DCM_PatientID) ); if ( patientsName.isEmpty() && !patientID.isEmpty() ) { // Use patient id as name if name is empty - can happen on anonymized datasets // see: http://www.na-mic.org/Bug/view.php?id=1643 patientsName = patientID; } if ( patientsName.isEmpty() || studyInstanceUID.isEmpty() || patientID.isEmpty() ) { logger.error("Dataset is missing necessary information!"); return; } QString patientsBirthDate(ctkDataset.GetElementAsString(DCM_PatientBirthDate) ); QString patientsBirthTime(ctkDataset.GetElementAsString(DCM_PatientBirthTime) ); QString patientsSex(ctkDataset.GetElementAsString(DCM_PatientSex) ); QString patientsAge(ctkDataset.GetElementAsString(DCM_PatientAge) ); QString patientComments(ctkDataset.GetElementAsString(DCM_PatientComments) ); QString studyID(ctkDataset.GetElementAsString(DCM_StudyID) ); QString studyDate(ctkDataset.GetElementAsString(DCM_StudyDate) ); QString studyTime(ctkDataset.GetElementAsString(DCM_StudyTime) ); QString accessionNumber(ctkDataset.GetElementAsString(DCM_AccessionNumber) ); QString modalitiesInStudy(ctkDataset.GetElementAsString(DCM_ModalitiesInStudy) ); QString institutionName(ctkDataset.GetElementAsString(DCM_InstitutionName) ); QString performingPhysiciansName(ctkDataset.GetElementAsString(DCM_PerformingPhysicianName) ); QString referringPhysician(ctkDataset.GetElementAsString(DCM_ReferringPhysicianName) ); QString studyDescription(ctkDataset.GetElementAsString(DCM_StudyDescription) ); QString seriesDate(ctkDataset.GetElementAsString(DCM_SeriesDate) ); QString seriesTime(ctkDataset.GetElementAsString(DCM_SeriesTime) ); QString seriesDescription(ctkDataset.GetElementAsString(DCM_SeriesDescription) ); QString bodyPartExamined(ctkDataset.GetElementAsString(DCM_BodyPartExamined) ); QString frameOfReferenceUID(ctkDataset.GetElementAsString(DCM_FrameOfReferenceUID) ); QString contrastAgent(ctkDataset.GetElementAsString(DCM_ContrastBolusAgent) ); QString scanningSequence(ctkDataset.GetElementAsString(DCM_ScanningSequence) ); long seriesNumber(ctkDataset.GetElementAsInteger(DCM_SeriesNumber) ); long acquisitionNumber(ctkDataset.GetElementAsInteger(DCM_AcquisitionNumber) ); long echoNumber(ctkDataset.GetElementAsInteger(DCM_EchoNumbers) ); long temporalPosition(ctkDataset.GetElementAsInteger(DCM_TemporalPositionIdentifier) ); // store the file if the database is not in memomry // TODO: if we are called from insert(file) we // have to do something else // QString filename = filePath; if ( storeFile && !q->isInMemory() && !seriesInstanceUID.isEmpty() ) { // QString studySeriesDirectory = studyInstanceUID + "/" + seriesInstanceUID; QString destinationDirectoryName = q->databaseDirectory() + "/dicom/"; QDir destinationDir(destinationDirectoryName); filename = destinationDirectoryName + studyInstanceUID + "/" + seriesInstanceUID + "/" + sopInstanceUID; destinationDir.mkpath(studyInstanceUID + "/" + seriesInstanceUID); if(filePath.isEmpty()) { logger.debug ( "Saving file: " + filename ); if ( !ctkDataset.SaveToFile( filename) ) { logger.error ( "Error saving file: " + filename ); return; } } else { // we're inserting an existing file QFile currentFile( filePath ); currentFile.copy(filename); logger.debug( "Copy file from: " + filePath ); logger.debug( "Copy file to : " + filename ); } } QSqlQuery checkPatientExistsQuery(Database); //The dbPatientID is a unique number within the database, //generated by the sqlite autoincrement //The patientID is the (non-unique) DICOM patient id int dbPatientID = -1; if ( patientID != "" && patientsName != "" ) { //Speed up: Check if patient is the same as in last file; // very probable, as all images belonging to a study have the same patient if ( lastPatientID != patientID || lastPatientsBirthDate != patientsBirthDate || lastPatientsName != patientsName ) { // Ok, something is different from last insert, let's insert him if he's not // already in the db. // // Check if patient is already present in the db // TODO: maybe add birthdate check for extra safety checkPatientExistsQuery.prepare ( "SELECT * FROM Patients WHERE PatientID = ? AND PatientsName = ?" ); checkPatientExistsQuery.bindValue ( 0, patientID ); checkPatientExistsQuery.bindValue ( 1, patientsName ); loggedExec(checkPatientExistsQuery); if (checkPatientExistsQuery.next()) { // we found him dbPatientID = checkPatientExistsQuery.value(checkPatientExistsQuery.record().indexOf("UID")).toInt(); } else { // Insert it QSqlQuery insertPatientStatement ( Database ); insertPatientStatement.prepare ( "INSERT INTO Patients ('UID', 'PatientsName', 'PatientID', 'PatientsBirthDate', 'PatientsBirthTime', 'PatientsSex', 'PatientsAge', 'PatientsComments' ) values ( NULL, ?, ?, ?, ?, ?, ?, ? )" ); insertPatientStatement.bindValue ( 0, patientsName ); insertPatientStatement.bindValue ( 1, patientID ); insertPatientStatement.bindValue ( 2, patientsBirthDate ); insertPatientStatement.bindValue ( 3, patientsBirthTime ); insertPatientStatement.bindValue ( 4, patientsSex ); // TODO: shift patient's age to study, // since this is not a patient level attribute in images // insertPatientStatement.bindValue ( 5, patientsAge ); insertPatientStatement.bindValue ( 6, patientComments ); loggedExec(insertPatientStatement); dbPatientID = insertPatientStatement.lastInsertId().toInt(); logger.debug ( "New patient inserted: " + QString().setNum ( dbPatientID ) ); } /// keep this for the next image lastPatientUID = dbPatientID; lastPatientID = patientID; lastPatientsBirthDate = patientsBirthDate; lastPatientsName = patientsName; } // Patient is in now. Let's continue with the study if ( studyInstanceUID != "" && lastStudyInstanceUID != studyInstanceUID ) { QSqlQuery checkStudyExistsQuery (Database); checkStudyExistsQuery.prepare ( "SELECT * FROM Studies WHERE StudyInstanceUID = ?" ); checkStudyExistsQuery.bindValue ( 0, studyInstanceUID ); checkStudyExistsQuery.exec(); if(!checkStudyExistsQuery.next()) { QSqlQuery insertStudyStatement ( Database ); insertStudyStatement.prepare ( "INSERT INTO Studies ( 'StudyInstanceUID', 'PatientsUID', 'StudyID', 'StudyDate', 'StudyTime', 'AccessionNumber', 'ModalitiesInStudy', 'InstitutionName', 'ReferringPhysician', 'PerformingPhysiciansName', 'StudyDescription' ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ); insertStudyStatement.bindValue ( 0, studyInstanceUID ); insertStudyStatement.bindValue ( 1, dbPatientID ); insertStudyStatement.bindValue ( 2, studyID ); insertStudyStatement.bindValue ( 3, QDate::fromString ( studyDate, "yyyyMMdd" ) ); insertStudyStatement.bindValue ( 4, studyTime ); insertStudyStatement.bindValue ( 5, accessionNumber ); insertStudyStatement.bindValue ( 6, modalitiesInStudy ); insertStudyStatement.bindValue ( 7, institutionName ); insertStudyStatement.bindValue ( 8, referringPhysician ); insertStudyStatement.bindValue ( 9, performingPhysiciansName ); insertStudyStatement.bindValue ( 10, studyDescription ); if ( !insertStudyStatement.exec() ) { logger.error ( "Error executing statament: " + insertStudyStatement.lastQuery() + " Error: " + insertStudyStatement.lastError().text() ); } else { lastStudyInstanceUID = studyInstanceUID; } } } if ( seriesInstanceUID != "" && seriesInstanceUID != lastSeriesInstanceUID ) { QSqlQuery checkSeriesExistsQuery (Database); checkSeriesExistsQuery.prepare ( "SELECT * FROM Series WHERE SeriesInstanceUID = ?" ); checkSeriesExistsQuery.bindValue ( 0, seriesInstanceUID ); logger.warn ( "Statement: " + checkSeriesExistsQuery.lastQuery() ); loggedExec(checkSeriesExistsQuery); if(!checkSeriesExistsQuery.next()) { QSqlQuery insertSeriesStatement ( Database ); insertSeriesStatement.prepare ( "INSERT INTO Series ( 'SeriesInstanceUID', 'StudyInstanceUID', 'SeriesNumber', 'SeriesDate', 'SeriesTime', 'SeriesDescription', 'BodyPartExamined', 'FrameOfReferenceUID', 'AcquisitionNumber', 'ContrastAgent', 'ScanningSequence', 'EchoNumber', 'TemporalPosition' ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ); insertSeriesStatement.bindValue ( 0, seriesInstanceUID ); insertSeriesStatement.bindValue ( 1, studyInstanceUID ); insertSeriesStatement.bindValue ( 2, static_cast<int>(seriesNumber) ); insertSeriesStatement.bindValue ( 3, seriesDate ); insertSeriesStatement.bindValue ( 4, QDate::fromString ( seriesTime, "yyyyMMdd" ) ); insertSeriesStatement.bindValue ( 5, seriesDescription ); insertSeriesStatement.bindValue ( 6, bodyPartExamined ); insertSeriesStatement.bindValue ( 7, frameOfReferenceUID ); insertSeriesStatement.bindValue ( 8, static_cast<int>(acquisitionNumber) ); insertSeriesStatement.bindValue ( 9, contrastAgent ); insertSeriesStatement.bindValue ( 10, scanningSequence ); insertSeriesStatement.bindValue ( 11, static_cast<int>(echoNumber) ); insertSeriesStatement.bindValue ( 12, static_cast<int>(temporalPosition) ); if ( !insertSeriesStatement.exec() ) { logger.error ( "Error executing statament: " + insertSeriesStatement.lastQuery() + " Error: " + insertSeriesStatement.lastError().text() ); lastSeriesInstanceUID = ""; } else { lastSeriesInstanceUID = seriesInstanceUID; } } } // TODO: what to do with imported files // if ( !filename.isEmpty() && !seriesInstanceUID.isEmpty() ) { QSqlQuery checkImageExistsQuery (Database); checkImageExistsQuery.prepare ( "SELECT * FROM Images WHERE Filename = ?" ); checkImageExistsQuery.bindValue ( 0, filename ); checkImageExistsQuery.exec(); if(!checkImageExistsQuery.next()) { QSqlQuery insertImageStatement ( Database ); insertImageStatement.prepare ( "INSERT INTO Images ( 'SOPInstanceUID', 'Filename', 'SeriesInstanceUID', 'InsertTimestamp' ) VALUES ( ?, ?, ?, ? )" ); insertImageStatement.bindValue ( 0, sopInstanceUID ); insertImageStatement.bindValue ( 1, filename ); insertImageStatement.bindValue ( 2, seriesInstanceUID ); insertImageStatement.bindValue ( 3, QDateTime::currentDateTime() ); insertImageStatement.exec(); } } if( generateThumbnail && thumbnailGenerator && !seriesInstanceUID.isEmpty() ) { QString studySeriesDirectory = studyInstanceUID + "/" + seriesInstanceUID; //Create thumbnail here QString thumbnailPath = q->databaseDirectory() + "/thumbs/" + studyInstanceUID + "/" + seriesInstanceUID + "/" + sopInstanceUID + ".png"; QFileInfo thumbnailInfo(thumbnailPath); if( !(thumbnailInfo.exists() && (thumbnailInfo.lastModified() > QFileInfo(filename).lastModified()))) { QDir(q->databaseDirectory() + "/thumbs/").mkpath(studySeriesDirectory); DicomImage dcmImage(QDir::toNativeSeparators(filename).toAscii()); thumbnailGenerator->generateThumbnail(&dcmImage, thumbnailPath); } } if (q->isInMemory()) { emit q->databaseChanged(); } } }
int main(int argc, char **argv) { CONDITION cond; DUL_NETWORKKEY* network = NULL; DUL_ASSOCIATIONKEY* association = NULL; DUL_ASSOCIATESERVICEPARAMETERS params; char *calledAPTitle = "CFIND_SCP", *callingAPTitle = "CFIND_SCU"; char localHost[40] = ""; int port; char *node; CTNBOOLEAN verbose = FALSE, abortFlag = FALSE, paramsFlag = FALSE; char *fileName = NULL; DUL_SC_ROLE role = DUL_SC_ROLE_DEFAULT; char* sopClass = DICOM_SOPSTUDYQUERY_FIND; char* outputPath = ""; while (--argc > 0 && (*++argv)[0] == '-') { switch (*(argv[0] + 1)) { case 'a': argc--; argv++; if (argc <= 0) usageerror(); callingAPTitle = *argv; break; case 'c': argc--; argv++; if (argc <= 0) usageerror(); calledAPTitle = *argv; break; case 'o': argc--; argv++; if (argc <= 0) usageerror(); outputPath = *argv; break; case 'v': verbose = TRUE; break; default: break; } } if (argc < 5) usageerror(); ::THR_Init(); ::DUL_Debug(verbose); ::SRV_Debug(verbose); node = *argv; if (sscanf(*++argv, "%d", &port) != 1) usageerror(); if( gethostname(localHost, sizeof(localHost)) != 0) { // gethostname is failing under Win32 //fprintf(stderr, "gethostname() failed.\n"); } cond = DUL_InitializeNetwork(DUL_NETWORK_TCP, DUL_AEREQUESTOR, NULL, 10, DUL_ORDERBIGENDIAN, &network); if (cond != DUL_NORMAL) myExit(&association); ::DUL_DefaultServiceParameters(¶ms); ::sprintf(params.calledPresentationAddress, "%s:%s", node, *argv); ::strcpy(params.callingPresentationAddress, localHost); ::strcpy(params.calledAPTitle, calledAPTitle); ::strcpy(params.callingAPTitle, callingAPTitle); cond = ::SRV_RequestServiceClass(sopClass, role, ¶ms); if (cond != SRV_NORMAL) { ::COND_DumpConditions(); ::THR_Shutdown(); ::exit(1); } cond = ::DUL_RequestAssociation(&network, ¶ms, &association); if (cond != DUL_NORMAL) { if (cond == DUL_ASSOCIATIONREJECTED) { ::fprintf(stderr, "Association Rejected\n"); ::fprintf(stderr, " Result: %2x Source %2x Reason %2x\n", params.result, params.resultSource, params.diagnostic); } myExit(&association); } if (verbose || paramsFlag) { (void) ::printf("Association accepted, parameters:\n"); ::DUL_DumpParams(¶ms); } MString patientID(*++argv); MDICOMWrapper qStudy(*++argv); qStudy.setString(0x00100020, patientID); MDICOMWrapper qSeries(*++argv); MDICOMWrapper qSOPInstance(*++argv); DCM_OBJECT* queryObj = qStudy.getNativeObject(); MLQuery qHandlerStudy(outputPath); MLQuery qHandlerSeries(outputPath); MLQuery qHandlerInstance(outputPath); MDICOMReactor reactor; reactor.registerHandler(&qHandlerStudy, sopClass); qHandlerStudy.sendCFindRequest(&association, ¶ms, sopClass, &queryObj); reactor.processRequests(&association, ¶ms, 1); WRAPPERVector studyVector = qHandlerStudy.wrapperVector(); WRAPPERVector::iterator studyIterator = studyVector.begin(); for (; studyIterator != studyVector.end(); studyIterator++) { MDICOMWrapper* w = *studyIterator; DCM_OBJECT* obj = w->getNativeObject(); ::DCM_FormatElements(&obj, 1, ""); reactor.registerHandler(&qHandlerSeries, sopClass); MString studyUID = w->getString(0x0020000D); qSeries.setString(0x0020000D, studyUID); DCM_OBJECT* seriesQueryObj = qSeries.getNativeObject(); qHandlerSeries.sendCFindRequest(&association, ¶ms, sopClass, &seriesQueryObj); qHandlerSeries.clearVector(); reactor.processRequests(&association, ¶ms, 1); WRAPPERVector seriesVector = qHandlerSeries.wrapperVector(); WRAPPERVector::iterator seriesIterator = seriesVector.begin(); for (; seriesIterator != seriesVector.end(); seriesIterator++) { MDICOMWrapper* w2 = *seriesIterator; DCM_OBJECT* objSeries = w2->getNativeObject(); ::DCM_FormatElements(&objSeries, 1, " "); reactor.registerHandler(&qHandlerInstance, sopClass); MString seriesUID = w2->getString(0x0020000E); qSOPInstance.setString(0x0020000D, studyUID); qSOPInstance.setString(0x0020000E, seriesUID); DCM_OBJECT* instanceQueryObj = qSOPInstance.getNativeObject(); qHandlerInstance.sendCFindRequest(&association, ¶ms, sopClass, &instanceQueryObj); qHandlerInstance.clearVector(); reactor.processRequests(&association, ¶ms, 1); WRAPPERVector instanceVector = qHandlerInstance.wrapperVector(); WRAPPERVector::iterator instanceIterator = instanceVector.begin(); for (; instanceIterator != instanceVector.end(); instanceIterator++) { MDICOMWrapper* w3 = *instanceIterator; DCM_OBJECT* objInstance = w3->getNativeObject(); ::DCM_FormatElements(&objInstance, 1, " "); } } } cond = ::DUL_ReleaseAssociation(&association); if (cond != DUL_RELEASECONFIRMED) { (void) ::fprintf(stderr, "%x\n", cond); ::COND_DumpConditions(); } (void) ::DUL_ClearServiceParameters(¶ms); (void) ::DUL_DropNetwork(&network); ::THR_Shutdown(); return 0; }