UNPKG

dicomweb-proxy

Version:

A proxy to translate between dicomweb and dimse

139 lines (121 loc) 3.96 kB
import { findScu, findScuOptions, Node as DicomNode } from 'dicom-dimse-native'; import { ConfParams, config } from '../utils/config'; import { LoggerSingleton } from '../utils/logger'; import { queryLevelToString, QUERY_LEVEL } from './querLevel'; import { get_element } from '@iwharris/dicom-data-dictionary'; import { tagsForLevel } from './tags'; const findDicomName = (name: string): string | undefined => { const dataElement = get_element(name); if (dataElement) { return dataElement.tag.replace('(', '').replace(',', '').replace(')', ''); } return undefined; }; const findVR = (name: string): string => { const dataElement = get_element(name); if (dataElement) { return dataElement.vr; } return ''; }; export interface IQueryParams { [key: string]: string; } export async function doFind(level: QUERY_LEVEL, query: IQueryParams): Promise<Record<string,string>[][]> { const peers = config.get(ConfParams.PEERS) as DicomNode[]; const promises: Array<Promise<Record<string,string>[]>> = []; peers.forEach((peer) => { promises.push(sendCFindRequest(level, peer, query)); }); return Promise.all(promises); } export async function sendCFindRequest(level: QUERY_LEVEL, target: DicomNode, query: IQueryParams): Promise<Record<string,string>[]> { const logger = LoggerSingleton.Instance; // add query retrieve level const options: findScuOptions = { tags: [ { key: '00080052', value: queryLevelToString(level), }, ], source: config.get(ConfParams.SOURCE), target, verbose: config.get(ConfParams.VERBOSE), }; // parse all include fields const includes = query.includefield; let tags = new Array<string>(); if (includes) { tags = includes.split(','); } const defaultTagsForLevel = tagsForLevel(level); tags.push(...defaultTagsForLevel); // add parsed tags tags.forEach((element: string) => { const tagName = findDicomName(element) || element; if (tagName) { options.tags.push({ key: tagName, value: '' }); } }); // add search param let invalidInput = false; const minCharsQido = config.get(ConfParams.MIN_CHARS) as number; Object.keys(query).forEach((propName) => { const tag = findDicomName(propName); const vr = findVR(propName); if (tag) { let v = query[propName]; // string vr types check if (['PN', 'LO', 'LT', 'SH', 'ST'].includes(vr)) { // just make sure to remove any wildcards from prefix and suffix v = v.replace(/^[*]/, ''); v = v.replace(/[*]$/, ''); // check if minimum number of chars are reached from input if (minCharsQido > v.length) { invalidInput = true; } // auto append wildcard if (config.get(ConfParams.APPEND_WILDCARD)) { v += '*'; } } options.tags.push({ key: tag, value: v }); } }); const offset = query.offset ? parseInt(query.offset, 10) : 0; // run find scu and return json response return new Promise((resolve) => { // return with empty results if invalid if (invalidInput) { resolve([]); } findScu(options, (result: string) => { if (result && result.length > 0) { try { const json = JSON.parse(result); if (json.code === 0) { const container = JSON.parse(json.container); if (container) { resolve(container.slice(offset)); } else { resolve([]); } } else if (json.code === 1) { logger.info('query is pending...'); } else { logger.error(`c-find failure: ${json.message}`); resolve([]); } } catch (error) { logger.error(error); logger.error(result); resolve([]); } } else { logger.error('invalid result received'); resolve([]); } }); }); }