                   throw ReferenceError.new("Subject #{ subject.number } does" +
                                            " not have a session #{ number }")
                 # Grab the subject session embedded object.
-                sess = subject.sessions[number - 1]
-                # The session must have a detail foreign key.
-                if not sess.detail?
-                  throw ReferenceError.new("Subject #{ subject.number }" +
-                                           " Session #{ sess.number } does" +
-                                           " not have detail")
-
-                # Fetch the session detail.
-                Router.getSessionDetail(sess)
+                session = subject.sessions[number - 1]
+                # If the session has a scans array, then the detail was already
+                # fetched and we are done. Otherwise, fetch the detail.
+                if session.scans?
+                  session
+                else
+                  # The session must have a detail foreign key.
+                  if not session.detail?
+                    throw ReferenceError.new("Subject #{ subject.number }" +
+                                             " Session #{ session.number } does" +
+                                             " not have detail")
+                  # Fetch the session detail.
+                  Router.getSessionDetail(session)
             views:
               'main@':
                 templateUrl: '/partials/session-detail.html'
                 controller:  'SessionDetailCtrl'
 
           # The scan state.
+          # The scan state parameter is the scan number.
           .state 'quip.subject.session.scan',
             abstract: true
             url: '/scan/:scan'
             resolve:
               scan: (session, $stateParams, Router) ->
-                Router.getScan(session, $stateParams.scan)
+                number = parseInt($stateParams.scan)
+                Router.getScan(session, number)
+
+          # The scan volume state.
+          # The volume state parameter is the volume number.
+          .state 'quip.subject.session.scan.volume',
+            url: '/volume/{volume:[1-9][0-9]*}'
+            resolve:
+              volume: (scan, $stateParams, Router) ->
+                number = parseInt($stateParams.volume)
+                Router.getVolume(scan, number)
+            views:
+              'main@':
+                templateUrl: '/partials/volume.html'
+                controller:  'VolumeCtrl'
 
           # The registration state.
+          # The registration state parameter is the registration
+          # resource name.
           .state 'quip.subject.session.scan.registration',
             abstract: true
             url: '/registration/:registration'

              registration: (scan, $stateParams, Router) ->
                Router.getRegistration(scan, $stateParams.registration)

          # The scan image detail page.
          .state 'quip.subject.session.scan.image',
            url: '/image/{timePoint:[1-9][0-9]*}'
            resolve:
              image: (scan, $stateParams, Router) ->
                timePoint = parseInt($stateParams.timePoint)
                Router.getImageDetail(scan, timePoint)
            views:
              'main@':
                templateUrl: '/partials/image-detail.html'
                controller:  'ImageDetailCtrl'

          # The registration image detail page.
          .state 'quip.subject.session.scan.registration.image',
            url: '/image/{timePoint:[1-9][0-9]*}'
            resolve:
              image: (registration, $stateParams, Router) ->
                timePoint = parseInt($stateParams.timePoint)
                Router.getImageDetail(registration, timePoint)
            views:
              'main@':
                templateUrl: '/partials/image-detail.html'
                controller:  'ImageDetailCtrl'

        # Redirect an URL with trailing slash to an URL without it.
        $urlRouterProvider.rule ($injector, $location) ->

                controller:  'SubjectListCtrl'

          # The subject state.
          .state 'quip.subject',
            url: '/:collection/subject/{subject:[0-9]+}?id'
            resolve:
