public async Task <ModelResult> SegmentationResultAsync(string modelId, string segmentationId, IEnumerable <DicomFile> referenceDicomFiles, IEnumerable <TagReplacement> userReplacements)
        {
            await DelayAndThrowExceptionIfNotNull(SegmentationResultException).ConfigureAwait(false);

            if (RealSegmentation)
            {
                return(await _InnerEyeSegmentationClient.SegmentationResultAsync(modelId, segmentationId, referenceDicomFiles, userReplacements).ConfigureAwait(false));
            }
            else if (SegmentationProgressResult != null)
            {
                return(SegmentationProgressResult);
            }
            else
            {
                var dicomFile = await DicomFile.OpenAsync(SegmentationResultFile, FileReadOption.ReadAll).ConfigureAwait(false);

                dicomFile.Dataset.AddOrUpdate(DicomTag.SoftwareVersions,
                                              $@"InnerEye AI Model: Test.Name\" +
                                              $@"InnerEye AI Model ID: Test.ID\" +
                                              $@"InnerEye Model Created: Test.CreatedDate\" +
                                              $@"InnerEye Version: Test.AssemblyVersion\");

                dicomFile.Dataset.AddOrUpdate(DicomTag.SeriesDate,
                                              $"{DateTime.UtcNow.Year}{DateTime.UtcNow.Month:D2}{DateTime.UtcNow.Day:D2}");

                var anonymized = DeanonymizeDicomFile(
                    dicomFile,
                    referenceDicomFiles,
                    TopLevelReplacements,
                    userReplacements,
                    SegmentationAnonymisationProtocolId,
                    SegmentationAnonymisationProtocol);
                return(new ModelResult(100, string.Empty, anonymized));
            }
        }
        /// <summary>
        /// Gets the segmentation result.
        /// </summary>
        /// <param name="downloadQueueItem">The download queue item.</param>
        /// <param name="retryDelay">The delay between getting segmentation progress.</param>
        /// <param name="timeout">The maximum time we will wait for a segmentation result.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>The segmentation result Dicom file or null.</returns>
        private async Task <DicomFile> GetSegmentationResultAsync(DownloadQueueItem downloadQueueItem, TimeSpan retryDelay, TimeSpan timeout, CancellationToken cancellationToken)
        {
            var referenceDicomFiles = OpenDicomFiles(downloadQueueItem.ReferenceDicomFiles);

            // Attempting to download result
            LogInformation(LogEntry.Create(AssociationStatus.Downloading,
                                           downloadQueueItem: downloadQueueItem,
                                           downloadProgress: 0,
                                           downloadError: string.Empty));

            var tagReplacements = JsonConvert.DeserializeObject <IEnumerable <TagReplacement> >(downloadQueueItem.TagReplacementJsonString);

            // Create a new token for the maximum time we will sit and wait for a result.
            // Note: We need to check both the passed cancellation token and this new token for cancellation requests
            using (var cancellationTokenSource = new CancellationTokenSource(timeout))
            {
                while (!cancellationTokenSource.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
                {
                    var modelResult = await _innerEyeSegmentationClient.SegmentationResultAsync(
                        modelId : downloadQueueItem.ModelId,
                        segmentationId : downloadQueueItem.SegmentationID,
                        referenceDicomFiles : referenceDicomFiles,
                        userReplacements : tagReplacements);

                    if (modelResult.Progress == 100 && modelResult.DicomResult != null)
                    {
                        return(modelResult.DicomResult);
                    }
                    else if (!string.IsNullOrEmpty(modelResult.Error))
                    {
                        LogError(LogEntry.Create(AssociationStatus.Downloading,
                                                 downloadQueueItem: downloadQueueItem,
                                                 downloadProgress: modelResult.Progress,
                                                 downloadError: modelResult.Error),
                                 new Exception("Failed to get a segmentation result."));

                        // We cannot recover from this error, so we log and continue.
                        return(null);
                    }
                    else
                    {
                        LogInformation(LogEntry.Create(AssociationStatus.Downloading,
                                                       downloadQueueItem: downloadQueueItem,
                                                       downloadProgress: modelResult.Progress,
                                                       downloadError: modelResult.Error));
                    }

                    // Make sure you pass the cancellation token, not the timeout token, so the service can stop timely
                    await Task.Delay(retryDelay, cancellationToken);
                }
            }

            return(null);
        }