Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OHI-1357] feat(static-wado): add support for case-insensitive searching #4603

Merged
merged 16 commits into from
Jan 27, 2025
2 changes: 2 additions & 0 deletions extensions/default/src/DicomWebDataSource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ function createDicomWebApi(dicomWebConfig: DicomWebConfig, servicesManager) {
singlepart: dicomWebConfig.singlepart,
headers: userAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
supportsFuzzyMatching: dicomWebConfig.supportsFuzzyMatching,
};

wadoConfig = {
Expand All @@ -159,6 +160,7 @@ function createDicomWebApi(dicomWebConfig: DicomWebConfig, servicesManager) {
singlepart: dicomWebConfig.singlepart,
headers: userAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
supportsFuzzyMatching: dicomWebConfig.supportsFuzzyMatching,
};

// TODO -> Two clients sucks, but its better than 1000.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,18 +156,40 @@ export default class StaticWadoClient extends api.DICOMwebClient {
*
* @param {*} desired
* @param {*} actual
* @param {*} options - fuzzyMatching: if true, then do a sub-string match
* @returns true if the values match
*/
compareValues(desired, actual) {
compareValues(desired, actual, options) {
const { fuzzyMatching } = options;

if (Array.isArray(desired)) {
return desired.find(item => this.compareValues(item, actual));
return desired.find(item => this.compareValues(item, actual, options));
}
if (Array.isArray(actual)) {
return actual.find(actualItem => this.compareValues(desired, actualItem));
return actual.find(actualItem => this.compareValues(desired, actualItem, options));
}
if (actual?.Alphabetic) {
actual = actual.Alphabetic;
}

if (fuzzyMatching && typeof actual === 'string' && typeof desired === 'string') {
const normalizeValue = str => {
IbrahimCSAE marked this conversation as resolved.
Show resolved Hide resolved
return str.toLowerCase();
};

const normalizedDesired = normalizeValue(desired);
const normalizedActual = normalizeValue(actual);

const tokenizeAndNormalize = str => str.split(/[\s^]+/).filter(Boolean);

const desiredTokens = tokenizeAndNormalize(normalizedDesired);
const actualTokens = tokenizeAndNormalize(normalizedActual);

return desiredTokens.every(desiredToken =>
actualTokens.some(actualToken => actualToken.startsWith(desiredToken))
);
}

if (typeof actual == 'string') {
if (actual.length === 0) {
return true;
Expand All @@ -194,7 +216,7 @@ export default class StaticWadoClient extends api.DICOMwebClient {
}
const dash = range.indexOf('-');
if (dash === -1) {
return this.compareValues(range, value);
return this.compareValues(range, value, {});
}
const start = range.substring(0, dash);
const end = range.substring(dash + 1);
Expand All @@ -211,6 +233,14 @@ export default class StaticWadoClient extends api.DICOMwebClient {
* @returns
*/
filterItem(key: string, queryParams, study, sourceFilterMap) {
const isName = (key: string) => key.indexOf('name') !== -1;

const { supportsFuzzyMatching = false } = this.config;

const options = {
fuzzyMatching: isName(key) && supportsFuzzyMatching,
};

const altKey = sourceFilterMap[key] || key;
if (!queryParams) {
return true;
Expand All @@ -227,7 +257,8 @@ export default class StaticWadoClient extends api.DICOMwebClient {
return this.compareDateRange(testValue, valueElem.Value[0]);
}
const value = valueElem.Value;
IbrahimCSAE marked this conversation as resolved.
Show resolved Hide resolved
return this.compareValues(testValue, value);

return this.compareValues(testValue, value, options);
}

/** Converts the query parameters to lower case query parameters */
Expand Down
4 changes: 2 additions & 2 deletions platform/app/public/config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ window.config = {
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
enableStudyLazyLoad: true,
supportsFuzzyMatching: false,
supportsWildcard: true,
supportsFuzzyMatching: true,
IbrahimCSAE marked this conversation as resolved.
Show resolved Hide resolved
supportsWildcard: false,
staticWado: true,
singlepart: 'bulkdata,video',
// whether the data source should use retrieveBulkData to grab metadata,
Expand Down
2 changes: 2 additions & 0 deletions platform/docs/docs/user-guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Below the study list are pagination options for 25, 50, or 100 studies per page.

![user-study-next](../assets/img/user-study-next.png)

For static wado servers, you can enable fuzzy matching by setting the `supportsFuzzyMatching` property to true, after enabling it, fuzzy matching will be peformed on the patient name field, for example, if PatientName is "John^Doe", then "jo", "Do" and "John Doe" will all match. However "ohn" will not match.

## Study Summary

Click on a study to expand the study summary panel.
Expand Down
Loading