cornerstonejs / cornerstoneTools

[Deprecated] Use Cornerstone3D Instead https://cornerstonejs.org/
MIT License
579 stars 456 forks source link

How to synchronize multiple elements containing same series #748

Closed leonardorame closed 5 years ago

leonardorame commented 5 years ago

Prerequisites

For more information, see the CONTRIBUTING guide.

Description

I would like to know how can I synchronize multiple elements, all of them containing the same series but each with an offset of 1 relative to the previous element. For example, in a grid of 2x2 elements, I want element (1,1) to reference index 0 of my series, element (1,2) to reference index 1, element (2,1) index 2, and so on.

If the user scrolls with the mouse, the first element should reference index 4, to view the next "page" of elements. This is called "tiled" view in some dicom Viewers.

dannyrb commented 5 years ago

@leonardorame, you would likely need to setup the initial state yourself.

  1. User clicks "Tiled Viewing" button
  2. Viewer enables elements, builds stack state, displays appropriate series image in each enabled element
  3. StackScrollSynchronization is automatically enabled, using a strategy where +/- scrolls to any enabledElement increment or decrement the stackScroll index for all other enabledElements in the same direction
leonardorame commented 5 years ago

hi @dannyrb, I already did exactly that, but isn't working as I expect.

My grid is this:

+---+---+
| 1 | 2 |
+---+---+
| 3 | 4 |
+---+---+

When I place the mouse pointer over 1 and scroll, only 2 and 4 are changed, but not 3. When I place it on 2, only 3 and 4 changes.

I would like to be able to change the page, or a row. After scrolling the grid should end as this:

+---+---+
| 3 | 4 |
+---+---+
| 5 | 6 |
+---+---+

That was one row scrolled.

leonardorame commented 5 years ago

To clarify this, this snippet is the one I'm using:

  var synchronizer = new cornerstoneTools.Synchronizer("cornerstonestackscroll",                                      cornerstoneTools.stackScrollSynchronizer);
  var loadAndViewImage = function (aUrl, el, serie) {                                                                 // primero se desabilita para borrar el contenido                                                                 el.serie = serie;
      cornerstone.disable(el);                                                                                          cornerstone.enable(el);                                                                                           cornerstone.loadAndCacheImage(aUrl).then(function (image) {
      cornerstone.displayImage(el, image);                                                                              // Set the stack as tool state                                                                                    // Por último habilitamos el mouse
      cornerstoneTools.mouseInput.enable(el);                                                                           cornerstoneTools.mouseWheelInput.enable(el);
      cornerstoneTools.addStackStateManager(el, ['stack']);                                                             cornerstoneTools.addToolState(el, 'stack', serie);                                                                // Enable all tools we want to use with this element
      cornerstoneTools.stackScroll.activate(el, 1);                                                                     cornerstoneTools.stackScrollWheel.activate(el);                                                                   //setTools(undefined, serie);
      synchronizer.add(el);                                                                                           
  });                                                                                                             
};

loadAndViewImage is called for every element.

Is it ok, or I need to change it?.

leonardorame commented 5 years ago

It looks like the problem is happening because I'm using the same "series" object for all the elements. When I check currentImageIdIndex I get the same value for all the elements.

Apart from creating multiple copies of my series, is there a way to use the same series on all the elements?.

leonardorame commented 5 years ago

Mmm, no, when I create a copy of the series all the elements are synchronized to the same element.

leonardorame commented 5 years ago

Btw, I'm using cornerstoneWADOImageLoaderto load my images, and I don't have a metadataProvider. Should I create one for this?.

dannyrb commented 5 years ago

If you whipped up a quick codepen, I could try to fix the issue. My time's a little tight, but I'll help if I'm able.

leonardorame commented 5 years ago

Hi @dannyrb, I managed to make it work, but it looks like the stackScrollSynchronizer should allow constraining the the stacks.

An example. The stack has 5 elements in a grid of 2x1, this is the scrolling sequence:

Initial state: image

After dragging down the right side cell: image

Continue dragging down the right side cell: image

Continue dragging down the right side cell: image

Now drag the left side cell: image

As you can see, the arrow indicates the left side cell is showing the image index 4, this shouldn't happen, because two cells shouldn't show the same image.

dannyrb commented 5 years ago

Well done on your progress ^_^

It's a bit odd, as synchronizes mostly react to a change on one element and update the others. It might be hard constrain your scroll range using it.

In vNext, you can get away with not using a traditional synchronizer, as the store allows you to see the state of each element, allowing for finer control in situations like this.

You could explore a custom tool? Or when this mode is enabled in your viewer, you could build the image stacks' list of ids in a way that makes your above scenario impossible:

3 elements, 5 images

const stack1ids = [1, 2, 3]
const stack2ids = [2, 3, 4]
const stack3ids = [3, 4, 5]

Pardon my formatting. Sent from my phone

leonardorame commented 5 years ago

Thanks!, I was thinking exactly about this, to create a different stack for each element. Let's try it and I'll be back.

leonardorame commented 5 years ago

Well, that won't be an optimal solution. With a series of 1000s of images and a grid of say 3 by 3 we'll end up having 9 arrays of ~1000 images.

What we need is a "pageSynchronizer" to allow change currentImageIdIndex of every element part of a page (where a page is composed for example with two rows of two elements each) using the formula currentImageIdIndex = currentImageIdIndex + pageSize;.

Could you help me create such synchronizer?.

dannyrb commented 5 years ago

@leonardorame, I'm going to close this issue for now. If you haven't already, you may want to take a peak at the latest version of cornerstone-tools. I think the above would be a lot easier to accomplish with the recent library updates.

If you have specific questions, or code you'd like peer reviewed, I could take a peak and offer thoughts.