1226
1196
}// end query modality
1228
FillInQuery(base, &query, server);
1230
e = newDicomElement(DCM_SpecificCharacterSet);
1231
e->putString(server->GetDefaultCharset().c_str());
1234
e = newDicomElement(DCM_QueryRetrieveLevel);
1235
e->putString(wxString( "SERIES", wxConvUTF8).mb_str(conv));
1236
query.insert(e, true);
1238
e = newDicomElement(DCM_SeriesInstanceUID);
1239
if (query.insert(e).bad()) {
1243
e = newDicomElement(DCM_Modality);
1244
if (query.insert(e).bad()) {
1248
e = newDicomElement(DCM_SeriesNumber);
1249
if (query.insert(e).bad()) {
1198
//association to make finds...
1199
NetClient<FindAssociation> f(connectionKey, "C-GET/FIND", pNotificador);
1200
f.SetMaxResults(-1);
1253
1202
std::string localAET = GNC::Entorno::Instance()->GetDicomLocalAET();
1255
if (server->GetRetrieveWithMove()) {
1258
LOG_INFO("C-MOVE", "Obteniendo serie del PACS " << serverId << ": " << server->AET << "@" << server->HostName << ":" << server->Port << " PDU=" << server->PDU << ", TLS=" << server->useTLS << ", User = " << server->pacsUser << ", Method=C-MOVE");
1262
LOG_INFO("C-MOVE", "Obteniendo estudio del PACS " << serverId << ": " << server->AET << "@" << server->HostName << ":" << server->Port << " PDU=" << server->PDU << ", TLS=" << server->useTLS << ", User = " << server->pacsUser << ", Method=C-MOVE");
1265
NetClient<MoveAssociation> a(connectionKey, "C-MOVE", pNotificador);
1266
a.SetRole(Association::RT_Requestor);
1267
a.SetModelo(pModelo);
1269
a.SetCallbackHandler(this);
1271
if (server->useTLS) {
1272
a.SetTLS(server->GetCertificate(), server->GetPrivateKey(), server->GetverifyCredentials());
1274
if (server->GetPACSUser() != "") {
1275
a.SetUserPass(server->GetPACSUser(), server->GetPACSPass());
1277
a.QueryServer(&query, server, pModelo, localAET, CT_MoveSerie);
1281
LOG_INFO("C-GET", "Obteniendo serie del PACS " << serverId << ": " << server->AET << "@" << server->HostName << ":" << server->Port << " PDU=" << server->PDU << ", TLS=" << server->useTLS << ", User = " << server->pacsUser << ", Method=C-GET");
1284
NetClient<GetAssociation> a(connectionKey, "C-GET", pNotificador);
1285
a.SetMaxResults(-1);
1286
a.SetWellKnownNumResults(numResults);
1287
a.SetStorageSOPClasses(GIL::DICOM::Conformance::GetModalities().GetSupportedSOPClassUIDs(modality));
1288
a.SetModelo(pModelo);
1290
a.SetCallbackHandler(this);
1292
if (server->useTLS) {
1293
a.SetTLS(server->GetCertificate(), server->GetPrivateKey(), server->GetverifyCredentials());
1295
if (server->GetPACSUser() != "") {
1296
a.SetUserPass(server->GetPACSUser(), server->GetPACSPass());
1298
if (!a.QueryServer(&query, server, pModelo, localAET, CT_MoveSerie)) {
1204
if (server->useTLS) {
1205
f.SetTLS(server->GetCertificate(), server->GetPrivateKey(), server->GetverifyCredentials());
1207
if (server->GetPACSUser() != "") {
1208
f.SetUserPass(server->GetPACSUser(), server->GetPACSPass());
1211
if (server->GetRetrieveMethod() == DicomServer::WADO)
1213
//we need to know StudyInstanceUID, SeriesInstanceUID and SopInstanceUID of all elements
1214
std::string seriesInstanceUID, studyInstanceUID;
1215
if (!base.getTag(GKDCM_SeriesInstanceUID, seriesInstanceUID)) {
1216
LOG_ERROR("PACSController", "to obtain a series you must specify seriesInstanceUID");
1219
if (!base.getTag(GKDCM_StudyInstanceUID, studyInstanceUID)) {
1220
FillInQuery(base, &query, server);
1222
e = newDicomElement(DCM_SpecificCharacterSet);
1223
e->putString(server->GetDefaultCharset().c_str());
1226
e = newDicomElement(DCM_QueryRetrieveLevel);
1227
e->putString(wxString( "SERIES", wxConvUTF8).mb_str(conv));
1228
query.insert(e, true);
1230
e = newDicomElement(DCM_StudyInstanceUID);
1231
if (query.insert(e).bad()) {
1235
e = newDicomElement(DCM_SeriesInstanceUID);
1236
if (query.insert(e).bad()) {
1240
if (!f.QueryServer(&query, server, pModelo, localAET, CT_None))
1248
DcmStack* stack = f.GetResultStack();
1252
for (unsigned int i = 0; i < stack->card(); i++) {
1254
if (stack->elem(i)->ident() == EVR_dataset) {
1255
DcmDataset* dset = dynamic_cast<DcmDataset*>(stack->elem(i));
1258
if ( dset->findAndGetOFString(DCM_StudyInstanceUID, tempOf).good() && tempOf.size() > 0 )
1260
studyInstanceUID = tempOf.c_str();
1269
if (studyInstanceUID.empty()) {
1270
LOG_ERROR("PACSController", "StudyInstanceUID not found");
1274
//now we have to get all sop instance uids...
1275
f.DeleteResultStack();
1276
e = newDicomElement(DCM_SpecificCharacterSet);
1277
e->putString(server->GetDefaultCharset().c_str());
1280
e = newDicomElement(DCM_QueryRetrieveLevel);
1281
e->putString(wxString( "IMAGE", wxConvUTF8).mb_str(conv));
1282
query.insert(e, true);
1284
e = newDicomElement(DCM_SeriesInstanceUID);
1285
e->putString(wxString( seriesInstanceUID.c_str(), wxConvUTF8).mb_str(conv));
1286
if (query.insert(e).bad()) {
1290
e = newDicomElement(DCM_SOPInstanceUID);
1291
if (query.insert(e).bad()) {
1295
e = newDicomElement(DCM_InstanceNumber);
1296
if (query.insert(e).bad()) {
1300
if (!f.QueryServer(&query, server, pModelo, localAET, CT_None))
1308
DcmStack* stack = f.GetResultStack();
1311
std::list<std::pair<long, std::string> > instances;
1313
for (unsigned int i = 0; i < stack->card(); i++) {
1314
if (stack->elem(i)->ident() == EVR_dataset) {
1315
DcmDataset* dset = dynamic_cast<DcmDataset*>(stack->elem(i));
1317
if ( dset->findAndGetOFString(DCM_SOPInstanceUID, tempOf).good() && tempOf.size() > 0 )
1319
const std::string sopInstanceUID = tempOf.c_str();
1320
long instanceNumber;
1321
std::pair<long, std::string> item;
1322
item.second = sopInstanceUID;
1323
if ( dset->findAndGetLongInt(DCM_InstanceNumber, instanceNumber).good() ) {
1324
item.first = instanceNumber;
1326
item.first = LONG_MAX;
1328
instances.push_back(item);
1335
//sort by instance number...
1336
instances.sort(compare_instances);
1337
std::list<std::string> sopInstanceUIDs;
1338
std::list<long> instanceNumbers;
1339
for (std::list<std::pair<long, std::string> >::const_iterator it = instances.begin(); it != instances.end(); ++it) {
1340
sopInstanceUIDs.push_back((*it).second);
1341
instanceNumbers.push_back((*it).first);
1344
//now we have studyInstanceUID, seriesInstanceUID and sopInstancesUIDS.... download it!
1345
return DownloadWADOImages(serverId, studyInstanceUID, seriesInstanceUID, sopInstanceUIDs, instanceNumbers, pModelo, pNotificador, link);
1349
FillInQuery(base, &query, server);
1351
e = newDicomElement(DCM_SpecificCharacterSet);
1352
e->putString(server->GetDefaultCharset().c_str());
1355
e = newDicomElement(DCM_QueryRetrieveLevel);
1356
e->putString(wxString( "SERIES", wxConvUTF8).mb_str(conv));
1357
query.insert(e, true);
1359
e = newDicomElement(DCM_SeriesInstanceUID);
1360
if (query.insert(e).bad()) {
1364
e = newDicomElement(DCM_Modality);
1365
if (query.insert(e).bad()) {
1369
e = newDicomElement(DCM_SeriesNumber);
1370
if (query.insert(e).bad()) {
1374
std::string localAET = GNC::Entorno::Instance()->GetDicomLocalAET();
1376
if (server->GetRetrieveMethod() == DicomServer::MOVE) {
1379
LOG_INFO("C-MOVE", "Downloading serie from PACS " << serverId << ": " << server->AET << "@" << server->HostName << ":" << server->Port << " PDU=" << server->PDU << ", TLS=" << server->useTLS << ", User = " << server->pacsUser << ", Method=C-MOVE");
1383
LOG_INFO("C-MOVE", "Downloading study from PACS " << serverId << ": " << server->AET << "@" << server->HostName << ":" << server->Port << " PDU=" << server->PDU << ", TLS=" << server->useTLS << ", User = " << server->pacsUser << ", Method=C-MOVE");
1386
NetClient<MoveAssociation> a(connectionKey, "C-MOVE", pNotificador);
1387
a.SetRole(Association::RT_Requestor);
1388
a.SetModelo(pModelo);
1391
if (server->useTLS) {
1392
a.SetTLS(server->GetCertificate(), server->GetPrivateKey(), server->GetverifyCredentials());
1394
if (server->GetPACSUser() != "") {
1395
a.SetUserPass(server->GetPACSUser(), server->GetPACSPass());
1397
if (!a.QueryServer(&query, server, pModelo, localAET, CT_MoveSerie)) {
1403
LOG_INFO("C-GET", "Downloading serie from PACS " << serverId << ": " << server->AET << "@" << server->HostName << ":" << server->Port << " PDU=" << server->PDU << ", TLS=" << server->useTLS << ", User = " << server->pacsUser << ", Method=C-GET");
1406
NetClient<GetAssociation> a(connectionKey, "C-GET", pNotificador);
1407
a.SetMaxResults(-1);
1408
a.SetWellKnownNumResults(numResults);
1409
a.SetStorageSOPClasses(GIL::DICOM::Conformance::GetModalities().GetSupportedSOPClassUIDs(modality));
1410
a.SetModelo(pModelo);
1412
if (server->useTLS) {
1413
a.SetTLS(server->GetCertificate(), server->GetPrivateKey(), server->GetverifyCredentials());
1415
if (server->GetPACSUser() != "") {
1416
a.SetUserPass(server->GetPACSUser(), server->GetPACSPass());
1418
if (!a.QueryServer(&query, server, pModelo, localAET, CT_MoveSerie)) {
1340
1461
std::string localAET = GNC::Entorno::Instance()->GetDicomLocalAET();
1342
if (server->GetRetrieveWithMove()) {
1463
if (server->GetRetrieveMethod() == DicomServer::MOVE) {
1345
LOG_INFO("C-MOVE", "Obteniendo imagen del PACS " << serverId << ": " << server->AET << "@" << server->HostName << ":" << server->Port << " PDU=" << server->PDU << ", TLS=" << server->useTLS << ", User = " << server->pacsUser << ", Method=C-MOVE");
1466
LOG_INFO("C-MOVE", "Downloading imagen from PACS " << serverId << ": " << server->AET << "@" << server->HostName << ":" << server->Port << " PDU=" << server->PDU << ", TLS=" << server->useTLS << ", User = " << server->pacsUser << ", Method=C-MOVE");
1348
1469
NetClient<MoveAssociation> a(connectionKey, "C-MOVE", pNotificador);
1349
1470
a.SetModelo(pModelo);
1351
a.SetCallbackHandler(this);
1353
1472
if (server->useTLS) {
1354
1473
a.SetTLS(server->GetCertificate(), server->GetPrivateKey(), server->GetverifyCredentials());
1356
1475
if (server->GetPACSUser() != "") {
1357
1476
a.SetUserPass(server->GetPACSUser(), server->GetPACSPass());
1359
a.QueryServer(&query, server, pModelo, localAET, CT_MoveImagen);
1478
if (!a.QueryServer(&query, server, pModelo, localAET, CT_MoveImagen)) {
1483
else if (server->GetRetrieveMethod() == DicomServer::GET) {
1365
LOG_INFO("C-GET", "Obteniendo imagen del PACS " << serverId << ": " << server->AET << "@" << server->HostName << ":" << server->Port << " PDU=" << server->PDU << ", TLS=" << server->useTLS << ", User = " << server->pacsUser << ", Method=C-GET");
1486
LOG_INFO("C-GET", "Downloading image from PACS " << serverId << ": " << server->AET << "@" << server->HostName << ":" << server->Port << " PDU=" << server->PDU << ", TLS=" << server->useTLS << ", User = " << server->pacsUser << ", Method=C-GET");
1368
1489
NetClient<GetAssociation> a(connectionKey, "C-GET", pNotificador);
1369
1490
a.SetModelo(pModelo);
1371
a.SetCallbackHandler(this);
1373
1492
if (server->useTLS) {
1374
1493
a.SetTLS(server->GetCertificate(), server->GetPrivateKey(), server->GetverifyCredentials());
1376
1495
if (server->GetPACSUser() != "") {
1377
1496
a.SetUserPass(server->GetPACSUser(), server->GetPACSPass());
1379
a.QueryServer(&query, server, pModelo, localAET, CT_MoveImagen);
1384
/** Gets the current server ID list */
1385
void PACSController::GetServerList(std::list<std::string>& /*list*/)
1498
if (!a.QueryServer(&query, server, pModelo, localAET, CT_MoveImagen)) {
1501
} else if (server->GetRetrieveMethod() == DicomServer::WADO) {
1502
//we have to get seriesInstance and studyInstanceUID...
1503
std::string seriesInstanceUID, studyInstanceUID;
1504
if (!base.getTag(GKDCM_SeriesInstanceUID, seriesInstanceUID) || !base.getTag(GKDCM_StudyInstanceUID, studyInstanceUID)) {
1505
FillInQuery(base, &query, server);
1507
e = newDicomElement(DCM_SpecificCharacterSet);
1508
e->putString(server->GetDefaultCharset().c_str());
1511
e = newDicomElement(DCM_QueryRetrieveLevel);
1512
e->putString(wxString( "IMAGE", wxConvUTF8).mb_str(conv));
1513
query.insert(e, true);
1515
e = newDicomElement(DCM_StudyInstanceUID);
1516
if (query.insert(e).bad()) {
1519
e = newDicomElement(DCM_SeriesInstanceUID);
1520
if (query.insert(e).bad()) {
1524
//association to make finds...
1525
NetClient<FindAssociation> f(connectionKey, "WADO/FIND", pNotificador);
1526
f.SetMaxResults(-1);
1528
std::string localAET = GNC::Entorno::Instance()->GetDicomLocalAET();
1530
if (server->useTLS) {
1531
f.SetTLS(server->GetCertificate(), server->GetPrivateKey(), server->GetverifyCredentials());
1533
if (server->GetPACSUser() != "") {
1534
f.SetUserPass(server->GetPACSUser(), server->GetPACSPass());
1538
if (!f.QueryServer(&query, server, pModelo, localAET, CT_None))
1546
DcmStack* stack = f.GetResultStack();
1550
for (unsigned int i = 0; i < stack->card(); i++) {
1552
if (stack->elem(i)->ident() == EVR_dataset) {
1553
DcmDataset* dset = dynamic_cast<DcmDataset*>(stack->elem(i));
1556
if ( dset->findAndGetOFString(DCM_StudyInstanceUID, tempOf).good() && tempOf.size() > 0 )
1558
studyInstanceUID = tempOf.c_str();
1560
if ( dset->findAndGetOFString(DCM_SeriesInstanceUID, tempOf).good() && tempOf.size() > 0 )
1562
seriesInstanceUID = tempOf.c_str();
1569
if (studyInstanceUID.empty() || seriesInstanceUID.empty()) {
1570
LOG_ERROR("PACSController", "StudyInstanceUID or SeriesInstanceUID not found");
1573
std::list<std::string> sopInstanceUIDs;
1574
sopInstanceUIDs.push_back(base.getTag(GKDCM_SOPInstanceUID));
1575
std::list<long> instanceNumbers;
1576
instanceNumbers.push_back(0);
1577
//now we have studyInstanceUID, seriesInstanceUID and sopInstancesUIDS.... download it!
1578
return DownloadWADOImages(serverId, studyInstanceUID, seriesInstanceUID, sopInstanceUIDs, instanceNumbers, pModelo, pNotificador, false);
1583
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
1584
size_t written = fwrite(ptr, size, nmemb, stream);
1588
//sopinstanceuids are sorted by instance number!
1589
bool PACSController::DownloadWADOImages(const std::string& serverId,
1590
const std::string& studyInstanceUID,
1591
const std::string& seriesInstanceUID,
1592
const std::list<std::string>& sopInstanceUID,
1593
const std::list<long>& instanceNumbers,
1594
IModeloDicom* pModelo,
1595
GNC::IProxyNotificadorProgreso* pNotificador,
1598
DicomServerList* listaServidores = DicomServerList::Instance();
1599
GNC::GCS::Ptr<DicomServer> server = listaServidores->GetServer(serverId);
1601
std::string pathOfSeries = GNC::Entorno::Instance()->CrearDirectorioTemporal();
1604
std::list<long>::const_iterator itInstanceNumber = instanceNumbers.begin();
1605
for (std::list<std::string>::const_iterator itSopInstances = sopInstanceUID.begin(); itSopInstances != sopInstanceUID.end(); ++itSopInstances, curr++, itInstanceNumber++)
1607
std::ostringstream progress;
1608
progress << _Std("Downloading file") << " " << curr << "/" << sopInstanceUID.size();
1609
if (!pNotificador->NotificarProgreso((float)(curr-1)/sopInstanceUID.size(), progress.str())) {
1612
std::ostringstream ostr;
1613
ostr << server->GetWADOURI();
1614
if (server->GetWADOURI().find("?") == std::string::npos) {
1617
ostr << "requestType=WADO&contentType=application%2Fdicom&studyUID=" << studyInstanceUID;
1618
ostr << "&seriesUID=" << seriesInstanceUID;
1619
ostr << "&objectUID=" << (*itSopInstances);
1620
std::string url = ostr.str();
1622
if (link && curr > 1) {
1624
const IModeloSerie* pSeries;
1625
pModelo->BuscarSerie(seriesInstanceUID, &pSeries);
1626
std::ostringstream ostr;
1627
ostr << (*itInstanceNumber);
1628
pModelo->InsertarImagen(seriesInstanceUID,(*itSopInstances), ostr.str(),url);
1630
//download first file of the series...
1631
std::ostringstream ofilePath;
1632
ofilePath << pathOfSeries << (char)wxFileName::GetPathSeparator();
1633
ofilePath << (*itSopInstances);
1634
std::string filePath = ofilePath.str();
1635
if (DownloadFileFromURL(url, filePath, pNotificador)) {
1637
GIL::DICOM::DicomDataset base;
1638
dm.CargarFichero(filePath, base);
1639
const IModeloPaciente& paciente = pModelo->InsertarPaciente(base.getTag(GKDCM_PatientID), base.getTag(GKDCM_PatientName), base.getTag(GKDCM_PatientBirthDate), base.getTag(GKDCM_PatientSex));
1640
pModelo->InsertarEstudio(paciente.GetUID(), base.getTag(GKDCM_StudyInstanceUID), base.getTag(GKDCM_AccessionNumber), base.getTag(GKDCM_StudyDescription), base.getTag(GKDCM_ModalitiesInStudy), base.getTag(GKDCM_StudyDate), base.getTag(GKDCM_StudyTime), base.getTag(GKDCM_ReferringPhysicianName));
1641
pModelo->InsertarSerie(base.getTag(GKDCM_StudyInstanceUID), base.getTag(GKDCM_SeriesInstanceUID), base.getTag(GKDCM_SeriesType), base.getTag(GKDCM_SeriesDate), base.getTag(GKDCM_SeriesTime), base.getTag(GKDCM_SeriesDescription), base.getTag(GKDCM_SeriesNumber),base.getTag(GKDCM_ReferringPhysicianName));
1642
pModelo->InsertarImagen(base.getTag(GKDCM_SeriesInstanceUID),base.getTag(GKDCM_SOPInstanceUID), base.getTag(GKDCM_InstanceNumber), filePath);
1644
}//end download first file of the series
1649
int progress_func_download_wado(void* ptr, double TotalToDownload, double NowDownloaded, double , double )
1651
GNC::IProxyNotificadorProgreso* pCmd = (GNC::IProxyNotificadorProgreso*)(ptr);
1652
if (pCmd != NULL && TotalToDownload != 0) {
1653
if (pCmd->NotificarProgreso((float)NowDownloaded/TotalToDownload, "")) {
1658
} else if (pCmd != NULL && NowDownloaded != 0) {
1659
wxString message = wxString::Format(wxT("Unknow file size downloaded %.2f Mb"), (float)NowDownloaded/(1024*1024));
1660
if (pCmd->NotificarProgreso((float)NowDownloaded/(10*1024*1024), std::string(message.ToUTF8()))) {
1670
bool PACSController::DownloadFileFromURL(const std::string& url, const std::string& filePath, GNC::IProxyNotificadorProgreso* pNotifier)
1672
LOG_DEBUG("PACSController", "Trying to download: " << url);
1676
http_handle = curl_easy_init();
1678
fp = fopen(filePath.c_str(), "wb");
1679
curl_easy_setopt(http_handle, CURLOPT_URL, url.c_str());
1681
wxProxySettings settings;
1682
settings.ProxySettingsLoadGeneral();
1683
if (settings.m_bUseProxy) {
1684
curl_easy_setopt(http_handle, CURLOPT_PROXY, std::string(settings.m_strProxyHostname.ToUTF8()).c_str());
1685
curl_easy_setopt(http_handle, CURLOPT_PROXYPORT, settings.m_nProxyPort);
1686
if (settings.m_bRequiresAuth) {
1687
curl_easy_setopt(http_handle, CURLOPT_PROXYUSERNAME,std::string(settings.m_strProxyUsername.ToUTF8()).c_str());
1688
curl_easy_setopt(http_handle, CURLOPT_PROXYPASSWORD, std::string(settings.m_strProxyPassword.ToUTF8()).c_str());
1690
curl_easy_setopt(http_handle, CURLOPT_NOPROXY, std::string(settings.m_strProxyExceptions.ToUTF8()).c_str());
1693
curl_easy_setopt(http_handle, CURLOPT_PROGRESSDATA , pNotifier);
1694
curl_easy_setopt(http_handle, CURLOPT_PROGRESSFUNCTION, progress_func_download_wado);
1695
curl_easy_setopt(http_handle, CURLOPT_NOPROGRESS, 0);
1697
curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, write_data);
1698
curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, fp);
1699
CURLcode res = curl_easy_perform(http_handle);
1702
curl_easy_getinfo (http_handle, CURLINFO_RESPONSE_CODE, &http_code);
1703
if (http_code == 200 && res != CURLE_ABORTED_BY_CALLBACK)
1706
curl_easy_cleanup(http_handle);
1709
curl_easy_cleanup(http_handle);
1710
LOG_ERROR("PACSController", "Error downloading file " << url << " Curl code (" << res << ") " << curl_easy_strerror(res) << " http status: " << http_code );
1711
std::ostringstream ostrMsg;
1712
ostrMsg << _Std("Error downloading WADO file") << " (HTTP Status: " << http_code << ") " << "URL :" << std::endl << url << std::endl << _Std("Check PACS configuration");
1713
throw GIL::DICOM::PACSException( ostrMsg.str());
1716
LOG_ERROR("PACSController", "Error initializing curl");
1717
throw GIL::DICOM::PACSException( "Error initialiting curl" );
1390
1721
/** Perform query */