PACSRequestStatus::RetrieveRequestStatus RetrieveDICOMFilesFromPACS::retrieve(const QString &studyInstanceUID, const QString &seriesInstanceUID, const QString &sopInstanceUID)
{
    T_ASC_PresentationContextID presentationContextID;
    T_DIMSE_C_MoveRSP moveResponse;
    DcmDataset *statusDetail = NULL;
    m_pacsConnection = new PACSConnection(m_pacs);
    PACSRequestStatus::RetrieveRequestStatus retrieveRequestStatus;
    MoveSCPCallbackData moveSCPCallbackData;
    DcmDataset *dcmDatasetToRetrieve = getDcmDatasetOfImagesToRetrieve(studyInstanceUID, seriesInstanceUID, sopInstanceUID);
    m_numberOfImagesRetrieved = 0;

    // TODO S'hauria de comprovar que es tracti d'un PACS amb el servei de retrieve configurat
    if (!m_pacsConnection->connectToPACS(PACSConnection::RetrieveDICOMFiles))
    {
        ERROR_LOG("S'ha produit un error al intentar connectar al PACS per fer un retrieve. AE Title: " + m_pacs.getAETitle());
        return PACSRequestStatus::RetrieveCanNotConnectToPACS;
    }

    // Which presentation context should be used, It's important that the connection has MoveStudyRoot level
    T_ASC_Association *association = m_pacsConnection->getConnection();
    presentationContextID = ASC_findAcceptedPresentationContextID(association, MoveAbstractSyntax);
    if (presentationContextID == 0)
    {
        ERROR_LOG("No s'ha trobat cap presentation context valid");
        return PACSRequestStatus::RetrieveFailureOrRefused;
    }

    moveSCPCallbackData.association = association;
    moveSCPCallbackData.presentationContextId = presentationContextID;
    moveSCPCallbackData.retrieveDICOMFilesFromPACS = this;

    // Set the destination of the images to us
    T_DIMSE_C_MoveRQ moveRequest = getConfiguredMoveRequest(association);
    ASC_getAPTitles(association->params, moveRequest.MoveDestination, NULL, NULL);

    OFCondition condition = DIMSE_moveUser(association, presentationContextID, &moveRequest, dcmDatasetToRetrieve, moveCallback, &moveSCPCallbackData,
                                           DIMSE_BLOCKING, 0, m_pacsConnection->getNetwork(), subOperationCallback, this, &moveResponse, &statusDetail,
                                           NULL /*responseIdentifiers*/);

    if (condition.bad())
    {
        ERROR_LOG(QString("El metode descarrega no ha finalitzat correctament. Codi error: %1, descripcio error: %2").arg(condition.code())
                     .arg(condition.text()));
    }

    m_pacsConnection->disconnect();

    retrieveRequestStatus = getDIMSEStatusCodeAsRetrieveRequestStatus(moveResponse.DimseStatus);
    processServiceClassProviderResponseStatus(moveResponse.DimseStatus, statusDetail);
    
    // Dump status detail information if there is some
    if (statusDetail != NULL)
    {
        delete statusDetail;
    }

    delete dcmDatasetToRetrieve;

    return retrieveRequestStatus;
}
Example #2
0
OFCondition Association::SendObject(DcmDataset *dataset) {
	OFCondition cond;
	DcmDataset *statusDetail = NULL;

	T_DIMSE_C_StoreRQ req;
	T_DIMSE_C_StoreRSP rsp;

	// check if we SOPClass and SOPInstance in dataset
	if (!DU_findSOPClassAndInstanceInDataSet(dataset, sopClass, sopInstance))
	{
		return DIMSE_BADDATA;
	}

	/* which presentation context should be used */
	presId = ASC_findAcceptedPresentationContextID(assoc, sopClass);
	if (presId == 0)
	{
		const char *modalityName = dcmSOPClassUIDToModality(sopClass);
		if (!modalityName) modalityName = dcmFindNameOfUID(sopClass);
		if (!modalityName) modalityName = "unknown SOP class";
		return DIMSE_BADDATA;
	}

	// init store

	bzero((char*)&req, sizeof(req));
	req.MessageID = msgId;
	strncpy(req.AffectedSOPClassUID, sopClass, sizeof(req.AffectedSOPClassUID));
	strncpy(req.AffectedSOPInstanceUID, sopInstance, sizeof(req.AffectedSOPInstanceUID));
	req.DataSetType = DIMSE_DATASET_PRESENT;
	req.Priority = DIMSE_PRIORITY_LOW;

	// convert to accepted transfer syntax
	T_ASC_PresentationContext pc;
	cond = ASC_findAcceptedPresentationContext(assoc->params, presId, &pc);
	ASC_dumpPresentationContext(&pc, COUT);

	DJEncoderRegistration::registerCodecs(
		ECC_lossyYCbCr,
		EUC_never,					// UID generation (never create new UID's)
		OFFalse,							// verbose
		OFTrue);							// optimize huffman table
	
	DJDecoderRegistration::registerCodecs();

	DcmXfer opt_oxferSyn(pc.acceptedTransferSyntax);
	E_TransferSyntax ori_oxferSyn = dataset->getOriginalXfer();

    DcmXfer original_xfer(dataset->getOriginalXfer());

	if(opt_oxferSyn.getXfer() != ori_oxferSyn) {
		std::cout << "Converting object to accepted transfer-syntax " << opt_oxferSyn.getXferName() << std::endl;
	
		OFCondition cond;
		// create RepresentationParameter
		DJ_RPLossless rp_lossless(6, 0);
		DJ_RPLossy rp_lossy(m_CompressionQuality);

		// NEW
		
		const DcmRepresentationParameter *rp = NULL;

		if(opt_oxferSyn.getXfer() == EXS_JPEGProcess14SV1 || opt_oxferSyn.getXfer() == EXS_JPEGProcess14) {
			rp = &rp_lossless;
		}
		else if(opt_oxferSyn.getXfer() == EXS_JPEGProcess1 || opt_oxferSyn.getXfer() == EXS_JPEGProcess2_4) {
			rp = &rp_lossy;
		}

		// recompress ?
		if(rp != NULL) {
		    if(original_xfer.isEncapsulated()) {
				std::cout << "DICOM file is already compressed, convert to uncompressed xfer syntax first\n";
				if(EC_Normal != dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL)) {
					std::cout << "No conversion from compressed original to uncompressed xfer syntax possible!\n";
				}
			}
		}

		cond = dataset->chooseRepresentation(opt_oxferSyn.getXfer(), rp);
		if(cond.bad()) {
			DimseCondition::dump(cond);
		}
	
		if (dataset->canWriteXfer(opt_oxferSyn.getXfer())) {
			std::cout << "Output transfer syntax " << opt_oxferSyn.getXferName() << " can be written" << std::endl;
		}
		else {
			std::cout << "No conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!" << std::endl;
		}
	}

	// store it

	cond = DIMSE_storeUser(
				assoc, 
				presId, 
				&req, 
				NULL, 
				dataset, 
				NULL,
				NULL, 
				(m_timeout == 0) ? DIMSE_BLOCKING : DIMSE_NONBLOCKING,
				m_timeout, 
				&rsp, 
				&statusDetail);
	
	// increase message id
	msgId++;

	// what happened

	if(rsp.DataSetType == DIMSE_DATASET_PRESENT) {
		printf("Response with dataset:\n");
	}
	
	if (statusDetail != NULL) {
		printf("Status detail:\n");
		statusDetail->print(COUT, false);
		delete statusDetail;
	}

	if (cond != EC_Normal)
	{
		return cond;
	}

	return (rsp.DimseStatus == STATUS_Success) ? EC_Normal : DIMSE_BADDATA;
}
OFCondition Association::SendObject(DcmDataset *dataset)
{
        OFCondition cond = EC_Normal;
        DcmDataset *statusDetail = NULL;

        if (Stopped()) {
                return DUL_NETWORKCLOSED;
        }

        T_DIMSE_C_StoreRQ req;
        T_DIMSE_C_StoreRSP rsp;

        // check if we SOPClass and SOPInstance in dataset
        if (!DU_findSOPClassAndInstanceInDataSet(dataset, sopClass, sopInstance)) {
                return makeOFCondition(OFM_dcmnet, DIMSEC_BADDATA, OF_error, "No SOPClass or SOPInstanceUID found on dataset");
        }

        /* which presentation context should be used */
        presId = ASC_findAcceptedPresentationContextID(assoc, sopClass);
        if (presId == 0) {
                const char *modalityName = dcmSOPClassUIDToModality(sopClass);
                if (!modalityName) modalityName = dcmFindNameOfUID(sopClass);
                if (!modalityName) modalityName = "unknown SOP class";
                std::ostringstream os;
                os << "No valid presentation context found. SOPClass = " << sopClass << " Modality = " << modalityName;
                return makeOFCondition(OFM_dcmnet, DIMSEC_BADDATA, OF_error, os.str().c_str());
        }

        bzero((char*) & req, sizeof (req));
        req.MessageID = msgId;
        strncpy(req.AffectedSOPClassUID, sopClass, sizeof (req.AffectedSOPClassUID)-1);
        req.AffectedSOPClassUID[sizeof (req.AffectedSOPClassUID)-1] = 0;
        strncpy(req.AffectedSOPInstanceUID, sopInstance, sizeof (req.AffectedSOPInstanceUID)-1);
        req.AffectedSOPInstanceUID[sizeof(req.AffectedSOPInstanceUID)-1] = 0;

        req.DataSetType = DIMSE_DATASET_PRESENT;
        req.Priority = DIMSE_PRIORITY_LOW;

        // convert to accepted transfer syntax
        T_ASC_PresentationContext pc;
        cond = ASC_findAcceptedPresentationContext(assoc->params, presId, &pc);
        ASC_dumpPresentationContext(&pc, COUT);

        DcmXfer opt_oxferSyn(pc.acceptedTransferSyntax);
        E_TransferSyntax ori_oxferSyn = dataset->getOriginalXfer();

        DcmXfer original_xfer(dataset->getOriginalXfer());

        if (opt_oxferSyn.getXfer() != ori_oxferSyn) {
                LOG_DEBUG(ambitolog, "Converting object into accepted Transfer-Syntax: " << opt_oxferSyn.getXferName());

                OFCondition cond;
                // create RepresentationParameter
                DJ_RPLossless rp_lossless(6, 0);
                DJ_RPLossy rp_lossy(70);

                // NEW

                const DcmRepresentationParameter *rp = NULL;

                if (opt_oxferSyn.getXfer() == EXS_JPEGProcess14SV1 || opt_oxferSyn.getXfer() == EXS_JPEGProcess14) {
                        rp = &rp_lossless;
                } else if (opt_oxferSyn.getXfer() == EXS_JPEGProcess1 || opt_oxferSyn.getXfer() == EXS_JPEGProcess2_4) {
                        rp = &rp_lossy;
                }

                // recompress ?
                if (rp != NULL) {
                        if (original_xfer.isEncapsulated()) {
                                LOG_DEBUG(ambitolog, "The DICOM file is already compressed. It will previously converted to uncompressed Transfer Syntax");
                                if (EC_Normal != dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL)) {
                                        return makeOFCondition(OFM_dcmnet, DIMSEC_BADDATA, OF_error, "Unable to convert the original format to uncompressed Transfer Syntax");
                                }
                        }
                }

                cond = dataset->chooseRepresentation(opt_oxferSyn.getXfer(), rp);
                if (cond.bad()) {
                        LOG_ERROR(ambitolog, "Error choosing representation: " << cond.text());
                }

                if (dataset->canWriteXfer(opt_oxferSyn.getXfer())) {
                        LOG_DEBUG(ambitolog, "The output transfer syntax (" <<  opt_oxferSyn.getXferName() << " can be writen");
                } else {
                        std::ostringstream os;
                        os << "Unable to find any possible converson to output Transfer Syntax " <<  opt_oxferSyn.getXferName();
                        return makeOFCondition(OFM_dcmnet, DIMSEC_BADDATA, OF_error, os.str().c_str());
                }
        }

        // store it

        cond = DIMSE_storeUser(
                       assoc,
                       presId,
                       &req,
                       NULL,
                       dataset,
                       NULL,
                       NULL,
                       (m_timeout == 0) ? DIMSE_BLOCKING : DIMSE_NONBLOCKING,
                       m_timeout,
                       &rsp,
                       &statusDetail);

        // increase message id
        msgId++;

        // what happened

        if (rsp.DataSetType == DIMSE_DATASET_PRESENT) {
                LOG_DEBUG(ambitolog, "Response with dataset");
        }

        if (statusDetail != NULL) {
                LOG_TRACE(ambitolog, "Status: " << DumpDataset(statusDetail));
                delete statusDetail;
        }

        if (cond != EC_Normal) {
                return cond;
        }

        if (rsp.DimseStatus == STATUS_Success) {
                return EC_Normal;
        } else {
                LOG_ERROR(ambitolog, "DIMSE Status failed: " << rsp.DimseStatus);
                return DIMSE_BADDATA;
        }
}
OFCondition FindAssociation::findSCU(T_ASC_Association *assoc, DcmDataset *query)
{
        OFCondition cond;
        DIC_US msgId = assoc->nextMsgID++;
        T_ASC_PresentationContextID presId;
        T_DIMSE_C_FindRQ req;
        T_DIMSE_C_FindRSP rsp;
        DcmDataset *statusDetail = NULL;
        std::string errorMessage;

        if (query == NULL) {
                return makeOFCondition(OFM_dcmnet, DIMSEC_BADDATA, OF_error, "NULL DIMSE Query");
        }

        DeleteResultStack();

        /* which presentation context should be used */
        presId = ASC_findAcceptedPresentationContextID(assoc, m_abstractSyntax.c_str());
        if (presId == 0) {
                LOG_ERROR(ambitolog, "Invalid PresentationContextId");
                return DIMSE_NOVALIDPRESENTATIONCONTEXTID;
        }

        req.MessageID = msgId;
        req.DataSetType = DIMSE_DATASET_PRESENT;
        req.Priority = DIMSE_PRIORITY_LOW;
        strncpy(req.AffectedSOPClassUID, m_abstractSyntax.c_str(), DIC_UI_LEN);
        req.AffectedSOPClassUID[DIC_UI_LEN] = 0;

        FindCallbackInfo callbackData;
        callbackData.pCaller = this;
        callbackData.assoc = assoc;

        cond = DIMSE_findUser(assoc, presId, &req, query,
                              findCallback, (void*) &callbackData,
                              (m_timeout == 0) ? DIMSE_BLOCKING : DIMSE_NONBLOCKING,
                              m_timeout,
                              &rsp, &statusDetail);

        if(rsp.DimseStatus != STATUS_Success && rsp.DimseStatus != STATUS_Pending) {
                std::ostringstream os;
                os << DU_cfindStatusString(rsp.DimseStatus);
                if (statusDetail != NULL) {
                        OFString errorComment;
                        if (statusDetail->findAndGetOFString(DCM_ErrorComment, errorComment).good()) {
                                os << ". " << errorComment.c_str();
                        }
                }
                errorMessage = os.str();
        }

        if (cond == EC_Normal) {
                if (rsp.DimseStatus == STATUS_Success) {
                }
        }

        if (statusDetail != NULL) {
                LOG_DEBUG(ambitolog, "DIMSE_findUser(): Status: " << std::endl << DumpDataset(statusDetail));
                delete statusDetail;
        }

        if (rsp.DimseStatus != STATUS_Success && rsp.DimseStatus != STATUS_Pending) {
                return makeOFCondition(OFM_dcmnet, 18, OF_error, errorMessage.c_str());
        }

        return cond;
}