Conquest and html5+js DICOM viewer (DWV), dwv025 below

  • Hm,


    you are probably hitting a known and unsolved bug concerning the low level socket communication (code socket.cxx unchanged since first release) that first and so far only appeared on ubuntu 12.04. Basically the first 64k of data comes through (explaining the correct thumbnails) and the rest becomes zeros. People got around this by cross-compiling on ubuntu10 and then things work.


    Marcel

  • Hi,


    you seems to be right, the bug is somewhere deeper in communication layer code. By the way I am testing in under Debian Wheezy. We have another ConQuest installation under Debian Squeeze, and there it works without any problems. I tried to use dgate executable from Squeeze in Wheezy, but the problem remained.


    However for now I got it running with the following steps. I found similar problem discussion on the forum (the guy was moving ConQuest server from windows to linux). Changing DEFAULT_BRAKE_SIZE macro defined constant in buffer.cxx from value 32600 to 8192. Fix my display images viewer issues. I only hope that it did not produce some errors. Anyway it will be nice to know what is going on there.


    Tomas

  • Hi,


    I have done some visual improvements (now it displays correctly in chromium) in dwv.lua script:

    HTML
    ---- DICOM Web Viewer (DWV) lua script for integration in a Conquest PACS server. ---- Usage-- In the dicom.ini of your web server, create the dwv viewer:-- >> [dwv]-- >> source = viewers\dwv.lua-- And set it as the default viewer:-- >> [webdefaults]-- >> ...-- >> viewer = dwv-- This script relies on the 'kFactorFile', 'ACRNemaMap' and 'Dictionary' -- variables being set correctly.-- Then copy the 'css', 'src' and 'ext' folders of DWV in a 'dwv' folder-- in the web folder of your web server.-- Get idslocal patientid = string.gsub(series2, ':.*$', '')local seriesuid = string.gsub(series2, '^.*:', '')--local patientid = CGI('patientidmatch');--local seriesuid = string.gsub(CGI('seriesUID'), '^.*:', '');-- Functions declarationfunction getstudyuid() local a, b, s s = servercommand('get_param:MyACRNema') b = newdicomobject() b.PatientID = patientid b.SeriesInstanceUID = seriesuid b.StudyInstanceUID = '' a = dicomquery(s, 'SERIES', b) return a[0].StudyInstanceUIDendfunction queryimages() local images, imaget, b, s s = servercommand('get_param:MyACRNema') b = newdicomobject() b.PatientID = patientid b.SeriesInstanceUID = seriesuid b.SOPInstanceUID = '' images = dicomquery(s, 'IMAGE', b) imaget={} for k=0,#images-1 do imaget[k+1]={} imaget[k+1].SOPInstanceUID = images[k].SOPInstanceUID end table.sort(imaget, function(a,b) return a.SOPInstanceUID < b.SOPInstanceUID end) return imagetend-- Mainlocal studyuid = getstudyuid()local images = queryimages()local url = webscriptadressurl = url .. '?requestType=WADO&contentType=application/dicom'url = url .. '&seriesUID=' .. seriesuidurl = url .. '&studyUID=' .. studyuidurl = url .. '&objectUID=' .. images[1].SOPInstanceUID-- Generate htmlHTML('Content-type: text/html\n\n')--print([[<!DOCTYPE html>]])print([[<html>]])print([[<head>]])print([[<title>DICOM Web Viewer</title><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><link rel="stylesheet" href="/dwv/css/style.css"><style>body { font-size: 80%; }#toolbox li:first-child { list-style-type: none; padding-bottom: 10px; margin-left: -20px; }</style><link rel="stylesheet" href="/dwv/ext/jquery/ui/1.10.1/themes/ui-darkness/jquery-ui.min.css">]])print([[<!-- Third party --> <script type="text/javascript" src="/dwv/ext/jquery/jquery-1.9.1.min.js"></script><script type="text/javascript" src="/dwv/ext/jquery/ui/1.10.1/jquery-ui.min.js"></script><script type="text/javascript" src="/dwv/ext/flot/jquery.flot.min.js"></script>]])print([[<!-- Local --><script type="text/javascript" src="/dwv/src/dwv.js"></script><script type="text/javascript" src="/dwv/src/application.js"></script><script type="text/javascript" src="/dwv/src/dicom/dicomParser.js"></script><script type="text/javascript" src="/dwv/src/dicom/dictionary.js"></script><script type="text/javascript" src="/dwv/src/html/gui.js"></script><script type="text/javascript" src="/dwv/src/html/gui_ui.js"></script><script type="text/javascript" src="/dwv/src/html/html.js"></script><script type="text/javascript" src="/dwv/src/html/style.js"></script><script type="text/javascript" src="/dwv/src/html/layer.js"></script><script type="text/javascript" src="/dwv/src/image/filter.js"></script><script type="text/javascript" src="/dwv/src/image/image.js"></script><script type="text/javascript" src="/dwv/src/image/luts.js"></script><script type="text/javascript" src="/dwv/src/image/reader.js"></script><script type="text/javascript" src="/dwv/src/math/shapes.js"></script><script type="text/javascript" src="/dwv/src/math/bucketQueue.js"></script><script type="text/javascript" src="/dwv/src/math/scissors.js"></script><script type="text/javascript" src="/dwv/src/utils/string.js"></script>]])print([[<!-- Tools: beware order is important... --><script type="text/javascript" src="/dwv/src/tools/toolbox.js"></script><script type="text/javascript" src="/dwv/src/tools/windowLevel.js"></script><script type="text/javascript" src="/dwv/src/tools/draw.js"></script><script type="text/javascript" src="/dwv/src/tools/line.js"></script><script type="text/javascript" src="/dwv/src/tools/rectangle.js"></script><script type="text/javascript" src="/dwv/src/tools/roi.js"></script><script type="text/javascript" src="/dwv/src/tools/circle.js"></script><script type="text/javascript" src="/dwv/src/tools/livewire.js"></script><script type="text/javascript" src="/dwv/src/tools/zoom.js"></script><script type="text/javascript" src="/dwv/src/tools/filter.js"></script><script type="text/javascript" src="/dwv/src/tools/undo.js"></script>]])print([[<script type="text/javascript">function toggle(dialogName){ if( $(dialogName).dialog('isOpen') ) { $(dialogName).dialog('close'); } else { $(dialogName).dialog('open'); }}function load(){ app.loadURL(']]..webscriptadress..[[?requestType=WADO&contentType=application/dicom'+ '&studyUID=]]..studyuid..[[' + '&seriesUID=]]..seriesuid..[[' + '&objectUID=' + document.forms[0].slice.value);}function nextslice(){ if (document.forms[0].slice.selectedIndex == document.forms[0].slice.length-1) { document.forms[0].slice.selectedIndex = 0; } else { document.forms[0].slice.selectedIndex = document.forms[0].slice.selectedIndex + 1; } load();}function previousslice(){ if (document.forms[0].slice.selectedIndex == 0) { document.forms[0].slice.selectedIndex = document.forms[0].slice.length-1; } else { document.forms[0].slice.selectedIndex = document.forms[0].slice.selectedIndex - 1; } load();}]])print([[// main applicationvar app = new dwv.App();// jquery$(document).ready(function(){ // create buttons and dialogs $("button").button(); $("#openData").dialog({ position: {my: "left top", at: "left top", of: "#pageMain"} }); $("#toolbox").dialog({ position: {my: "left top+200", at: "left top", of: "#pageMain"} }); $("#history").dialog({ position: {my: "left top+370", at: "left top", of: "#pageMain"}, autoOpen: false }); $("#tags").dialog({ position: {my: "right top", at: "right top", of: "#pageMain"}, autoOpen: false, width: 500, height: 590 }); $("#layerContainer").dialog({ position: {my: "center top", at: "center top", of: "#pageMain"}, width: 570, height: 590 }); // initialise the application app.init(); // possible load from URL app.loadURL("]].. url ..[[");});</script>]])print([[</head>]])print([[<body style="cursor: auto;">]])print([[<div id="pageHeader>"]])print([[<!-- Title --><h1>DICOM Web Viewer (<a href="https://github.com/ivmartel/dwv">dwv</a> v0.3b)</h1><!-- Buttons --><button onclick="toggle('#openData')" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false">File</button><button onclick="toggle('#toolbox')" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false">Toolbox</button><button onclick="toggle('#history')">History</button><button onclick="toggle('#tags')" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false">Tags</button><button onclick="toggle('#layerContainer')" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false">Image</button>]])print([[</div>]])print([[<div id="pageMain"><!-- Open file --><!-- Toolbox --><!-- History --><!-- Tags --><!-- Layer Container --></div>]])print([[<!-- pageMain -->]])print([[<!-- Open file --><div id="openData" title="File"> <p> <form> Path: <input type="file" id="imagefiles" multiple /> URL: <input type="url" id="imageurl" /> Slice: <input type=button value='<' onclick=previousslice() /> <select name=slice onchange=load()>]]) for i=1, #images do print(' <option value='..images[i].SOPInstanceUID..'>'..i..'</option>') end print([[</select> <input type=button value='>' onclick=nextslice() /> </form>]]) print([[</p> <div id="progressbar" class="ui-progressbar ui-widget ui-widget-content ui-corner-all" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="100"><div class="ui-progressbar-value ui-widget-header ui-corner-left ui-corner-right" style="display: block; width: 100%;"></div></div></div>]])print([[<!-- Toolbox --><div id="toolbox" title="Toolbox"><ul id="toolList"></ul></div><!-- History --><div id="history" title="History"></div><!-- Tags --><div id="tags" title="Tags" style="display:none;"></div>]])print([[<!-- Layer Container --><div id="layerContainer" title="Image" style="width: auto; min-height: 0px; max-height: none; height: 536px;" class="ui-dialog-content ui-widget-content"><canvas id="imageLayer" width="512" height="512"></canvas><canvas id="drawLayer" width="512" height="512"></canvas><canvas id="infoLayer" width="512" height="512"></canvas><canvas id="tempLayer" width="512" height="512"></canvas><div id="plot" style="width:100px;height:70px"></div></div></div>]])print([[</body>]])print([[</html>]])


    additionaly I have included also support for .gif images in dwv applicatition.js:



    have a nice day


    Tomas

  • Thanks for these fixes Tomas, I've push them to the DWV repository. One question, why do you need to specify the jquery ui classes? I tried DWV on Chrome and Firefox under Windows 7 and Fedora and did not have to do it.
    Best,
    Yves

  • Hallo,


    hmmm, maybe the classes are not really necessary. The thing is that original dwv.lua from repository was not working properly in my case (debian, chromium), the container windows for image, tools, etc. options were missing so I started examining why is this happening by inspecting generated html code from your website (where you provide an example) because there everything was displayed properly. So I start adding elements which were missing util I reach the state when it was display properly. However you are right. The original problem was that some part of div elements were not there. The jquery ui classes are not neccessary. I clean it up a little bit.



    For the progress bar, in order to see it properly I need to have it as it is there. (Again I am no expert on jquery at all :)


    There is still serious display issue when using Iceweasel browser (firefox replacement in Debian - predefined browser). It did not create the widow container for image is not displayed. I think that iceweasel is not supported by jquery or it has som compatibility issues.

  • Hi,


    I am trying to do one more thing, which I am not completely sure is actually possible. Imagine that I have following infrastructure setup. I have an application server (tomcat) which can be accessed by anyone. On the application server there is a web application (java ee), which for the simplicity now only takes care about authentication. After a user authenticate himself he gets access to other features.


    Now I have ConQuest running on different machine. Application server can communicate with the machine where ConQuest is running and that is it.


    Now my web app on application server. Is executing dgate CGI with proper query strings. Taking the resulting HTML output and showing it in its own interface. This seems to work so far. However I wanted to integrate DWV viewer and I am encountering on problem. The dicom server query is performed correctly. DWV is displayed correctly. The number of slices of images are filled correctly, but the image is not displayed and I got an error:


    An error occurred while retrieving the file.


    Any idea how to go around this? (maybe it is same origin policy)


    thanks


    Tomas

  • Hi Yves,


    a WADO request to the CGI server is actually passed on the DICOM server using a beefed up DICOM 'echo' request. This is the same protocol that I use for all dgate -- commands.


    Marcel

  • Hi Marcel,


    The WADO request which is generated is correct. I think the problem is how the HTTP response of WADO request link is formulated. In the header of the HTTP response there should be the following information and CORS should work after that:


    Access-Control-Allow-Origin: *


    Marcel, is it possible to change WADO response to include this information in the header?


    best


    Tomas

  • Hi,


    Would it be something like this (similar for all mime types generated from WADO)?


    fprintf(f, "Content-type: image/gif\nAccess-Control-Allow-Origin: *\n\n");


    And is there any danger or disadvantage in doing this? Should it be configurable?


    Marcel

  • Hi,


    I do not see any real danger in it. This setup is kind of standard in cross site scripting. However if you can make it configurable, than it will be definitely safe. Even more you can let the user specify the origin server which their trust. And the cross site scripting will be available only for this server.


    trustServer = http://locahost or xxxx


    Access-Control-Allow-Origin: trustServer


    Tomas

  • Hi,


    A little snag is that the html page is passed in a DICOM message and that therefore the total message has to be even lenght. With a configurable header the code becomes a bit more complicated.


    But I will put it on the list to implement soon.


    Marcel

  • Hi,


    I will try it hopefully next week, I only loaded the the trunk from your website with multi slice example. I see that it is loading at once but I just see one slice. I thought that I load them and than e.g. the thumbnails of will be displayed in a special panel. Is it there or do you plan this type of functionality?


    best


    Tomas

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!