This commit is contained in:
2025-02-26 14:49:25 +07:00
commit 1c1d9c4474
6403 changed files with 1953774 additions and 0 deletions

18
nv/html/dcmgw/LICENSE.md Normal file
View File

@@ -0,0 +1,18 @@
Copyright (C) 2013 Jose Antonio Perez
[ http://goo.gl/lW17d ]
dcmgw: DICOM c-find gateway
[ https://github.com/jap1968/dcmgw ]
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/gpl.html

15
nv/html/dcmgw/README.md Normal file
View File

@@ -0,0 +1,15 @@
dcmgw is a script acting as a gateway allowing to do c-find requests to a Dicom server.
The results are returned as XML contents. The xml folder contains the XSD specification
of the response messages as well as some XML samples.
dcmgw relies upon dcmqr, from the [dcm4che2 toolkit](http://www.dcm4che.org/confluence/display/d2/dcm4che2+DICOM+Toolkit).
Dicom servers are intended to be accessed just by Dicom clients. This is one important limitation in order to access
these servers from web applications.
Currently, things are changing and there are new proposals in order to extend the Dicom protocol by means of
RESTful web services.
In particular, QIDO-RS (Query based on ID for DICOM Objects by RESTful Services) will be included
in Dicom [supplement 166](http://www.dclunie.com/dicom-status/status.html). Meanwhile, applications like dcmgw provide similar functionality allowing
to access Dicom servers from web applications right now.

478
nv/html/dcmgw/dcmgw.php Normal file
View File

@@ -0,0 +1,478 @@
<?php
/*
Copyright (C) 2013 Jose Antonio Perez
[ http://goo.gl/lW17d ]
This file is part of dcmgw (Dicom gateway)
[ https://github.com/jap1968/dcmgw ]
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/gpl.html
*/
define('DCMGW_INCLUDE', './');
include_once(DCMGW_INCLUDE.'dcmgwPacs.php');
include_once(DCMGW_INCLUDE.'dcmgwConfig.php');
// *****************************************************************************
_dumpvar($_REQUEST);
// operation: cfind | dicomfields | wado | binarydata
$operation = isset($_GET['operation']) ? $_GET['operation'] : 'cfind';
if ($operation == 'cfind') {
if (isset($_GET['studyUID'])) {
$studyUID = $_GET['studyUID'];
dicomQRStudy($pacs, $studyUID);
}
else {
dicomQR($pacs);
}
}
else if ($operation == 'dicomfields') {
$studyUID = $_GET['studyUID'];
$seriesUID = $_GET['seriesUID'];
$objectUID = $_GET['objectUID'];
getDicomWadoFields($pacs, $studyUID, $seriesUID, $objectUID);
}
else if ($operation == 'binarydata') {
$studyUID = $_GET['studyUID'];
$seriesUID = $_GET['seriesUID'];
$objectUID = $_GET['objectUID'];
$len = $_GET['len'];
$src = $_GET['src'];
getBinaryData($pacs, $studyUID, $seriesUID, $objectUID, $len, $src);
}
else {
// define('TAM_MAX_THUMB', 120);
$studyUID = $_GET['studyUID'];
$seriesUID = $_GET['seriesUID'];
$objectUID = $_GET['objectUID'];
getWado($pacs, $studyUID, $seriesUID, $objectUID);
/*
$uriWado = $pacs->getUriWado($studyUID, $seriesUID, $objectUID);
// To get thumbnails:
if (isset($_GET['rows']) && isset($_GET['cols'])) {
$uriWado .= "&rows={$_GET['rows']}&cols={$_GET['cols']}";
}
// header("Cache-Control: public");
// header('Expires: '.gmdate('D, d M Y H:i:s', strtotime('+1 day')).' GMT');
header("Content-Type: image/jpeg");
readfile($uriWado);
*/
}
// *****************************************************************************
// *****************************************************************************
/**
* The Query/Retrieve answer is processed
* outputRes: Q/R answer string
*/
function processResponse($outputRes, $encoding) {
$pattern = "/^((?:[0|1][0-9]|2[0-3])(?::[0-5][0-9]){2},[0-9]{3})\s([A-Z]+)\s+-\s(.+)$/";
$dicom = array();
foreach ($outputRes as $numLine => $strLine) {
$matches = array();
$numMatches = preg_match($pattern, $strLine, $matches);
if ($numMatches == 1) {
// $matches[1]: time (hh:mm:ss,mil)
// $matches[2]: INFO|ERROR|???
$outputType = $matches[2];
// $matches[3]: info string
$outputStr = $matches[3];
if (DEBUG_LEVEL >= DEBUG_DUMP) {
// Mensajes de tipo INFO / ERROR
echo "<div style='color:red; margin:2em 0.5em;'>Patr&oacute;n reconocido (I)</div>";
echo "<pre>";
print_r($matches);
echo "</pre>";
}
// 20120120: ToDo: Dealing with errors. Inform the client about the error
if ($outputType == 'ERROR') {
echo "ERROR";
if (DEBUG_LEVEL >= DEBUG_INFO) {
echo ": $outputStr";
}
echo "<br>\n";
return false;
}
if ($element = identifyPattern($outputStr)) {
$lineNum = $numLine + 1;
_dumpvar($element);
$xmlString = '';
while(strlen($outputRes[$lineNum]) > 0) {
if (DEBUG_LEVEL >= DEBUG_INFO) {
echo $outputRes[$lineNum]."<br>\n";
}
if ($df = processDicomField($outputRes[$lineNum], $encoding)) {
_dumpvar($df);
$xmlString .= $df['xmlString']."\n";
}
$lineNum++;
}
$element['xmlString'] = $element['xmlPre'].$xmlString.$element['xmlPost'];
if (DEBUG_LEVEL >= DEBUG_DUMP) {
// print_r($dicomHeaders);
echo $element['xmlString'];
}
array_push($dicom, $element);
}
}
}
if (DEBUG_LEVEL >= DEBUG_INFO) {
echo "<pre>";
// print_r($result);
echo "</pre>";
}
elseif (DEBUG_LEVEL == DEBUG_NONE) {
header('Content-type: text/xml; charset='.XML_ENCODING);
echo "<?xml version=\"1.0\" encoding=\"".XML_ENCODING."\"?>\n";
$fechaAhora = strftime("%Y%m%d%H%M%S%z");
echo "<dicom datetime=\"$fechaAhora\">\n";
foreach ($dicom as $response) {
echo $response['xmlString'];
}
echo "</dicom>\n";
}
} // function processResponse(...)
// *****************************************************************************
function identifyPattern($testStr) {
$patterns = array();
$element = false;
if (SHOW_REQUEST)
{
// Send Query Request using 1.2.840.10008.5.1.4.1.2.2.1/Study Root Query/Retrieve Information Model - FIND:
$patterns[QUERY_REQUEST_ROOT] = "/^Send Query Request using ([0-9]+(?:\.[0-9]+)+)\/([[:alpha:][:space:]\/\-]+):$/";
// Send Query Request #1/3 using 1.2.840.10008.5.1.4.1.2.2.1/Study Root Query/Retrieve Information Model - FIND:
$patterns[QUERY_REQUEST] = "/^Send Query Request #([1-9][0-9]*)\/([1-9][0-9]*) using ([0-9]+(?:\.[0-9]+)+)\/([[:alpha:][:space:]\/\-]+):$/";
}
// Query Response #1:
$patterns[QUERY_RESPONSE_ROOT] = "/^Query Response #([1-9][0-9]*):$/";
// Query Response #1 for Query Request #1/3:
$patterns[QUERY_RESPONSE] = "/^Query Response #([1-9][0-9]*) for Query Request #([1-9][0-9]*)\/([1-9][0-9]*):$/";
$matches = array();
$numMatches = 0;
foreach ($patterns as $type => $pattern)
{
if (DEBUG_LEVEL >= DEBUG_INFO) {
echo "Testing $testStr<br>against pattern: $pattern<br>";
}
$numMatches = preg_match($pattern, $testStr, $matches);
if($numMatches == 1)
{
$element = array();
$element['xmlPre'] = "<!--{$matches[0]}-->\n";
$element['type'] = $type;
switch ($type) {
case QUERY_REQUEST_ROOT:
$element['tag'] = 'request';
$element['xmlPre'] .= "<{$element['tag']} qrim='{$matches[1]}'>\n";
break;
case QUERY_RESPONSE_ROOT:
$element['tag'] = 'response';
$element['xmlPre'] .= "<{$element['tag']} number='{$matches[1]}'>\n";
break;
case QUERY_REQUEST:
$element['tag'] = 'qrequest';
$element['xmlPre'] .= "<{$element['tag']} number='{$matches[1]}' qrim='{$matches[3]}'>\n";
break;
case QUERY_RESPONSE:
$element['tag'] = 'qresponse';
$element['xmlPre'] .= "<{$element['tag']} number='{$matches[1]}' qrequest='{$matches[2]}'>\n";
break;
default:
$element['tag'] = 'dummy';
$element['xmlPre'] .= "<{$element['tag']}>\n";
}
$element['xmlPost'] = "</{$element['tag']}>\n";
break; // break 2 ???
}
}
return $element;
}
// 20120112: Parameters are obtained directly from $_GET
// ToDo: Dealing with errors (returning error information) in the case of incorrect parameters
function dicomQR ($pacs)
{
// Nivel Q/R | | -P | -S | -I
$extraFields = '-r 00080061 -r 00081030 -r 00100010 -r 00100021 -r 00100030 -r 00100040 -r 00201206 -r 00201208';
// (0008,0061) Modalities in Study
// (0008,1030) Study Description
// (0010,0010) Patient's Name
// (0010,0021) Issuer of Patient ID
// (0010,0030) Patient's Birth Date
// (0010,0040) Patient's Sex
// (0020,1206) Number of Study Related Series
// (0020,1208) Number of Study Related Instances
// (0020,000D) Study IUID
// ToDo: Take also into account PatientIdIssuer
$qPatId = isset($_GET['patId']) ? " -q 00100020='" . $_GET['patId'] . "'" : "";
$qAccessionNo = isset($_GET['AccessionNo']) ? " -q 00080050='" . $_GET['AccessionNo'] . "'" : "";
$qStudyDate = isset($_GET['studyDate']) ? " -q StudyDate={$_GET['studyDate']}" : ""; // AAAAMMDD ???
$qFilter = $qPatId . $qAccessionNo . $qStudyDate . " ";
// $command = 'LANG='.$pacs->getLocale().' '.PATH_BASE_DCM4CHE2.'dcmqr -device '.AETITLE_GATEWAY.' '.$pacs->getDicomServer()." -q 00100020='$patientId' $extraFields";
if (strlen($qFilter) > 1) {
$command = 'JAVA_HOME=/usr/lib/jvm/jdk1.7.0_80 LANG='.$pacs->getLocale().' '.PATH_BASE_DCM4CHE2.'dcmqr -device '.AETITLE_GATEWAY.' '.$pacs->getDicomServer() . $qFilter . $extraFields;
// echo $command;
$outputRes = array();
exec($command, $outputRes);
if (DEBUG_LEVEL >= DEBUG_DUMP) {
echo "<pre>";
print_r($outputRes);
echo "</pre>";
}
processResponse($outputRes, $pacs->encoding);
}
/*
Example of a Q/R answer (at study level)
14:28:31,609 INFO - Query Response #4:
(0008,0005) CS #10 [ISO_IR 100] Specific Character Set
(0008,0020) DA #8 [20080410] Study Date
(0008,0030) TM #14 [103025.000000] Study Time
(0008,0050) SH #0 [] Accession Number
(0008,0052) CS #6 [STUDY] Query/Retrieve Level
(0008,0054) AE #8 [PACSECO] Retrieve AE Title
(0008,0056) CS #6 [ONLINE] Instance Availability
(0010,0020) LO #6 [72471] Patient ID
(0020,000D) UI #62 [1.2.840.113543.6.6.3.4.617968937028517893191307041671843345256] Study Instance U
(0020,0010) SH #4 [3379] Study ID
(0020,1206) IS #2 [1] Number of Study Related Series
(0020,1208) IS #2 [2] Number of Study Related Instances
(0088,0130) SH #0 [] Storage Media File-set ID
(0088,0140) UI #0 [] Storage Media File-set UID
*/
}
// *****************************************************************************
/**
* Performa a QR operation to get series and instances from a given study
*/
function dicomQRStudy ($pacs, $study_IUID)
{
// Nivel Q/R | | -P | -S | -I
// Problema: Algun campo extra lo pide en la subquery de instancias, pero no en la query principal de series
$extraFields = '-r 00080060 -r 0008103E -r 00200011 -r 00201209';
// (0008,0060) Modality
// (0008,103E) Series Description // Solo se envia en las subquery
// (0020,0011) Series Number
// (0020,1209) Number of Series Related Instances // Solo se envia en las subquery
$command = 'JAVA_HOME=/usr/lib/jvm/jdk1.7.0_80 LANG='.$pacs->getLocale().' '.PATH_BASE_DCM4CHE2.'dcmqr -device '.AETITLE_GATEWAY.' -I '.$pacs->getDicomServer()." -q 0020000D=$study_IUID $extraFields";
_debuglog($command);
$outputRes = array();
exec($command, $outputRes);
if (DEBUG_LEVEL >= DEBUG_DUMP) {
echo "<pre>";
print_r($outputRes);
echo "</pre>";
}
processResponse($outputRes, $pacs->encoding);
}
function processDicomField($dcmString, $encoding) {
/*
// (0008,0020) DA #8 [20080410] Study Date
// Returned values (string):
tagGroup = 0008
tagElement = 0020
value = 20080410
tagName = Study Date
valueRepr = DA
valueLength = 8 (int)
*/
if (DEBUG_LEVEL >= DEBUG_INFO) {
echo "processDicomField($dcmString)<br>";
}
$matches = array();
$pattern = "/^\(([0-9A-F]{4}),([0-9A-F]{4})\)\s([A-Z]{2})\s#([0-9]+)\s\[([^\]]*)\]\s(.*)$/";
$numMatches = preg_match($pattern, $dcmString, $matches);
if($numMatches == 1) {
$d = array();
if (DEBUG_LEVEL >= DEBUG_DUMP) {
echo "<pre>";
print_r($matches);
echo "</pre>";
}
$d['tagGroup'] = $matches[1];
$d['tagElement'] = $matches[2];
$d['valueRepr'] = $matches[3];
$d['valueLength'] = $matches[4];
$d['value'] = $matches[5];
$d['tagName'] = $matches[6];
// Characters to convert to UTF-8: Elements with VR=PN, SH, LO, ST, LT, UT in the Data Set.
$vr = $d['valueRepr'];
if ($vr == 'PN' || $vr == 'SH' || $vr == 'LO' || $vr == 'ST' || $vr == 'LT' || $vr == 'UT') {
$d['value'] = iconv($encoding, XML_ENCODING, $d['value']);
$d['value'] = htmlspecialchars($d['value'], ENT_QUOTES); // Convert non valid XML characters
}
$xmlString = "<!--{$d['tagName']}-->\n";
$xmlString .= "<attr tag=\"{$d['tagGroup']}{$d['tagElement']}\" vr=\"{$d['valueRepr']}\" len=\"{$d['valueLength']}\">";
$xmlString .= "{$d['value']}</attr>";
$d['xmlString'] = $xmlString;
}
else {
if (DEBUG_LEVEL >= DEBUG_DUMP) {
echo "NO match!!!<br>";
}
$d = false;
}
return $d;
}
// *****************************************************************************
/**
* Recovers a Dicom object via WADO
*/
function getWado($pacs, $studyUID, $seriesUID, $objectUID) {
// $tStart = microtime(true);
$uriWado = $pacs->getUriWado($studyUID, $seriesUID, $objectUID);
if (isset($_GET['contentType']) && $_GET['contentType'] == 'application/dicom') {
$header = "Content-Type: application/dicom";
$uriWado .= "&contentType=application%2Fdicom";
// 20130502: Force transfer syntax to Explicit VR little endian
$uriWado .= "&transferSyntax=1.2.840.10008.1.2.1";
}
else {
error_log("ERROR jpeg/WADO files should not be used anymore");
$header = "Content-Type: image/jpeg";
}
// To get thumbnails:
if (isset($_GET['rows']) && isset($_GET['cols']))
{
// $uriWado .= "&rows={$_GET['rows']}&cols={$_GET['cols']}";
$uriWado .= "&rows=".THUMBNAIL_SIZE."&cols=".THUMBNAIL_SIZE;
}
if (RETRIEVE_LOCAL) {
// Store a local copy of the Dicom file to obtain its size.
$tmpFWado = tempnam('/tmp', 'dicom_');
// $tmpFWado = tempnam('/dev/shm/dicom', 'dicom_');
if ($getOk = getLocalWado($uriWado, $tmpFWado))
{
$fp = fopen($tmpFWado, 'rb');
header("Content-Type: application/dicom");
header("Content-Length: " . filesize($tmpFWado));
header("Content-Disposition: inline");
fpassthru($fp);
fclose($fp);
}
else
{
error_log("Error retrieving WADO/Dicom object");
}
unlink($tmpFWado);
}
else
{
// header("Cache-Control: public");
// header('Expires: '.gmdate('D, d M Y H:i:s', strtotime('+1 day')).' GMT');
header($header);
readfile($uriWado);
}
/*
$tEnd = microtime(true);
$tDelta = round(1000 * ($tEnd - $tStart));
$logMsg = "getWado: $tDelta ms";
error_log($logMsg);
*/
}
// ******* ********* ********* ********* ********* ********* ********* *********
function getLocalWado($uriWado, $tmpFWado) {
$getOk = false;
$numTry = 0;
$maxTry = 3;
$delayTry = 1;
while (!$getOk && $numTry < $maxTry)
{
if ($numTry > 0)
{
sleep($delayTry);
}
$retrieveCommand = PATH_WGET." '$uriWado' -O $tmpFWado --server-response 2> /dev/stdout | grep Content-Type | awk -F\"Content-Type: \" '{print $2}'";
// error_log($retrieveCommand);
$outputCommand = array();
exec($retrieveCommand, $outputCommand);
// Verification: The returned contents is a dicom object
$getOk = $outputCommand[0] == 'application/dicom';
$numTry++;
}
return $getOk;
}
// ******* ********* ********* ********* ********* ********* ********* *********
function _debuglog($cmd) {
error_log("$cmd\n",3,"/var/www/html/dcmgw/tmp/debuglog");
}
function _dumpvar($var) {
ob_start();
print_r($var);
_debuglog(ob_get_contents());
ob_end_clean();
}

View File

@@ -0,0 +1,98 @@
<?php
ini_set("log_errors",1);
ini_set("error_log","/var/www/html/dcmgw/php_error.log");
/*
Copyright (C) 2013 Jose Antonio Perez
[ http://goo.gl/lW17d ]
This file is part of dcmgw (Dicom gateway)
[ https://github.com/jap1968/dcmgw ]
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/gpl.html
*/
// ******* ********* ********* ********* ********* ********* ********* *********
/**
* Avoids direct execution of the script
*/
if (!defined('DCMGW_INCLUDE')) {
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
die;
}
// ******* ********* ********* ********* ********* ********* ********* *********
// Configuration: Change values to fit your environment
// ******* ********* ********* ********* ********* ********* ********* *********
// You should end up having a variable $pacs pointing to your PACS server.
// You can find below some configuration samples for public servers
// Please, for testing purposes use your own server (if possible) to avoid overloading the public servers
// http://www.dicomserver.co.uk/
// http://wado.medicalconnections.co.uk/WADO/WADO.asp
//$pacsMedicalConnections = new PACS('ABPACS', '127.0.0.1', '11112');
//$pacsMedicalConnections->setWado('http', '127.0.0.1', '80', 'wado/wadp.asp');
// DC's public PixelMed PACS.
// No WADO?
//$pacsPixelMed = new PACS('ABPACS', '127.0.0.1', '11112');
// Public JVSdicom Server. Not sure if this one has any contents.
// No WADO ?
// More information: http://153.1.200.58/?q=dicom_images
//$pacsJVSdicom = new PACS('JVSDICOM', '153.1.200.58', '104');
// My own PACS
$pacsHome = new DCM4CHEE('ABPACS', '128.199.154.150');
$pacs = $pacsHome;
// ******* ********* ********* ********* ********* ********* ********* *********
// This script makes use of dcmqr, from the dcm4che2 Dicom toolkit
// dcm4che2 Dicom toolkit: http://www.dcm4che.org/confluence/display/d2/dcm4che2+DICOM+Toolkit
// dcmqr: http://www.dcm4che.org/confluence/display/d2/dcmqr
//define ('PATH_BASE_DCM4CHE2', '/usr/local/dcm4che/dcm4che2/bin/');
define ('PATH_BASE_DCM4CHE2', '/var/www/dcm4che/dcm4che2/bin/');
define ('PATH_BASE_DICOM_CACHE', '/tmp/dicom/');
define ('PATH_WGET', '/usr/bin/wget');
define ('RETRIEVE_LOCAL', true);
define('SHOW_REQUEST', false);
define('XML_ENCODING', 'UTF-8');
define ('DEBUG_NONE', 0);
define ('DEBUG_INFO', 5);
define ('DEBUG_DUMP', 9);
define ('DEBUG_LEVEL', DEBUG_NONE);
define ('AETITLE_GATEWAY', 'DCMGW');
define ('THUMBNAIL_SIZE', '200');
// ******* ********* ********* ********* ********* ********* ********* *********
define('QUERY_REQUEST_ROOT', '0');
define('QUERY_RESPONSE_ROOT', '1');
define('QUERY_REQUEST', '2');
define('QUERY_RESPONSE', '3');
// ******* ********* ********* ********* ********* ********* ********* *********

133
nv/html/dcmgw/dcmgwPacs.php Normal file
View File

@@ -0,0 +1,133 @@
<?php
/*
Copyright (C) 2013 Jose Antonio Perez
[ http://goo.gl/lW17d ]
This file is part of dcmgw (Dicom gateway)
[ https://github.com/jap1968/dcmgw ]
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/gpl.html
*/
// ******* ********* ********* ********* ********* ********* ********* *********
/**
* Avoids direct execution of the script
*/
if (!defined('DCMGW_INCLUDE')) {
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
die;
}
// ******* ********* ********* ********* ********* ********* ********* *********
// Configuration: Generic Dicom Storage SCP
// ******* ********* ********* ********* ********* ********* ********* *********
class PACS
{
// DICOM setup
public $AETitle;
public $host;
public $port;
// WADO setup
public $wadoProtocol;
public $wadoHost;
public $wadoPort;
public $wadoScript;
public $lang = 'en_US'; // No need to change
public $encoding = 'iso-8859-1'; // May need to change to UTF-8
function __construct($AETitle, $host, $port) {
$this->AETitle = $AETitle;
$this->host = $host;
$this->port = $port;
$this->wadoProtocol = 'http';
$this->wadoHost = $host;
$this->wadoPort = $port;
}
public function getDicomServer() {
$dicomServer = $this->AETitle.'@'.$this->host.':'.$this->port;
return $dicomServer;
}
/**
* Force Dicom Q/R execution under a given locale to deal properly with non-ascii characters
*/
public function getLocale() {
return $this->lang.'.'.$this->encoding;
}
/**
* In some environments Wado server runs independently of Dicom server
*/
public function setWado($wadoProtocol, $wadoHost, $wadoPort, $wadoScript) {
$this->wadoProtocol = $wadoProtocol;
$this->wadoHost = $wadoHost;
$this->wadoPort = $wadoPort;
$this->wadoScript = $wadoScript;
}
public function setWadoScript($wadoScript) {
$this->wadoScript = $wadoScript;
}
public function getUriWado($studyUID, $seriesUID, $objectUID) {
// Additional parameters ???
// contentType
// transferSyntax (UID)
$codeBase = "{$this->wadoProtocol}://{$this->wadoHost}:{$this->wadoPort}/{$this->wadoScript}?";
$queryString = "requestType=WADO&studyUID={$studyUID}&seriesUID={$seriesUID}&objectUID={$objectUID}";
$uriWado = $codeBase.$queryString;
return $uriWado;
}
}
// ******* ********* ********* ********* ********* ********* ********* *********
// Specific subclasses for some popular Dicom servers
class DCM4CHEE extends PACS {
function __construct($AETitle, $host) {
$port = '11112';
parent::__construct($AETitle, $host, $port);
$this->wadoPort = '8080';
$this->setWadoScript('wado');
}
}
class CONQUEST extends PACS {
function __construct($AETitle, $host, $port) {
parent::__construct($AETitle, $host, $port);
$this->setWadoScript('cgi-bin/dgate.exe');
}
}
class CLEARCANVAS extends PACS {
function __construct($AETitle, $host, $port) {
parent::__construct($AETitle, $host, $port);
$this->wadoPort = '1000';
$this->setWadoScript('wado/'.$AETitle);
}
}
// ******* ********* ********* ********* ********* ********* ********* *********

3
nv/html/dcmgw/info.php Normal file
View File

@@ -0,0 +1,3 @@
<?php
phpinfo();

18979
nv/html/dcmgw/php_error.log Normal file

File diff suppressed because it is too large Load Diff

32
nv/html/dcmgw/tmp/DEADJOE Normal file
View File

@@ -0,0 +1,32 @@
*** These modified files were found in JOE when it aborted on Thu Apr 12 07:54:04 2018
*** JOE was aborted because the terminal closed
*** File '(Unnamed)'
while
for
debug
dumpvar
port
8080
8080
mysql
mysql
mysql
*** File '(Unnamed)'
/tmp/ck.log
mcserver
docs/README.txt
mcservice
mcservice.vmoptions
conf/mirth.properties
conf/mirth.properties
conf/dbdrivers.xml
mcservice
mcservice
debuglog
*** File '* Startup Log *'
Processing '/etc/joe/joerc'...
Finished processing /etc/joe/joerc

133137
nv/html/dcmgw/tmp/debuglog Normal file

File diff suppressed because it is too large Load Diff

41513
nv/html/dcmgw/tmp/olddebuglog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<dicom datetime="20130526224447+0200">
<!--Query Response #1:-->
<response number='1'>
<!--Specific Character Set-->
<attr tag="00080005" vr="CS" len="0"></attr>
<!--Study Date-->
<attr tag="00080020" vr="DA" len="8">19991223</attr>
<!--Study Time-->
<attr tag="00080030" vr="TM" len="6">100545</attr>
<!--Accession Number-->
<attr tag="00080050" vr="SH" len="4">0001</attr>
<!--Query/Retrieve Level-->
<attr tag="00080052" vr="CS" len="6">STUDY</attr>
<!--Retrieve AE Title-->
<attr tag="00080054" vr="AE" len="4">TEST</attr>
<!--Modalities in Study-->
<attr tag="00080061" vr="CS" len="4">ECG</attr>
<!--Study Description-->
<attr tag="00081030" vr="LO" len="0"></attr>
<!--Patient?s Name-->
<attr tag="00100010" vr="PN" len="12">Patient^Test</attr>
<!--Patient ID-->
<attr tag="00100020" vr="LO" len="8">123-654</attr>
<!--Patient?s Birth Date-->
<attr tag="00100030" vr="DA" len="8">19440102</attr>
<!--Patient?s Sex-->
<attr tag="00100040" vr="CS" len="2">M</attr>
<!--Study Instance UID-->
<attr tag="0020000D" vr="UI" len="22">1.3.6.1.4.1.6018.4.999</attr>
<!--Study ID-->
<attr tag="00200010" vr="SH" len="6">43288</attr>
<!--Number of Study Related Series-->
<attr tag="00201206" vr="IS" len="2">1</attr>
<!--Number of Study Related Instances-->
<attr tag="00201208" vr="IS" len="2">1</attr>
</response>
<!--Query Response #2:-->
<response number='2'>
<!--Specific Character Set-->
<attr tag="00080005" vr="CS" len="0"></attr>
<!--Study Date-->
<attr tag="00080020" vr="DA" len="8">19940323</attr>
<!--Study Time-->
<attr tag="00080030" vr="TM" len="6">115104</attr>
<!--Accession Number-->
<attr tag="00080050" vr="SH" len="0"></attr>
<!--Query/Retrieve Level-->
<attr tag="00080052" vr="CS" len="6">STUDY</attr>
<!--Retrieve AE Title-->
<attr tag="00080054" vr="AE" len="4">TEST</attr>
<!--Modalities in Study-->
<attr tag="00080061" vr="CS" len="2">US</attr>
<!--Study Description-->
<attr tag="00081030" vr="LO" len="14">Echocardiogram</attr>
<!--Patient?s Name-->
<attr tag="00100010" vr="PN" len="10">Rubo DEMO</attr>
<!--Patient ID-->
<attr tag="00100020" vr="LO" len="12">123-45-6789</attr>
<!--Patient?s Birth Date-->
<attr tag="00100030" vr="DA" len="8">19231016</attr>
<!--Patient?s Sex-->
<attr tag="00100040" vr="CS" len="2">F</attr>
<!--Study Instance UID-->
<attr tag="0020000D" vr="UI" len="16">999.999.3859744</attr>
<!--Study ID-->
<attr tag="00200010" vr="SH" len="10">027893462</attr>
<!--Number of Study Related Series-->
<attr tag="00201206" vr="IS" len="2">1</attr>
<!--Number of Study Related Instances-->
<attr tag="00201208" vr="IS" len="2">1</attr>
</response>
</dicom>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0"?>
<!-- Generated using Flame-Ware Solutions XML-2-XSD v2.0 at http://www.flame-ware.com/Products/XML-2-XSD/ -->
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="dicom">
<xs:complexType>
<xs:sequence>
<xs:element name="response" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="attr" nillable="true" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent msdata:ColumnName="attr_Text" msdata:Ordinal="3">
<xs:extension base="xs:string">
<xs:attribute name="tag" type="xs:string" />
<xs:attribute name="vr" type="xs:string" />
<xs:attribute name="len" type="xs:string" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="number" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="datetime" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="dicom" />
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<dicom datetime="20130526224718+0200">
<!--Query Response #1:-->
<response number='1'>
<!--Specific Character Set-->
<attr tag="00080005" vr="CS" len="0"></attr>
<!--Query/Retrieve Level-->
<attr tag="00080052" vr="CS" len="6">SERIES</attr>
<!--Retrieve AE Title-->
<attr tag="00080054" vr="AE" len="4">TEST</attr>
<!--Modality-->
<attr tag="00080060" vr="CS" len="2">US</attr>
<!--Study Instance UID-->
<attr tag="0020000D" vr="UI" len="16">999.999.3859744</attr>
<!--Series Instance UID-->
<attr tag="0020000E" vr="UI" len="16">999.999.94827453</attr>
<!--Series Number-->
<attr tag="00200011" vr="IS" len="4">5829</attr>
</response>
<!--Query Response #1 for Query Request #1/1:-->
<qresponse number='1' qrequest='1'>
<!--SOP Class UID-->
<attr tag="00080016" vr="UI" len="28">1.2.840.10008.5.1.4.1.1.3.1</attr>
<!--SOP Instance UID-->
<attr tag="00080018" vr="UI" len="30">999.999.133.1996.1.1800.1.6.29</attr>
<!--Query/Retrieve Level-->
<attr tag="00080052" vr="CS" len="6">IMAGE</attr>
<!--Retrieve AE Title-->
<attr tag="00080054" vr="AE" len="4">TEST</attr>
<!--Series Instance UID-->
<attr tag="0020000E" vr="UI" len="16">999.999.94827453</attr>
<!--Instance Number-->
<attr tag="00200013" vr="IS" len="2">28</attr>
</qresponse>
</dicom>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0"?>
<!-- Generated using Flame-Ware Solutions XML-2-XSD v2.0 at http://www.flame-ware.com/Products/XML-2-XSD/ -->
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="attr" nillable="true">
<xs:complexType>
<xs:simpleContent msdata:ColumnName="attr_Text" msdata:Ordinal="3">
<xs:extension base="xs:string">
<xs:attribute name="tag" type="xs:string" />
<xs:attribute name="vr" type="xs:string" />
<xs:attribute name="len" type="xs:string" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="dicom">
<xs:complexType>
<xs:sequence>
<xs:element name="response" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element ref="attr" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="number" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="qresponse" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element ref="attr" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="number" type="xs:string" />
<xs:attribute name="qrequest" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="datetime" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="attr" />
<xs:element ref="dicom" />
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>