Difference between revisions of "CTSC Slicer XNE"

From NAMIC Wiki
Jump to: navigation, search
Line 187: Line 187:
 
== Things to Build ==
 
== Things to Build ==
  
* Authentication dialog (try using existing Base/GUI/vtkSlicerXNATPermissionPrompterWidget code) (wjp)
+
* Authentication dialog (try using existing Base/GUI/vtkSlicerXNATPermissionPrompterWidget code) '''(wjp)'''
* extend FetchMI infrastructure to admit XNE web services (wjp)
+
* extend FetchMI infrastructure to admit XNE web services '''(wjp)'''
 
* Improve/generalize http error checking  
 
* Improve/generalize http error checking  
 
** bring to superclass vtkFetchMIParser (right now, just looking for error string in html title in vtkFetchMIParserXND)
 
** bring to superclass vtkFetchMIParser (right now, just looking for error string in html title in vtkFetchMIParserXND)
 
** recognize and report specific http error codes via vtkFetchMINode::ErrorMessage and vtkFetchMINode::RaiseErrorEvent
 
** recognize and report specific http error codes via vtkFetchMINode::ErrorMessage and vtkFetchMINode::RaiseErrorEvent
* Extend FetchMI's GUI to include an XNE notebook, switch notebooks when serverType changes. (wjp)
+
* Extend FetchMI's GUI to include an XNE notebook, switch notebooks when serverType changes. '''(wjp)'''
* Build vtkFetchMIQueryBuilder superclass (wjp)
+
* Build vtkFetchMIQueryBuilder superclass '''(wjp)'''
* Derive vtkFetchMIQueryBuilderXND class and move XND query formulation into here. (wjp)
+
* Derive vtkFetchMIQueryBuilderXND class and move XND query formulation into here. '''(wjp)'''
 
* Add vtkFetchMIQueryBuilderXNE class
 
* Add vtkFetchMIQueryBuilderXNE class
 
* Add vtkFetchMIWriterXNE class
 
* Add vtkFetchMIWriterXNE class

Revision as of 20:46, 4 August 2009

Home < CTSC Slicer XNE

UXP & functionality planning for Slicer's XNE client

Workflow & Implementation approaches

All Workflow Steps:

  • Select XNAT Enterprise server
  • Authentication dialog presented
  • XNAT login performed and session opened;
  • Response is checked for error codes
  • XNAT queried for projects
  • response is checked for http error codes
  • xml parsed to get list of projects
  • GUI populated
  • One project selected
  • XNAT queried for subjects and experiments in that project
  • GUI populated
  • User performs search for data
  • User selects one scan and "download"
  • Scan is loaded into Slicer

This workflow is detailed below. Note: Slicer uses the curl_easy library for client calls to RESTful web services. So the unix commandline curl calls below will need to be packaged up appropriately (including whatever basic authentication header information is required).

1. Select XNAT Enterprise Server

This sets the current URI handler to be the XNE_HttpHandler for subsequent REST-based client calls to XNE web services.

2. Authentication Dialog Presented

CTSC Slicer XNE PermissionPrompter.png

  • Enter user name and password

3. Process Dialog Input

  • Save the username (XNE_UserName) and password (XNE_Password)
  • Authenticate with $XNE_Svr and create a session:
curl -d POST $XNE_Svr/REST/JSESSION -u $XNE_UserName:$XNE_Password

The response from this request is a session ID that should be stored in $JSessionID; that ID can be used in all subsequent queries so authentication doesn't have to be performed at each transaction.

4. Query XNAT for Projects Available to User

  • XNAT queried for appropriate projects
curl $XNE_Srv/REST/projects?format=xml --cookie JSESSIONID=$sessionID
  • response is checked for http error codes
    • if error is found, report to user
    • else xml is parsed to get list of scans
  • GUI is populated

Question: Eventually, it would be nice to get the same info that the web GUI presents on its project view. Can we get a set of queries from Tim that give us the info there? including:

  • Project Name
  • Project ID
  • PI
  • Description
  • Permissions

5. User Selects One Project from GUI and clicks "Search Button"

CTSC Slicer XNE ProjectPanel.png

Question: Would be nice to search across multiple projects. Ask Tim for help on formulating queries to search for subjects, experiments, etc., for projects {P1, P2,...,PN}.

6. Query XNAT for Subjects in Selected Project

  • XNAT queried for appropriate subjects
curl $XNE_Svr/REST/projects/$projectID/subjects?format=xml --cookie JSESSIONID=$sessionID
  • response is checked for http error codes
    • if error is found, report to user
    • else xml is parsed to get list of scans

7. User Selects One Subject, Configures Filters to Narrow Search & Selects Search

Presents a search that only requires SubjectID or ExperimentID to be selected in order to populate the list of scans, but each additional selection (corresponding to the basic XNE data model) can be used to focus the search:

7a. Initial Presentation

  • Subject: { All SubjectIDs} (eventually a checkbox for "include shared subjects")
  • Experiments: { All ExperimentIDs } (eventually a checkbox for "include shared experiments")
    • Scans: { }
    • Reconstructions: { }
    • Assessors: { }
    • Non-imaging Assessments: { }
query: curl $XNE_Svr/REST/projects/$ProjectID/subjects?format=xml --cookie JSESSIONID=$JsessionID
parse response into list of SubjectIDs
query: curl $XNE_Svr/REST/projects/$ProjectID/experiments?format=xml --cookie JSESSIONID=$JSessionID
parse response and add to list of ExperimentIDs
update GUI


7b1. Just a Subject ID is selected; Filters are updated

  • Subject: $SubjectID
  • Experiments: { All for $SubjectID }
    • Scans: { All for $SubjectID }
    • Reconstructions: { All for $SubjectID }
    • Assessors: { All for $SubjectID }
    • Non-imaging Assessments: { All for $SubjectID }
query: curl $XNE_Svr/REST/projects/$ProjectID/subjects/$SubjectID/experiments?format=xml --cookie JSESSIONID=$JsessionID
parse response into list of ExperimentIDs
for each id in list of ExperimentIDs
{
 query: curl $XNE_Svr/REST/projects/$ProjectID/subjects/subjects/$SubjectID/experiments/$id/scans?format=xml --cookie JSESSIONID=$JSessionID
 parse response and add to list of ScanIDs
 query: curl $XNE_Svr/REST/projects/$ProjectID/subjects/subjects/$SubjectID/experiments/$id/reconstructions?format=xml --cookie JSESSIONID=$JSessionID
 parse response and add to list of ReconstructionIDs
 query: curl $XNE_Svr/REST/projects/$ProjectID/subjects/subjects/$SubjectID/experiments/$idD/assessors?format=xml --cookie JSESSIONID=$JSessionID
 parse response and add to list of AssessorIDs
}
update GUI

7b2. OR, just an Experiment ID is selected; Filters are updated

  • Subject: { All for $ExperimentID }
  • Experiments: $ExperimentID
    • Scans: { All for $ExperimentID }
    • Reconstructions: { All for $ExperimentID }
    • Assessors: { All for $ExperimentID }
    • Non-imaging Assessments: { All for $ExperimentID }
query: curl $XNE_Svr/REST/projects/$ProjectID/experiments/$ExperimentID/subjects?format=xml --cookie JSESSIONID=$JsessionID
parse response into list of SubjectIDs
for each id in list of SubjectIDs
{
 query: curl $XNE_Svr/REST/projects/$ProjectID/subjects/subjects/$id/experiments/$ExperimentID/scans?format=xml --cookie JSESSIONID=$JSessionID
 parse response and add to list of ScanIDs
 query: curl $XNE_Svr/REST/projects/$ProjectID/subjects/subjects/$id/experiments/$ExperimentID/reconstructions?format=xml --cookie JSESSIONID=$JSessionID
 parse response and add to list of ReconstructionIDs
 query: curl $XNE_Svr/REST/projects/$ProjectID/subjects/subjects/$id/experiments/$ExperimentID/assessors?format=xml --cookie JSESSIONID=$JSessionID
 parse response and add to list of AssessorIDs
}
update GUI


7c. Both SubjectID && Experiment ID have been selected; Filters are updated

  • Subject: $SubjectIDs
  • Experiments: $ExperimentID
    • Scans: { All for $SubjectID && $ExperimentID }
    • Reconstructions: { Focused for $SubjectID && $ExperimentID }
    • Assessors: { Focused for $SubjectID && $ExperimentID }
    • Non-imaging Assessments: { Focused for $SubjectID && $ExperimentID }
 query: curl $XNE_Svr/REST/projects/$ProjectID/subjects/subjects/$SubjectID/experiments/$ExperimentID/scans?format=xml --cookie JSESSIONID=$JSessionID
 parse response and add to list of ScanIDs
 query: curl $XNE_Svr/REST/projects/$ProjectID/subjects/subjects/$SubjectID/experiments/$ExperimentID/reconstructions?format=xml --cookie JSESSIONID=$JSessionID
 parse response and add to list of ReconstructionIDs
 query: curl $XNE_Svr/REST/projects/$ProjectID/subjects/subjects/$SubjectID/experiments/$ExperimentID/assessors?format=xml --cookie JSESSIONID=$JSessionID
 parse response and add to list of AssessorIDs
update GUI


7d. A ScanID is selected; Filters are updated

  • Subject: $SubjectIDs
  • Experiments: $ExperimentID
    • Scans: { $ScanID }
    • Reconstructions: { }
    • Assessors: { }
    • Non-imaging Assessments: { }

8. User Clicks Download

Questions for the XNAT Team: Once we get this far, presume we don't know the format of the resource (DICOM, Analyze, NRRD, etc.) so we can't just use the following to retrieve a list of files:

curl $XNE_Svr/projects/$ProjectID/subjects/$SubjectID/experiments/$ExpID/scans/$ScanID/resources/DICOM/files/format=xml --cookie JSESSIONID=$JSessionID

What is the recommended way to download the resource?

This returns a list of URIs which Slicer uses to populate a vtkMRMLVolumeArchetypeStorageNode:URI and vtkMRMLVolumeArchetypeStorageNode::URIListMembers

9. Scan is Loaded into Slicer

vtkMRMLVolumeArchetypeStorageNode::ReadData( vtkMRMLVolumeArchetypeStorage *node) is called, which calls vtkMRMLStorageNode::StageReadData (*node) to download data using the XNE_HttpHandler.

Question for Nicole: Does the approach here seem to fit with the multi-file volume code you've written?

We can also ask for a .zip (or .xar?) file and use something like the code in Base/GUI/Tcl/Loader.tcl to load the archive from cache.

Questions

  • We'll need an XNETagTable to hold metadata for all resources coming from and going up to $XNE_Svr.
  • We'll need to decide what metadata to put on resources downloaded from $XNE_Srv (stored in each vtkMRMLStorableNode's UserTagTable) and determine how to translate this metadata into appropriate URIs to PUT or POST back to $XNE_Svr.
  • XNE web services allows us to DL multiple resources using one URI (see here); should we implement this in a first pass, or later?
  • Custom tags are present in XNE -- how can we query for all custom tags and their values for a selected $XNE_Svr? This would allow us to populate an "advanced" search widget.

Things to Build

  • Authentication dialog (try using existing Base/GUI/vtkSlicerXNATPermissionPrompterWidget code) (wjp)
  • extend FetchMI infrastructure to admit XNE web services (wjp)
  • Improve/generalize http error checking
    • bring to superclass vtkFetchMIParser (right now, just looking for error string in html title in vtkFetchMIParserXND)
    • recognize and report specific http error codes via vtkFetchMINode::ErrorMessage and vtkFetchMINode::RaiseErrorEvent
  • Extend FetchMI's GUI to include an XNE notebook, switch notebooks when serverType changes. (wjp)
  • Build vtkFetchMIQueryBuilder superclass (wjp)
  • Derive vtkFetchMIQueryBuilderXND class and move XND query formulation into here. (wjp)
  • Add vtkFetchMIQueryBuilderXNE class
  • Add vtkFetchMIWriterXNE class
  • Add vtkFetchMIParserXNE class
  • Add vtkFetchMIWebServicesClientXNE class to encapsulate
  • Add vtkXNETagTable in Libs/RemoteIO
  • Add vtkXNEHandler in Libs/RemoteIO