Compare commits

...

2 Commits

Author SHA1 Message Date
ae69d5ef41 prod temp changes 2024-07-24 00:27:44 +05:30
c0ff0f35c3 DicomMigratorApp 2024-07-22 18:08:33 +05:30
3 changed files with 120 additions and 68 deletions

22
Dockerfile Normal file
View File

@ -0,0 +1,22 @@
# Use the official .NET SDK image to build the app
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app
# Copy the csproj and restore any dependencies
COPY *.csproj ./
RUN dotnet restore
# Copy the entire project and build the app
COPY . ./
RUN dotnet publish -c Release -o out
# Use the official .NET runtime image to run the app
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build-env /app/out .
# Expose port
EXPOSE 80
# Entry point to run the application
ENTRYPOINT ["dotnet", "DicomMigratorApp.dll"]

View File

@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System.Threading;
namespace DicomMigratorApp namespace DicomMigratorApp
{ {
@ -20,8 +21,8 @@ namespace DicomMigratorApp
private static string targetIP; private static string targetIP;
private static string senderAET; private static string senderAET;
private static string targetAET; private static string targetAET;
private static string folderLocation;
private static int targetPort; private static int targetPort;
private static string db_status_to_pick;
static async Task Main(string[] args) static async Task Main(string[] args)
{ {
@ -38,12 +39,12 @@ namespace DicomMigratorApp
_logger.LogInformation("Application started"); _logger.LogInformation("Application started");
connectionString = "Server=127.0.0.1;Port=3306;Database=dms_db;User Id=root;Password=Rootmatrix23@;"; connectionString = Environment.GetEnvironmentVariable("ConnectionStrings__DefaultConnection") ?? "Server=127.0.0.1;Port=3306;Database=dms_db;User Id=root;Password=Rootmatrix23@;";
targetIP = "127.0.0.1"; targetIP = Environment.GetEnvironmentVariable("Dest__IP") ?? "127.0.0.1";
senderAET = "MYAE"; senderAET = Environment.GetEnvironmentVariable("Sender__AET") ?? "MYAE";
targetAET = "ORTHANC"; targetAET = Environment.GetEnvironmentVariable("Dest__AET") ?? "ORTHANC";
folderLocation = "D:\\dicom_imags\\"; var targetPortStr = Environment.GetEnvironmentVariable("Dest__Port") ?? "4242";
var targetPortStr = "4242"; db_status_to_pick = Environment.GetEnvironmentVariable("DB_STATUS") ?? "MIGRATION_QUEUE";
if (!int.TryParse(targetPortStr, out targetPort)) if (!int.TryParse(targetPortStr, out targetPort))
{ {
@ -51,126 +52,134 @@ namespace DicomMigratorApp
return; return;
} }
while (true)
{
try try
{ {
var migrationStudy = await GetMigrationStudy(connectionString); var imagePaths = await GetMigrationImages(connectionString,db_status_to_pick);
if (migrationStudy == null) if (imagePaths == null || imagePaths.Count == 0)
{ {
_logger.LogInformation("No studies found for migration."); await Task.Delay(5000);
return; continue;
} }
_logger.LogInformation($"Retrieved studyDetails for Migration"); foreach (var image in imagePaths)
{
try try
{ {
await MigrateStudy(migrationStudy.StudyInstanceUID, folderLocation + migrationStudy.StudyInstanceUID); await MigrateImage(image.Path);
await UpdateSourceCFind(connectionString, migrationStudy.StudyInstanceUID, "MIGRATION_COMPLETE"); await UpdateImagePathStatus(connectionString, image.Id, "MIGRATION_COMPLETE");
} }
catch (DicomAssociationRejectedException ex) catch (DicomAssociationRejectedException ex)
{ {
_logger.LogError(ex, $"Association rejected for studyInstanceUID {migrationStudy.StudyInstanceUID}"); _logger.LogError(ex, $"Association rejected for image path {image.Path}");
await UpdateSourceCFind(connectionString, migrationStudy.StudyInstanceUID, "MIGRATION_ERRORED"); await UpdateImagePathStatus(connectionString, image.Id, "MIGRATION_ERRORED");
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, $"An error occurred while retrieving or saving studyInstanceUID {migrationStudy.StudyInstanceUID}"); _logger.LogError(ex, $"An error occurred while migrating image path {image.Path}");
await UpdateSourceCFind(connectionString, migrationStudy.StudyInstanceUID, "MIGRATION_ERRORED"); await UpdateImagePathStatus(connectionString, image.Id, "MIGRATION_ERRORED");
} }
} }
}
catch (MySqlException ex)
{
_logger.LogError(ex, "An error occurred while connecting to the database");
break;
}
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "An error occurred in the main processing loop"); _logger.LogError(ex, "An error occurred in the main processing loop");
break;
}
} }
} }
private static async Task<SourceStudy> GetMigrationStudy(string connectionString) private static async Task<List<ImageRecord>> GetMigrationImages(string connectionString, string db_status_to_pick)
{ {
var qrStudy = new SourceStudy(); var imagePaths = new List<ImageRecord>();
try try
{ {
using (var connection = new MySqlConnection(connectionString)) using (var connection = new MySqlConnection(connectionString))
{ {
_logger.LogInformation("Opening a connection to the database");
await connection.OpenAsync(); await connection.OpenAsync();
_logger.LogInformation("Database connection established"); _logger.LogInformation("Database connection established");
var command = new MySqlCommand("SELECT study_instance_uid,patient_id,status FROM source_cfind WHERE status='QR_COMPLETE' LIMIT 1", connection);
var command = new MySqlCommand("SELECT id, image_path FROM priority_migration_image WHERE status=@Status order by priority LIMIT 10", connection);
command.Parameters.AddWithValue("@Status", db_status_to_pick);
var reader = await command.ExecuteReaderAsync(); var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync()) while (await reader.ReadAsync())
{ {
qrStudy = new SourceStudy imagePaths.Add(new ImageRecord
{ {
StudyInstanceUID = reader.IsDBNull(0) ? null : reader.GetString(0), Id = reader.IsDBNull(0) ? 0 : reader.GetInt32(0),
PatientID = reader.IsDBNull(1) ? null : reader.GetString(1), Path = reader.IsDBNull(1) ? null : reader.GetString(1)
Status = reader.IsDBNull(2) ? null : reader.GetString(2) });
};
} }
reader.Close(); reader.Close();
} }
if (qrStudy.StudyInstanceUID != null) _logger.LogInformation($"Retrieved {imagePaths.Count} image paths for migration");
{
_logger.LogInformation("Picked study to be migrated from the database");
await UpdateSourceCFind(connectionString, qrStudy.StudyInstanceUID, "MIGRATION_INPROGRESS");
}
else
{
qrStudy = null;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Error retrieving study to be migrated from the database"); _logger.LogError(ex, "Error retrieving image paths from the database");
throw; // Re-throw the exception to ensure it is caught by the outer try-catch block
} }
return qrStudy; return imagePaths;
} }
private static async Task UpdateSourceCFind(string connectionString, string study_instance_uid, string updateStatus) private static async Task UpdateImagePathStatus(string connectionString, int imageId, string updateStatus)
{ {
try try
{ {
using (var connection = new MySqlConnection(connectionString)) using (var connection = new MySqlConnection(connectionString))
{ {
await connection.OpenAsync(); await connection.OpenAsync();
var command = new MySqlCommand("UPDATE source_cfind SET status = @Status WHERE study_instance_uid = @StudyInstanceUID", connection); var command = new MySqlCommand("UPDATE priority_migration_image SET status = @Status WHERE id = @ImageId", connection);
command.Parameters.AddWithValue("@StudyInstanceUID", study_instance_uid); command.Parameters.AddWithValue("@ImageId", imageId);
command.Parameters.AddWithValue("@Status", updateStatus); command.Parameters.AddWithValue("@Status", updateStatus);
await command.ExecuteNonQueryAsync(); await command.ExecuteNonQueryAsync();
_logger.LogInformation($"Updated source C-FIND record for study instance uid {study_instance_uid}"); _logger.LogInformation($"Updated image path record for image ID {imageId} with status {updateStatus}");
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, $"Error updating source study record for study {study_instance_uid}"); _logger.LogError(ex, $"Error updating image path record for image ID {imageId}");
throw; // Re-throw the exception to ensure it is caught by the outer try-catch block
} }
} }
private static async Task MigrateStudy(string studyInstanceUID, string folderPath) private static async Task MigrateImage(string imagePath)
{
try
{ {
var client = DicomClientFactory.Create(targetIP, targetPort, false, senderAET, targetAET); var client = DicomClientFactory.Create(targetIP, targetPort, false, senderAET, targetAET);
var files = System.IO.Directory.GetFiles(folderPath, "*"); var dicomFile = await DicomFile.OpenAsync(imagePath);
foreach (var file in files)
{
var dicomFile = await DicomFile.OpenAsync(file);
await client.AddRequestAsync(new DicomCStoreRequest(dicomFile)); await client.AddRequestAsync(new DicomCStoreRequest(dicomFile));
}
await client.SendAsync(); await client.SendAsync();
_logger.LogInformation($"Migrated studyInstanceUID {studyInstanceUID} to target AET {targetAET}"); _logger.LogInformation($"Migrated image {imagePath} to target AET {targetAET}");
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error migrating image {imagePath}");
throw; // Re-throw the exception to ensure it is caught by the outer try-catch block
}
} }
} }
class SourceStudy class ImageRecord
{ {
public string PatientID { get; set; } public int Id { get; set; }
public string StudyInstanceUID { get; set; } public string Path { get; set; }
public string Status { get; set; }
} }
} }

21
docker-compose.yml Normal file
View File

@ -0,0 +1,21 @@
version: '3.8'
services:
dicom-migrator-app:
image: seyfertsoft/dicommigratorapp:1.0.0
container_name: dicommigrator
environment:
- "ConnectionStrings__DefaultConnection=Server=mysqldb;Port=3306;Database=dms_db;User Id=root;Password=Rootmatrix23@;"
- Dest__IP=127.0.0.1
- Sender__AET=MYAE
- Dest__AET=ORTHANC
- Dest__Port=4242
volumes:
- /path/to/images1:/app/images1
- /path/to/images2:/app/images2
networks:
- dmsnetwork
networks:
dmsnetwork:
external: true