Thursday, 14 July 2016

Even more molecular depiction in Vim

Previous posts focused on popping up an ASCII depiction in Vim, but what doing something with the PNG output from Open Babel? Is there any way this can be viewed from Vim? Aged readers may remember a previous blog post of mine that looked into PNG to ASCII conversion, and that would be one approach.

A more direct approach is to use Vim's built-in capabilities to view bitmap files. Well, to be exact, a specific type of old-skool bitmap called an XPM. This has a very simple format and so Vim can show the entire contents of the file and use syntax-highlighting to visualise it. The alleged use for this is to enable people to directly edit bitmaps - that's right, someone out there is using Vim as a bitmap editor.

The only problem is generating the XPM file in the first place. We could probably do this directly from Open Babel as the format is fairly simple (e.g. as an option to the PNG writer) but in a certain light that just might ("just might", mind you) be viewed as feature creep. So instead, we can use ImageMagick's convert to do the job (which is available cross-platform). As before the required script is shown below.

Once I got it working I got to thinking, "well, that's a 79x79 bitmap it's showing, which is pretty small but what if I reduce the font size? aha! - then I can show an arbitrary sized bitmap and show much better detail". At which point I realised that in any environment where I can change the font size in Vim, I should probably just pop up an image viewer to display the PNG (left as an exercise for the reader).

In the end, are these depictions better than the ASCII ones? Meh, probably not - which I think was one of the conclusions also from my previous foray into PNG to ASCII conversion. Oh well.

noremap <silent> <leader>d :call SmiToPng(77)<CR>
function! SmiToPng(width)
  let smiles = expand("<cWORD>")
  " Strip quotation marks and commas
  let smiles = substitute(smiles, "[\"',]", "", "g")
  " Handle escaped backslashes, e.g. in C++ strings
  let smiles = substitute(smiles, "\\\\", "\\", "g")

  botright new
  setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
  let fname = tempname().'.png'
  call system('obabel -:'.smiles. ' -O '.fname.' -d -xm -xp '. a:width)
  execute '$read ! "C:\Program Files (x86)\ImageMagick-6.5.8-Q16\convert.exe" '.fname.' xpm:-'
  setlocal filetype=xpm
  execute "normal! ggd/pixels\<cr>dd"
  silent! g/\v^"(\S)\1+",?/d
  execute "normal! Gdd"
  setlocal nomodifiable

No comments: