materialscloud-org / tools-phonon-dispersion

Visualize interactively phonon dispersions and their eigenvectors
https://www.materialscloud.org/work/tools/interactivephonon
Other
11 stars 4 forks source link

High-resolution screenshots #6

Open giovannipizzi opened 4 years ago

giovannipizzi commented 4 years ago

A requested feature is to have the possibility to get high-resolution screenshot of the displacements. This could be implemented as a button.

For now, I report here a workaround to get such images (that can also be useful later for the implementation).

  1. Open the tool with this direct URL. Then, load your structure and go to the page of the visualisation.

  2. Open the browser Developers Tools. For instance, in Safari you first have to activate the menu (via Safari->Preferences->Advanced->Show Develop menu in menu bar), then select from the menu Develop->Show Javascript Console). In Chrome, instead, you can open the menu (three dots on the top-right of your browser), then More Tools->Developer Tools, and then choose the tab "Console" if not already selected)

  3. In the Console, copy-paste this code to increase the number of segments to draw spheres from the default of 12 to 100:

    v.sphereLat = 100;
    v.sphereLon = 100;
    v.bondSegments = 30;
    v.updatelocal(); 
    • Remember to press Enter at the end
    • Note: v is the global variable of type VibCrystal that controls the 3D visualiser
    • Note: the number of segments is currently hardcoded and a code change is needed to allow to update it. It's using Three.JS default for radialSegments (8) and, to update, will need to pass it as another variable e.g. here
  4. Copy-paste this code in the console (adapted from here:

    function takeScreenshot( vibCrystal, width, height ) {
    
      // set camera and renderer to desired screenshot dimension
      vibCrystal.camera.aspect = width / height;
      vibCrystal.camera.updateProjectionMatrix();
      vibCrystal.renderer.setSize(  width, height );
    
      vibCrystal.renderer.render( vibCrystal.scene, vibCrystal.camera, null, false );
    
      const dataURL = vibCrystal.renderer.domElement.toDataURL( 'image/png' );
    
      const iframe = `
        <iframe
          src="${dataURL}"
          frameborder="0"
          style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;"
          allowfullscreen>
        </iframe>`
    
      const win = window.open();
      window.document.write( iframe );
      window.document.close();
    }
  5. Set the various parameters (angle, vector length, amplitude, ...). Only at the end, pause the animation and possibly fine-tune the angle.

  6. Finally, to take a screenshot, copy-paste the following code: takeScreenshot(v, 2048, 1024);

    • v as above is the VibCrystal object, the other two are the image resolution
    • The webpage will be replaced with a high-resolution PNG
    • Just right-click and save it
    • Note: if you have a high-resolution (e.g. Retina) display, you will get an image that is possibly 1.5x or 2x larger (e.g. in the example above on a recent MacBook I get a huge 4096x2048 image)
    • In my experience, the open window with the image can slow down your computer, close it when you are done
  7. Close/discard the Tab (not ideal, but this is for now just a workaround...)

giovannipizzi commented 3 years ago

@elsapassaro would it be possible to add an "export PNG" button that calls something similar to the code above? (but avoiding that you get a iframe hiding everything, rather just letting the browser download the file).

giovannipizzi commented 5 months ago

Also Chiara C. requested the option to download a (high-res) movie. This is not possible yet, but code was available in the original widget here (https://henriquemiranda.github.io/phononwebsite/phonon.html) [button "Export movie (GIF)"], so there is code to do it. The code should be this, but I am not sure how to adapt it to the current phonon visualiser.

giovannipizzi commented 5 months ago

as a follow up, I tried this function:

function capturevideo(vibCrystal) {
    let format = 'gif';
    let options = { format: format,
                    //../../user_static/js/gif.js
                    workersPath: '../../user_static/js/',
                    verbose: true,
                    frameMax: vibCrystal.fps,
                    end: vibCrystal.captureend.bind(vibCrystal, format),
                    framerate: vibCrystal.fps,
                    onProgress: function( p ) { console.log('GIF progress: ' + ( p * 100 ) + '%'); }
                  }

    vibCrystal.capturer = new CCapture( options );
    vibCrystal.capturer.start();
}

with the idea that then, one could run capturevideo(v)

However, this does not work. I thought it was because some files (user_static/js/gif.js.map, user_static/js/gif.worker.js, user_static/js/gif.worker.js.map) are missing form the js folder, but I tried locally and this is not enough to make it work (probably still these files need to be there, according to the CCapture docs.

I write this here because maybe it's just a small additional step and it works, but I don't manage to check it now.