Viewers icon indicating copy to clipboard operation
Viewers copied to clipboard

How to add 3D button with its features

Open MongiBr opened this issue 3 years ago • 46 comments

I need to add a button 3d to Ohif viewer app vtk viewport mpr2D button i want to change it to 3D Button Someone help me please!

MongiBr avatar May 03 '21 22:05 MongiBr

@MongiBr Hello, I have managed to apply a 3D button using https://react-vtkjs-viewport.netlify.app/. I have reused the MPR 2D button function and using the code from https://react-vtkjs-viewport.netlify.app/volume-rendering. You can see the code from Sources. Then upload the images by ID and it works. image

ArturRod avatar Aug 06 '21 08:08 ArturRod

Hello, @ArturRod! I'm a student with little experience with VTK and OHIF. I've been trying to do the same thing as you did, but I don't know how exactly to do it. Could you tell me where can I find the MPR 2D and what code from sources I should use?

ed-morais avatar Sep 07 '21 23:09 ed-morais

Hello, @ed-morais, let me tell you, you have the codes for the 3D generation here, you will only have to adapt it with your IDs of the images of your PACS. -> https://github.com/OHIF/react-vtkjs-viewport/tree/master/examples (I in this case use VTKVolumeRenderingExample.js, and presets.js is also necessary). On VTKVolumeRenderingExample.js -> From this class you have to adapt to load the IDs of the images. You have to implement that class in your code and make it call from a new button, for this I loaded a new event in commandsModule.js ->

render: {
      commandFn: actions.render,
      storeContexts: ['viewports'],
      options: {},
      context: 'VIEWER',
},
-------------------------------------------------------------------------
    render: async ({ viewports }) => {
      const displaySet =
        viewports.viewportSpecificData[viewports.activeViewportIndex];
      const viewportProps = [
        {
          orientation: {
            sliceNormal: [0, 0, 1],
            viewUp: [0, -1, 0],
          },
        },
      ];
      try {
        await setMPRLayout(displaySet, viewportProps, 1, 1);
      } catch (error) {
        throw new Error(error);
      }
      const vistaActivada = Array.from(
        document.getElementsByClassName('vtk-viewport-handler')
      );
      vistaActivada[0].innerHTML = '';
      ReactDOM.render(<Render3D />, vistaActivada[0]);
      Render3D.botones(false);
    },

TolbarModule create Button 3D: { id: '3D', label: '3D', icon: 'cube', type: TOOLBAR_BUTTON_TYPES.COMMAND, CustomComponent: VTKMPRToolbarButton, commandName: 'render', context: 'ACTIVE_VIEWPORT::CORNERSTONE', }, As you can see, duplicate the event from 2D and adapt them for the 3D view. I hope I can help you with this, you can ask me any questions.

ArturRod avatar Sep 13 '21 07:09 ArturRod

The 3D render is now working perfectly. Thank you so much, @ArturRod! :)

ed-morais avatar Sep 14 '21 14:09 ed-morais

Hello again, @ArturRod! I've been able to adapt the code to load the IDs, but I think I didn't manage to do it properly. Every time I click on a different study or series I need to reload the page so the 3D render can display the right image. I have tried to pass the data from the commandsModule.js (displaySet.StudyInstanceUID, displaySet.SeriesInstanceUID) via props to the VTKVolumeRenderingExample.js How did you manage to adapt the code so there is no need to reload the page?

ed-morais avatar Sep 30 '21 10:09 ed-morais

Hi @ed-morais, the same thing happened to me too. It is a react-vtkjs-viewport problem, the problem is that the internal map generated by react-vtkjs-viewport cannot be updated, that is, it generates a cache but does not delete it. To solve it you have to do the following:

  1. React-vtkjs-viewport needs to be recompiled with a slight modification. To do this, download: https://github.com/OHIF/react-vtkjs-viewport
  2. Once you have it downloaded you will have to modify these files so that you can clear the cache: image
  3. Once you have it, compile it again, and it will generate the file index.umd.js
  4. When you have it, copy it into your project, overwriting the one you already have:OHIF/node_modules/react-vtkjs-viewport-master-master\dist.
  5. With this it will work for you, now you just have to call imageDataCache.clear (); in loadDataset, so it will clear the cache every time you load the data. image

The only problem is that every time you compile your project with yarn install again, you will have to copy the index.umd.js file I already mentioned this in react-vtkjs-viewport, their thing would be to put this in a committee and add it definitively.

I hope I have helped.

ArturRod avatar Sep 30 '21 11:09 ArturRod

Hi @ed-morais and @ArturRod ! Thanks both for these suggestions. I've applied your modifications and everything works. I've also inserted the coding for extracting the studyInstanceUID of the current study, by using studyMetadataManager. There is only one problem I haven't been able to solve yet, which is extracting SeriesInstanceUID parameter too. @ed-morais you mentioned you managed to pass the data from the commandsModule.js (displaySet.StudyInstanceUID, displaySet.SeriesInstanceUID) via props to the VTKVolumeRenderingExample.js . Can you please share the code?

Thanks again

NicholasDascanio avatar Sep 30 '21 14:09 NicholasDascanio

Hello @NicholasDascanio! What I have put in the code to be able to obtain the UIDs, is to save the urls in localStorage with a viewer ID activated. So when I want to access I always have the UID available, then I have methods so that the local storage does not fill up and is cleaned every time you change your view. (I only save in localstorage the UIDs of the series that are in the views). This I have implemented in getViewportData: image I get the index from -> let index = this.props.viewportIndex;

Later in the 3D class, in the method -> createStudyImageIds I get the data of the selected view: image

ArturRod avatar Oct 01 '21 10:10 ArturRod

Hello @ArturRod !! Everything works now, thanks a lot! Your help has been precious :)

NicholasDascanio avatar Oct 01 '21 16:10 NicholasDascanio

Hello again @ArturRod !! I was wondering if you could help me out with an issue related to #2180 . I've add the 3D button and it's working perfectly thanks to your suggestions. However, I wanted to create a new toolbar for the 3D functionality with just an exit button, since the one i've used so far it's equal to the MPR one (which is obvious since the functionality is implemented in the VTK extension).

After having add a new context here (platform/viewer/src/context/AppContext.js), I tried to modify VTK extension toolbar, having no effects. Then I tried to create another extension (VTK-3D), equal to the VTK one except for the fact that it should use just 1 button and a different defaultContext, but i haven't managed to make it work, even though it gives me no error.

Do you have any idea about how to proceed? :)

NicholasDascanio avatar Oct 04 '21 15:10 NicholasDascanio

Hello @NicholasDascanio What I did is a bit of a 'fix' since what I really do is generate the 2D view and then hide and modify the buttons. When I open I call this method true or false depending on whether I am going to hide or show the data:

//Makes the buttons visible or invisible, if true they are activated: image

Activado it is a global variable that has to be where you are going to put this method.

ArturRod avatar Oct 05 '21 07:10 ArturRod

Hello again @ArturRod ! Thanks a lot for the insights!! Basing my solution on your suggestions, I've solved every problem :)

NicholasDascanio avatar Oct 05 '21 12:10 NicholasDascanio

Hello @ArturRod According to your steps, I have added 3D buttons. At this time, I want to freely control the window width and level of 3D view. What should I do with the same window width and level function as the MPR toolbar?

Future-Zlb avatar Oct 13 '21 06:10 Future-Zlb

Hello @zlb8888 ! I don't know if this is what you mean? If not, let me know, since I still misunderstood about the levels or the width.

Currently do not modify the width and height of the window for the 3D view, leave it as the 2D MPR. But I think that the best solution in this case would be to modify the main canvas from js, that is, modify the structure of the view to your own, this will have to be done with some method. There is also the option that if you didn't want to modify the 2D MPR window and transform it to 3D, you could create a 3D button and make it open a new 3D view -> window.open (url," name of window "," width = 300, height = 200 ") These are some ideas that I can give you, I hope I can help you 😊

ArturRod avatar Oct 13 '21 08:10 ArturRod

Hello again @ArturRod Thank you for your reply.I'm sorry. Maybe I didn't make myself clear.

At present, the window level can only be adjusted through the CT preset value of the existing 3D, that is, the window level can be set by writing the dead data in presets.js. // WWWC image

But what I want to do is to have the same effect as the WWW tool in the 2D MPR toolbar. The left mouse button can adjust the size of window level.

// Modified preset window level. image

tried this method, but it didn't work. image

Have you ever encountered such a problem?

Future-Zlb avatar Oct 13 '21 09:10 Future-Zlb

Hello again @Zaid-Safadi Bffff ..... well this in particular I have not tried. I understand that what should be done is a contextual menu, which is activated if you have the WWWC button activated and modify the button event with the list of presets.js. Maybe this can help: https://www.youtube.com/watch?v=RHQfmpBEKf8&ab_channel=Codingflag You would have to apply what has been said, that when the WWWC is activated, the contextual menu with the pretests is put, I think it is quite simple to implement, and a good idea! For now I have it with the list, maybe I will implement it like you, since I liked the idea.

ArturRod avatar Oct 13 '21 09:10 ArturRod

Hello again @ArturRod Thank you for your advice.

Future-Zlb avatar Oct 18 '21 01:10 Future-Zlb

Hello! @ArturRod @NicholasDascanio I've been trying to pass data via props, but I think that's not the best way to do it, so I'm trying to implement the code the way you did, but I'm having some issues.

Here is the code using props:

commandsModule.js image

Render3D.js image image

First I tried to recompile react-vtkjs-viewport keeping the props and call imageDataCache.clear(); in loadDataset, but it didn't work. An error occurred after I changed the original index.umd.js for the recompiled one. And I think it may be because I'm using props.

Screenshot from 2021-10-20 11-35-26

Now I'm trying to get the StudyUID and SeriesUID the way you did, but I'm not sure in which file getViewportData is located and where I need to put the "let index = this.props.viewportIndex;" in the code.

I would really appreciate your help :)

ed-morais avatar Oct 26 '21 12:10 ed-morais

Hi @ed-morais ! I've not used props, I've used the localStorage workaround in the end.

In particular, I've put the "StudyInstanceUID" and "SeriesInstanceUID" into it (through the localStorage.setItem method ). You can do it basically everywhere: I personally do it in VTK3DToolbarButton, which is a customized version of VTKMPRToolbarButton.js for the 3D rendering, located in extensions/vtk/src/toolbarComponents.

Then, I'm able to retrieve them into Render3D.js (through the localStorage.getItem method). Afterwards, I delete these parameters, to keep the localStorage clean.

I don't know if it's the best workaround, but it works. I hope it'll work for you as well :)

NicholasDascanio avatar Oct 27 '21 07:10 NicholasDascanio

Hi @ed-morais Indeed, as @NicholasDascanio comments, the problem may be due to the fact that the IDs of the images are not recovered well. That's why I decided to put it in localStorage and as @NicholasDascanio comments you can use it whenever you want. I take advantage of and also use it to generate reference lines or other tools that require a stackID of images. Then with what controls that only the data that is visible on the screen is saved in localStorage and the rest is deleted ... so that the memory is not full would be valid. I know it's not the best option, but for now it works fine :)

ArturRod avatar Oct 27 '21 08:10 ArturRod

Thank you so much! @ArturRod @NicholasDascanio Everything is working just fine right now (:

ed-morais avatar Nov 04 '21 13:11 ed-morais

Thank you so much! @ArturRod @NicholasDascanio Everything is working just fine right now (:

@ArturRod @ed-morais @NicholasDascanio would you please share your build of OHIF with 3D features?

ranasrule avatar Nov 07 '21 14:11 ranasrule

Hi, @ranasrule Sorry but I can't upload a version with the changes publicly. Help how to implement 3D with code snippets and manuals, but I can't upload that version. If you have any questions, here it is explained how 3D can be activated, the other colleagues have achieved it 😊

ArturRod avatar Nov 11 '21 11:11 ArturRod

Would you be willing to do it on a commercial basis?

On Thu, Nov 11, 2021, 4:26 PM Arturo Rodrigo @.***> wrote:

Hi, @ranasrule https://github.com/ranasrule Sorry but I can't upload a version with the changes publicly. Help how to implement 3D with code snippets and manuals, but I can't upload that version. If you have any questions, here it is explained how 3D can be activated, the other colleagues have achieved it 😊

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/OHIF/Viewers/issues/2394#issuecomment-966225480, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABGKNOZHS5LOIWL62MOL2HLULOR7TANCNFSM44BTVXYA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

ranasrule avatar Nov 11 '21 11:11 ranasrule

Hello, @ArturRod @NicholasDascanio!

Now I'm trying to remove the buttons from the 3D toolbar. In fact, the code is working just fine removing the buttons from the 3D toolbar but the problem is: when I go back to the previous page or click the 2DMPR function the buttons removed in the 3D function are still removed. Something similar occurred to you guys, and do you have a clue on how to fix it?

When all buttons are visible: Screenshot from 2021-11-18 12-34-56 Clicking the 3D function: Screenshot from 2021-11-18 12-35-24 After clicking the "Sair do 3D" button: Screenshot from 2021-11-18 12-35-35 Some buttons missing in the 2DMPR as well: Screenshot from 2021-11-18 12-35-45 This is the code I'm using: Screenshot from 2021-07-20 11-40-20 I didn't get what lines 30 and 31 are doing and also there's an error in the console related to the line 31 Screenshot from 2021-11-18 13-25-04

Thank you for your time :)

ed-morais avatar Nov 18 '21 16:11 ed-morais

Hello, @ArturRod @NicholasDascanio!

Now I'm trying to remove the buttons from the 3D toolbar. In fact, the code is working just fine removing the buttons from the 3D toolbar but the problem is: when I go back to the previous page or click the 2DMPR function the buttons removed in the 3D function are still removed. Something similar occurred to you guys, and do you have a clue on how to fix it?

When all buttons are visible: Screenshot from 2021-11-18 12-34-56 Clicking the 3D function: Screenshot from 2021-11-18 12-35-24 After clicking the "Sair do 3D" button: Screenshot from 2021-11-18 12-35-35 Some buttons missing in the 2DMPR as well: Screenshot from 2021-11-18 12-35-45 This is the code I'm using: Screenshot from 2021-07-20 11-40-20 I didn't get what lines 30 and 31 are doing and also there's an error in the console related to the line 31 Screenshot from 2021-11-18 13-25-04

Thank you for your time :)

@ed-morais would you please share your build of OHIF with 3D features? I'm also willing to pay for it if you like.

ranasrule avatar Nov 18 '21 20:11 ranasrule

Hi @ed-morais and @ranasrule Indeed, the problem I see is that the previous state is not returned to the buttons. You have to make sure that when you exit you call this method: static buttons (activate) { being activate true; Since that's how it rebuilds the buttons. In case it does not detect let view = document.getElementsByClassName ( 'viewport-drop-target viewport-container active' ); You will have to check why you do not select the activated viewport. You must control the possible errors that the 3D may have, since if there is an error when generating it, you will have to call this method of buttons, because it will automatically exit the 3D. (This as a recommendation)

ArturRod avatar Nov 19 '21 08:11 ArturRod

hello @ArturRod

i cant found Render3D.js

halitince avatar Nov 25 '21 08:11 halitince

Hi @halitince The Render3D class is the name that I have given it, the original is this -> https://github.com/OHIF/react-vtkjs-viewport/blob/master/examples/VTKVolumeRenderingExample.js

ArturRod avatar Nov 25 '21 09:11 ArturRod

Hi @ArturRod Would you contact me. I have a few question.

https://www.linkedin.com/in/halit-ince-aa809266/

halitince avatar Nov 25 '21 10:11 halitince