Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
celeron533 committed Nov 19, 2023
1 parent 12432a0 commit 90a1648
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 83 deletions.
108 changes: 27 additions & 81 deletions DicomGrepCore/DicomGrepCore.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using FellowOakDicom;
using System.Text;
using System;
using DicomGrepCore.Extensions;
using DicomGrepCore.EventArgs;
using DicomGrepCore.Models;
using DicomGrepCore.Utils;

namespace DicomGrepCore
{
Expand All @@ -23,25 +23,23 @@ public class DicomGrepCore
public delegate void OnSearchCompleteDelegate(object sender, OnSearchCompleteEventArgs e);
public event OnSearchCompleteDelegate OnSearchComplete;

private SearchCriteria criteria;
private List<string> filenameList = new List<string>();
private List<string> matchFilenameList = new List<string>();
private CancellationToken token;

private int searchedFileCount = 0;
private int matchFileCount = 0;

public void SearchInDicomFile(string filePath, in SearchCriteria criteria)
public bool SearchInDicomFile(string filePath, in SearchCriteria criteria)
{
ResultDicomFile resultDicomFile = null;

Check warning on line 34 in DicomGrepCore/DicomGrepCore.cs

View workflow job for this annotation

GitHub Actions / build (Debug, 6.0.x)

Converting null literal or possible null value to non-nullable type.
bool anyMatch = false;
bool hasMatch = false;

try
{
OnLoadDicomFile?.Invoke(this, new OnLoadDicomFileEventArgs(filePath));

DicomFile dicomFile = DicomFile.Open(filePath, FileReadOption.ReadLargeOnDemand, 16 * 1024);

IList<ResultDicomItem> resultDicomItems = new List<ResultDicomItem>();
//new DicomDatasetWalker(dicomFile.Dataset).Walk(new DatasetWalker());

string patientName = string.Empty;
Expand All @@ -51,14 +49,17 @@ public void SearchInDicomFile(string filePath, in SearchCriteria criteria)
// if the criteria provides sop class uid, filter this file
if (!string.IsNullOrWhiteSpace(criteria.SearchSopClassUid) && sopClassUID.UID != criteria.SearchSopClassUid)
{
return;
return false;
}

dicomFile.Dataset.TryGetString(DicomTag.PatientName, out patientName);

CompareDicomTagAndValue(dicomFile.FileMetaInfo, ref resultDicomItems);
CompareDicomTagAndValue(dicomFile.Dataset, ref resultDicomItems);
IList<ResultDicomItem> resultDicomItems =
CompareDicomTagAndValue(dicomFile.FileMetaInfo, criteria).Concat(
CompareDicomTagAndValue(dicomFile.Dataset, criteria))
.ToList();

hasMatch = resultDicomItems.Count > 0;
resultDicomFile = new ResultDicomFile(filePath, sopClassUID, patientName, resultDicomItems);

}
Expand All @@ -73,20 +74,16 @@ public void SearchInDicomFile(string filePath, in SearchCriteria criteria)
logger.Warn(ex);
}
}
finally
{
OnCompletDicomFile?.Invoke(this,
new OnCompleteDicomFileEventArgs(filePath, resultDicomFile));
}

OnCompletDicomFile?.Invoke(this,
new OnCompleteDicomFileEventArgs(filePath, resultDicomFile));

Check warning on line 79 in DicomGrepCore/DicomGrepCore.cs

View workflow job for this annotation

GitHub Actions / build (Debug, 6.0.x)

Possible null reference argument for parameter 'resultDicomFile' in 'OnCompleteDicomFileEventArgs.OnCompleteDicomFileEventArgs(string filename, ResultDicomFile resultDicomFile)'.
return hasMatch;
}

public void Search(SearchCriteria criteria, CancellationTokenSource tokenSource)
{
logger.Info(criteria.ToString());

this.criteria = criteria;
this.token = tokenSource.Token;

searchedFileCount = 0;


Expand All @@ -99,7 +96,7 @@ public void Search(SearchCriteria criteria, CancellationTokenSource tokenSource)
else
{
// construct new filename list
CreateFilenameList();
CreateFilenameList(criteria, tokenSource);
}

FileListCompleted?.Invoke(this, new ListFileCompletedEventArgs(filenameList));
Expand All @@ -110,14 +107,16 @@ public void Search(SearchCriteria criteria, CancellationTokenSource tokenSource)
ParallelOptions options = new ParallelOptions
{
MaxDegreeOfParallelism = criteria.SearchThreads,
CancellationToken = this.token
CancellationToken = tokenSource.Token
};
try
{
Parallel.ForEach(filenameList, options, (filename, loopStat) =>
{
options.CancellationToken.ThrowIfCancellationRequested();
SearchInDicomFile(filename, criteria);
bool hasMatch = SearchInDicomFile(filename, criteria);
Interlocked.Increment(ref searchedFileCount);
if (hasMatch) Interlocked.Increment(ref matchFileCount);
});
OnSearchComplete?.Invoke(this, new OnSearchCompleteEventArgs { Reason = Enums.ReasonEnum.Normal });
}
Expand All @@ -134,60 +133,30 @@ public void Search(SearchCriteria criteria, CancellationTokenSource tokenSource)



private void CreateFilenameList()
private void CreateFilenameList(SearchCriteria criteria, CancellationTokenSource tokenSource)
{
filenameList.Clear();

if (Directory.Exists(criteria.SearchPath))
{
LookupDirectory(criteria.SearchPath, criteria.FileTypes, criteria.IncludeSubfolders);
filenameList = Util.LookupDirectory(criteria.SearchPath, criteria.FileTypes, criteria.IncludeSubfolders ? int.MaxValue : 0, tokenSource);
}
}

private void LookupDirectory(in string directoryPath, in string fileTypes, in bool includeSubfolders)
{
try
{
if (token.IsCancellationRequested)
return;
else
Array.ForEach(Directory.GetFiles(directoryPath, fileTypes), fn => filenameList.Add(fn));
}
catch (Exception e)
{
logger.Error(e, $"Unable to access files in: '{directoryPath}'");
}

if (includeSubfolders)
{
try
{
foreach (string subdirectory in Directory.GetDirectories(directoryPath))
{
if (token.IsCancellationRequested)
return;
else
LookupDirectory(subdirectory, fileTypes, includeSubfolders);
}
}
catch (Exception e)
{
logger.Error(e, $"Unable to access directory: '{directoryPath}'");
}
}
}


private IList<ResultDicomItem> CompareDicomTagAndValue(DicomDataset dataset, ref IList<ResultDicomItem> resultDicomItems)
private IEnumerable<ResultDicomItem> CompareDicomTagAndValue(in DicomDataset dataset, in SearchCriteria criteria)
{
IEnumerable<ResultDicomItem> result = new List<ResultDicomItem>();
foreach (DicomItem dicomItem in dataset)
{
// dig into sub sequence
if (dicomItem.ValueRepresentation == DicomVR.SQ)
{
foreach (DicomDataset innerDataset in ((DicomSequence)dicomItem).Items)
{
CompareDicomTagAndValue(innerDataset, ref resultDicomItems);
result = result.Concat(CompareDicomTagAndValue(innerDataset, criteria));
}
}
else
Expand Down Expand Up @@ -226,12 +195,8 @@ private IList<ResultDicomItem> CompareDicomTagAndValue(DicomDataset dataset, ref
if (string.IsNullOrWhiteSpace(criteria.SearchText) || CompareString(valueString, criteria))
{
//handle match
if (resultDicomItems == null)
{
resultDicomItems = new List<ResultDicomItem>();
}

resultDicomItems.Add(new ResultDicomItem(element.Tag, valueString, rawValue));
result.Append(new ResultDicomItem(element.Tag, valueString, rawValue));

//Console.WriteLine($"match value: {dicomItem.ToString()}, {valueString}");

Expand All @@ -255,7 +220,7 @@ private IList<ResultDicomItem> CompareDicomTagAndValue(DicomDataset dataset, ref

}
}
return resultDicomItems;
return result;
}

private bool CompareString(string refString, SearchCriteria criteria)
Expand All @@ -265,29 +230,10 @@ private bool CompareString(string refString, SearchCriteria criteria)
return false;
}

return CompareString(refString, criteria.SearchText, criteria.CaseSensitive, criteria.WholeWord);

}
return Util.CompareString(refString, criteria.SearchText, criteria.CaseSensitive, criteria.WholeWord);

private bool CompareString(string refString, string testString, bool caseSensitive, bool wholeWord)
{
if (wholeWord)
{
if (caseSensitive)
return refString.Equals(testString, StringComparison.InvariantCulture);
else
return refString.Equals(testString, StringComparison.InvariantCultureIgnoreCase);
}
else
{
if (caseSensitive)
return refString.CaseInsensitiveContains(testString, StringComparison.InvariantCulture);
else
return refString.CaseInsensitiveContains(testString, StringComparison.InvariantCultureIgnoreCase);
}
}


}

}
4 changes: 2 additions & 2 deletions DicomGrepCore/Models/ResultDicomItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ public class ResultDicomItem
{
public DicomTag Tag { get; private set; }
public string ValueString { get; private set; }
public byte[] Buffer { get; private set; }
public byte[] Raw { get; private set; }


public ResultDicomItem(DicomTag tag, string valueString, byte[] buffer)
{
this.Tag = tag;
this.ValueString = valueString;
this.Buffer = buffer;
this.Raw = buffer;
}
}
}
83 changes: 83 additions & 0 deletions DicomGrepCore/Utils/Util.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using DicomGrepCore.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DicomGrepCore.Utils
{
public static class Util
{
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

/// <summary>
///
/// </summary>
/// <param name="refString"></param>
/// <param name="testString"></param>
/// <param name="caseSensitive"></param>
/// <param name="wholeWord"></param>
/// <returns></returns>
public static bool CompareString(string refString, string testString, bool caseSensitive, bool wholeWord)
{
if (wholeWord)
{
if (caseSensitive)
return refString.Equals(testString, StringComparison.InvariantCulture);
else
return refString.Equals(testString, StringComparison.InvariantCultureIgnoreCase);
}
else
{
if (caseSensitive)
return refString.CaseInsensitiveContains(testString, StringComparison.InvariantCulture);
else
return refString.CaseInsensitiveContains(testString, StringComparison.InvariantCultureIgnoreCase);
}
}

/// <summary>
///
/// </summary>
/// <param name="directoryPath"></param>
/// <param name="pattern"></param>
/// <param name="depth"></param>
/// <param name="tokenSource"></param>
/// <returns></returns>
public static List<string> LookupDirectory(string directoryPath, string pattern, int depth, CancellationTokenSource tokenSource)
{
List<string> filenames = new List<string>();
try
{
if (tokenSource.IsCancellationRequested)
return filenames;
else
filenames.AddRange(Directory.GetFiles(directoryPath, pattern));
}
catch (Exception e)
{
logger.Error(e, $"Unable to list files in: '{directoryPath}'");
}

if (depth > 0)
{
try
{
foreach (string subdirectory in Directory.GetDirectories(directoryPath))
{
if (tokenSource.IsCancellationRequested)
return filenames;
else
filenames.AddRange(LookupDirectory(subdirectory, pattern, depth - 1, tokenSource));
}
}
catch (Exception e)
{
logger.Error(e, $"Unable to access directory: '{directoryPath}'");
}
}
return filenames;
}
}
}

0 comments on commit 90a1648

Please sign in to comment.