C-Move fo-dicom implementation downloading a single file only

658 views
Skip to first unread message

Harshal Srivastava

unread,
Jun 8, 2020, 7:11:13 AM6/8/20
to Fellow Oak DICOM
Hello Everybody

My name is Harshal

I am learning how to interact with PACS and am using Fo-Dicom Unity Asset Store Package.

So far I am able to successfully find the patient study and series data.

For downloading the images, I have made some implementation using C-Move and CStoreSCP but when I run it, it only downloads a single DICOM image (even when I am trying for whole series) and I guess it is just downloading the last DICOM image in the series.

Here is my code implementation: 

server = DicomServer.Create<CStoreSCP>(104);
DicomCMoveRequest cmoverequest = CreateCMoveRequest(studyInstanceUID, seriesInstanceUID);
cmoverequest.OnResponseReceived += StoreResponse;
client.AddRequest(cmoverequest);
client.Send(serverName, portNumber, false, callingAE, calledAE);

Here is the CreateCMoveRequest function definition:

 public static DicomCMoveRequest CreateCMoveRequest(string studyUID, string seriesUID)
    {
        //var request = new DicomCMoveRequest("MYSCP",studyUID,seriesUID);
        DicomCMoveRequest request = new DicomCMoveRequest("MYSCP", studyUID, seriesUID);
        
        request.Dataset.AddOrUpdate(DicomTag.QueryRetrieveLevel, DicomQueryRetrieveLevel.Series);

        request.Dataset.AddOrUpdate(DicomTag.StudyInstanceUID, studyUID);
        request.Dataset.AddOrUpdate(DicomTag.SeriesInstanceUID, seriesUID);
        // no more dicomtags have to be set
        return request;
    }


Here is my CStoreSCP implementation:

public class CStoreSCP : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider
{
    public delegate DicomCStoreResponse OnCStoreRequestCallback(DicomCStoreRequest request);
    public static event OnCStoreRequestCallback CStoreRequestCallBack;
    private static readonly DicomTransferSyntax[] AcceptedTransferSyntaxes = new DicomTransferSyntax[]
    {
               DicomTransferSyntax.ExplicitVRLittleEndian,
               DicomTransferSyntax.ExplicitVRBigEndian,
               DicomTransferSyntax.ImplicitVRLittleEndian
    };

    private static readonly DicomTransferSyntax[] AcceptedImageTransferSyntaxes = new DicomTransferSyntax[]
    {
               // Lossless
               DicomTransferSyntax.JPEGLSLossless,
               DicomTransferSyntax.JPEG2000Lossless,
               DicomTransferSyntax.JPEGProcess14SV1,
               DicomTransferSyntax.JPEGProcess14,
               DicomTransferSyntax.RLELossless,
               // Lossy
               DicomTransferSyntax.JPEGLSNearLossless,
               DicomTransferSyntax.JPEG2000Lossy,
               DicomTransferSyntax.JPEGProcess1,
               DicomTransferSyntax.JPEGProcess2_4,
               // Uncompressed
               DicomTransferSyntax.ExplicitVRLittleEndian,
               DicomTransferSyntax.ExplicitVRBigEndian,
               DicomTransferSyntax.ImplicitVRLittleEndian
    };

    public CStoreSCP(INetworkStream stream, Encoding fallbackEncoding, Dicom.Log.Logger log)
        : base(stream, fallbackEncoding, log)
    {
    }

    public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
    {
        Debug.LogError("association request : called AE " + association.CalledAE + " calling ae : " + association.CallingAE);
        if (association.CalledAE != "MYSCP")
        {
            return SendAssociationRejectAsync(
                DicomRejectResult.Permanent,
                DicomRejectSource.ServiceUser,
                DicomRejectReason.CalledAENotRecognized);
        }

        foreach (var pc in association.PresentationContexts)
        {
            if (pc.AbstractSyntax == DicomUID.Verification)
            {
                pc.AcceptTransferSyntaxes(AcceptedTransferSyntaxes);
                Debug.LogError("condition 1 calling");
            }
            else if (pc.AbstractSyntax.StorageCategory != DicomStorageCategory.None)
            {
                pc.AcceptTransferSyntaxes(AcceptedImageTransferSyntaxes);
                Debug.LogError("condition 2 calling");
            }
        }

        return SendAssociationAcceptAsync(association);
    }

    public Task OnReceiveAssociationReleaseRequestAsync()
    {
        return SendAssociationReleaseResponseAsync();
    }

    public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
    {
    }

    public void OnConnectionClosed(Exception exception)
    {
        Debug.LogError("connection closed");
    }
    public string storagePath;
    //public static OnCStoreRequestCallback OnCStoreRequestCallBack;
    public DicomCStoreResponse OnCStoreRequest(DicomCStoreRequest request)
    {
        // Debug.LogError("asdosahjd : dataset " + request.Dataset.ToString());
        Debug.LogError(request.Dataset.WriteToString());
        var studyUid = request.Dataset.Get<string>(DicomTag.StudyInstanceUID,"not found");
        var instUid = request.SOPInstanceUID.UID;
        storagePath = "C:/Users/user/Downloads/Series4";
        //var path = Path.GetFullPath(storagePath);
        //path = Path.Combine(path, studyUid);
        var path = storagePath + "/" + studyUid;
        if (!Directory.Exists(path))
            Directory.CreateDirectory(path);

        path = Path.Combine(path, instUid) + ".dcm";

        request.File.Save(path);
        //if (CStoreRequestCallBack! = null)
        //{
        //    return OnCStoreRequestCallBack(request);
        //}
        Debug.LogError("cstore request called");
        return new DicomCStoreResponse(request, DicomStatus.NoSuchActionType);
       

        //return new DicomCStoreResponse(request, DicomStatus.Success);
    }

    public void OnCStoreRequestException(string tempFileName, Exception e)
    {
        // let library handle logging and error response
    }

    public DicomCEchoResponse OnCEchoRequest(DicomCEchoRequest request)
    {
        return new DicomCEchoResponse(request, DicomStatus.Success);
    }
}


When I run the code. only a single file gets downloaded and in the CMoveRequest response I get Failure [c000: Cannot understand]

Any help on this would be highly appreciated

Thank you

Reinhard Gruber

unread,
Jul 3, 2020, 3:31:26 AM7/3/20
to Fellow Oak DICOM
Hi,

your StoreSCP's method   `OnCStoreRequest(DicomCStoreRequest request)` seems to return `DicomStatus.NoSuchActionType`. This will indicate an error on the server side, so I guess thats why the server aborts sending after the first file.

You should remove this line and instead return `DicomStatus.Success` if everything went fine.
Reply all
Reply to author
Forward
0 new messages