Mercurial > hg > orthanc
changeset 2873:703d1e848907
Orthanc Explorer: Lookup and limit the results to 100 patients/studies
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 09 Oct 2018 16:27:49 +0200 |
parents | 9d08edde614b |
children | 67ebfacf4467 |
files | NEWS OrthancExplorer/explorer.html OrthancExplorer/explorer.js |
diffstat | 3 files changed, 268 insertions(+), 60 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Tue Oct 09 14:19:48 2018 +0200 +++ b/NEWS Tue Oct 09 16:27:49 2018 +0200 @@ -7,6 +7,12 @@ * Possibility to restrict the allowed DICOM commands for each modality +Orthanc Explorer +---------------- + +* The first screen of Orthanc Explorer is now a form to do studies lookups +* Support of large databases, by limiting the results to 100 patients or studies + REST API --------
--- a/OrthancExplorer/explorer.html Tue Oct 09 14:19:48 2018 +0200 +++ b/OrthancExplorer/explorer.html Tue Oct 09 16:27:49 2018 +0200 @@ -34,11 +34,11 @@ <script src="../plugins/explorer.js"></script> </head> <body> - <div data-role="page" id="find-patients" > + <div data-role="page" id="lookup" > <div data-role="header" > - <h1><span class="orthanc-name"></span>Find a patient</h1> + <h1><span class="orthanc-name"></span>Lookup studies</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-right"> @@ -48,16 +48,67 @@ </div> </div> <div data-role="content"> - <ul id="all-patients" data-role="listview" data-inset="true" data-filter="true"> - </ul> + <form data-ajax="false" id="lookup-form"> + <div data-role="fieldcontain"> + <label for="lookup-patient-id">Patient ID:</label> + <input type="text" name="lookup-patient-id" id="lookup-patient-id" value="" /> + </div> + + <div data-role="fieldcontain"> + <label for="lookup-patient-name">Patient Name:</label> + <input type="text" name="lookup-patient-name" id="lookup-patient-name" value="" /> + </div> + + <div data-role="fieldcontain"> + <label for="lookup-accession-number">Accession Number:</label> + <input type="text" name="lookup-accession-number" id="lookup-accession-number" value="" /> + </div> + + <div data-role="fieldcontain"> + <label for="lookup-study-description">Study Description:</label> + <input type="text" name="lookup-study-description" id="lookup-study-description" value="" /> + </div> + + <div data-role="fieldcontain"> + <label for="lookup-study-date">Study Date:</label> + <select name="lookup-study-date" id="lookup-study-date"> + </select> + </div> + + <fieldset class="ui-grid-b"> + <div class="ui-block-a"> + <a href="#find-patients" data-role="button" data-theme="b" data-direction="reverse">All patients</a> + </div> + <div class="ui-block-b"> + <a href="#find-studies" data-role="button" data-theme="b" data-direction="reverse">All studies</a> + </div> + <div class="ui-block-c"> + <button id="lookup-submit" type="submit" data-theme="e">Do lookup</button> + </div> + </fieldset> + <div> </div> + </form> + <div id="lookup-result"> + <div id="lookup-alert"> + <div class="ui-bar ui-bar-e"> + <h3>Warning:</h3> Your lookup led to many results! + Showing only <span id="lookup-count">?</span> studies to + avoid performance issue. Please make your query more + specific, then relaunch the lookup. + </div> + <div> </div> + </div> + <ul data-role="listview" data-inset="true" data-filter="true"> + </ul> + </div> </div> </div> - <div data-role="page" id="find-studies" > + <div data-role="page" id="find-patients" > <div data-role="header" > - <h1><span class="orthanc-name"></span>Find a study</h1> + <h1><span class="orthanc-name"></span>All patients</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-right"> @@ -67,6 +118,43 @@ </div> </div> <div data-role="content"> + <div id="alert-patients"> + <div class="ui-bar ui-bar-e"> + <h3>Warning:</h3> This is a large Orthanc server. Showing + only <span id="count-patients">?</span> patients to avoid + performance issue. Make sure to use lookup if targeting + specific patients! + </div> + <div> </div> + </div> + <ul id="all-patients" data-role="listview" data-inset="true" data-filter="true"> + </ul> + </div> + </div> + + <div data-role="page" id="find-studies" > + <div data-role="header" > + <h1><span class="orthanc-name"></span>All studies</h1> + <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> + </div> + <div data-type="horizontal" data-role="controlgroup" class="ui-btn-right"> + <a href="#upload" data-icon="gear" data-role="button">Upload</a> + <a href="#query-retrieve" data-icon="search" data-role="button">Query/Retrieve</a> + <a href="#jobs" data-icon="refresh" data-role="button" data-direction="reverse">Jobs</a> + </div> + </div> + <div data-role="content"> + <div id="alert-studies"> + <div class="ui-bar ui-bar-e"> + <h3>Warning:</h3> This is a large Orthanc server. Showing + only <span id="count-studies">?</span> studies to avoid + performance issue. Make sure to use lookup if targeting + specific studies! + </div> + <div> </div> + </div> <ul id="all-studies" data-role="listview" data-inset="true" data-filter="true"> </ul> </div> @@ -76,8 +164,8 @@ <div data-role="header" > <h1><span class="orthanc-name"></span>Upload DICOM files</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> </div> <div data-role="content"> @@ -105,8 +193,8 @@ <div data-role="header" > <h1><span class="orthanc-name"></span>Patient</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-right"> <a href="#upload" data-icon="gear" data-role="button">Upload</a> @@ -166,8 +254,8 @@ Study </h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-right"> <a href="#upload" data-icon="gear" data-role="button">Upload</a> @@ -221,8 +309,8 @@ Series </h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-right"> <a href="#upload" data-icon="gear" data-role="button">Upload</a> @@ -278,8 +366,8 @@ Instance </h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-right"> <a href="#upload" data-icon="gear" data-role="button">Upload</a> @@ -334,8 +422,8 @@ <div data-role="header" > <h1><span class="orthanc-name"></span>Plugins</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> </div> <div data-role="content"> @@ -348,8 +436,8 @@ <div data-role="header" > <h1><span class="orthanc-name"></span>DICOM Query/Retrieve (1/4)</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> </div> <div data-role="content"> @@ -419,8 +507,8 @@ <div data-role="header" > <h1><span class="orthanc-name"></span>DICOM Query/Retrieve (2/4)</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> <a href="#query-retrieve" data-icon="search" class="ui-btn-right" data-direction="reverse">Query/Retrieve</a> </div> @@ -435,8 +523,8 @@ <div data-role="header" > <h1><span class="orthanc-name"></span>DICOM Query/Retrieve (3/4)</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> <a href="#query-retrieve" data-icon="search" class="ui-btn-right" data-direction="reverse">Query/Retrieve</a> </div> @@ -451,8 +539,8 @@ <div data-role="header" > <h1><span class="orthanc-name"></span>DICOM Query/Retrieve (4/4)</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> <a href="#query-retrieve" data-icon="search" class="ui-btn-right" data-direction="reverse">Query/Retrieve</a> </div> @@ -480,8 +568,8 @@ <div data-role="header" > <h1><span class="orthanc-name"></span>Jobs</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> </div> <div data-role="content"> @@ -494,8 +582,8 @@ <div data-role="header" > <h1><span class="orthanc-name"></span>Job</h1> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-left"> - <a href="#find-patients" data-icon="home" data-role="button" data-direction="reverse">Patients</a> - <a href="#find-studies" data-icon="arrow-r" data-role="button" data-direction="reverse">Studies</a> + <a href="#lookup" data-icon="arrow-r" data-role="button" data-direction="reverse">Lookup</a> + <a href="#plugins" data-icon="grid" data-role="button" data-direction="reverse">Plugins</a> </div> <div data-type="horizontal" data-role="controlgroup" class="ui-btn-right"> <a href="#jobs" data-icon="refresh" data-role="button" data-direction="reverse">Jobs</a>
--- a/OrthancExplorer/explorer.js Tue Oct 09 14:19:48 2018 +0200 +++ b/OrthancExplorer/explorer.js Tue Oct 09 16:27:49 2018 +0200 @@ -13,6 +13,8 @@ //$.mobile.defaultPageTransition = 'slide'; +var LIMIT_RESOURCES = 100; + var currentPage = ''; var currentUuid = ''; @@ -360,57 +362,169 @@ +$('#lookup').live('pagebeforeshow', function() { + // NB: "GenerateDicomDate()" is defined in "query-retrieve.js" + var target = $('#lookup-study-date'); + $('option', target).remove(); + target.append($('<option>').attr('value', '*').text('Any date')); + target.append($('<option>').attr('value', GenerateDicomDate(0)).text('Today')); + target.append($('<option>').attr('value', GenerateDicomDate(-1)).text('Yesterday')); + target.append($('<option>').attr('value', GenerateDicomDate(-7) + '-').text('Last 7 days')); + target.append($('<option>').attr('value', GenerateDicomDate(-31) + '-').text('Last 31 days')); + target.append($('<option>').attr('value', GenerateDicomDate(-31 * 3) + '-').text('Last 3 months')); + target.append($('<option>').attr('value', GenerateDicomDate(-365) + '-').text('Last year')); + target.selectmenu('refresh'); + + $('#lookup-result').hide(); +}); + + +$('#lookup-submit').live('click', function() { + $('#lookup-result').hide(); + + var lookup = { + 'Level' : 'Study', + 'Expand' : true, + 'Limit' : LIMIT_RESOURCES + 1, + 'Query' : { + 'StudyDate' : $('#lookup-study-date').val() + } + }; + + $('#lookup-form input').each(function(index, input) { + if (input.value.length != 0) { + if (input.id == 'lookup-patient-id') { + lookup['Query']['PatientID'] = input.value; + } + else if (input.id == 'lookup-patient-name') { + lookup['Query']['PatientName'] = input.value; + } + else if (input.id == 'lookup-accession-number') { + lookup['Query']['AccessionNumber'] = input.value; + } + else if (input.id == 'lookup-study-description') { + lookup['Query']['StudyDescription'] = input.value; + } + else { + console.error('Unknown lookup field: ' + input.id); + } + } + }); + + console.log(lookup); + + $.ajax({ + url: '../tools/find', + type: 'POST', + data: JSON.stringify(lookup), + dataType: 'json', + async: false, + error: function() { + alert('Error during lookup'); + }, + success: function(studies) { + console.log(studies); + FormatListOfStudies('#lookup-result ul', '#lookup-alert', '#lookup-count', studies); + $('#lookup-result').show(); + } + }); + + return false; +}); + + $('#find-patients').live('pagebeforeshow', function() { - GetResource('/patients?expand', function(patients) { + GetResource('/patients?expand&since=0&limit=' + (LIMIT_RESOURCES + 1), function(patients) { var target = $('#all-patients'); $('li', target).remove(); SortOnDicomTag(patients, 'PatientName', false, false); - for (var i = 0; i < patients.length; i++) { + var count, showAlert; + if (patients.length <= LIMIT_RESOURCES) { + count = patients.length; + showAlert = false; + } + else { + count = LIMIT_RESOURCES; + showAlert = true; + } + + for (var i = 0; i < count; i++) { var p = FormatPatient(patients[i], '#patient?uuid=' + patients[i].ID); target.append(p); } - target.listview('refresh'); + target.listview('refresh'); + + if (showAlert) { + $('#count-patients').text(LIMIT_RESOURCES); + $('#alert-patients').show(); + } else { + $('#alert-patients').hide(); + } }); }); -$('#find-studies').live('pagebeforeshow', function() { - GetResource('/studies?expand', function(studies) { - var target = $('#all-studies'); - $('li', target).remove(); +function FormatListOfStudies(targetId, alertId, countId, studies) +{ + var target = $(targetId); + $('li', target).remove(); + + for (var i = 0; i < studies.length; i++) { + var patient = studies[i].PatientMainDicomTags.PatientName; + var study = studies[i].MainDicomTags.StudyDescription; - for (var i = 0; i < studies.length; i++) { - var patient = studies[i].PatientMainDicomTags.PatientName; - var study = studies[i].MainDicomTags.StudyDescription; + var s; + if (typeof patient === 'string') { + s = patient; + } - var s; - if (typeof patient === 'string') { - s = patient; + if (typeof study === 'string') { + if (s.length > 0) { + s += ' - '; } - if (typeof study === 'string') { - if (s.length > 0) { - s += ' - '; - } - - s += study; - } - - studies[i]['Label'] = s; + s += study; } - Sort(studies, function(a) { return a.Label }, false, false); + studies[i]['Label'] = s; + } + + Sort(studies, function(a) { return a.Label }, false, false); + + + var count, showAlert; + if (studies.length <= LIMIT_RESOURCES) { + count = studies.length; + showAlert = false; + } + else { + count = LIMIT_RESOURCES; + showAlert = true; + } - for (var i = 0; i < studies.length; i++) { - var p = FormatStudy(studies[i], '#study?uuid=' + studies[i].ID, false, true); - target.append(p); - } + for (var i = 0; i < count; i++) { + var p = FormatStudy(studies[i], '#study?uuid=' + studies[i].ID, false, true); + target.append(p); + } + + target.listview('refresh'); - target.listview('refresh'); + if (showAlert) { + $(countId).text(LIMIT_RESOURCES); + $(alertId).show(); + } else { + $(alertId).hide(); + } +} + + +$('#find-studies').live('pagebeforeshow', function() { + GetResource('/studies?expand&since=0&limit=' + (LIMIT_RESOURCES + 1), function(studies) { + FormatListOfStudies('#all-studies', '#alert-studies', '#count-studies', studies); }); });