Using bioformats with python and virtualenvs

Bioformats

Problem

Python-bioformats is a python wrapper for bioformats. Useage is explained in the docs and seems relatively straightforward.

import javabridge
import bioformats
javabridge.start_vm(class_path=bioformats.JARS)

Note that you also typically have to tell javabridge where the bioformats jars are like so:

other_jars = javabridge.JARS+bioformats.JARS+['/Users/Nick/bin/bioformats_package.jar']

This adds the default jars, the bioformats jars and my copy of the bioformats package to the search path.
The issue I had was when I try to import javabridge I get the following error:

Failed to run /usr/libexec/java_home, defaulting to best guess for Java
Traceback (most recent call last):
  File "/Users/Nick/.virtualenvs/cars/lib/python3.6/site-packages/javabridge/locate.py", line 45, in find_javahome
    os.path.join(os.path.dirname(path), "Libraries"),
  File "/Users/Nick/.virtualenvs/cars/bin/../lib/python3.6/posixpath.py", line 92, in join
    genericpath._check_arg_types('join', a, *p)
  File "/Users/Nick/.virtualenvs/cars/bin/../lib/python3.6/genericpath.py", line 151, in _check_arg_types
    raise TypeError("Can't mix strings and bytes in path components") from None
TypeError: Can't mix strings and bytes in path components

Weird. And no clear explanation on the internet. I did find one post explaining that OSX default java path is /usr/libexec/java_home, which is not necessarily where java is installed.
When I checked my path on Bash:

which java

I got my typical bin. This post explained that you need to set the JAVA_HOME variable. A quick inspection of the javabridge/locate.py (as indicated in the error) shows the following check:

# javabridge/locate.py
def find_javahome():
     """Find JAVA_HOME if it doesn't exist"""
     if 'JAVA_HOME' in os.environ:
         return os.environ['JAVA_HOME']
     elif is_mac:
         # Use the "java_home" executable to find the location
...

Simple enough, just set the environmental variable in ~/.bash_profile

echo JAVA_HOME=/usr/bin/java >> ~/.bash_profile

now when I echo JAVA_HOME

echo $JAVA_HOME

Great. Unfortunately, when I started up an ipython shell in my virtualenvironment and check my environmental variables (print(os.environ)), JAVA_HOME is nowhere to be found.

Why?

When working in a virtualenv, not all of your system path variables are translated over.
A fix for this is explained in the virtualenvwrapper docs, you simply add a Hook script.
In my case I added the following line to my postactivate script:

JAVA_HOME=/usr/bin/java
export JAVA_HOME

Now whenever I activate my virtualenv and check my path with os.environ, I see my variable exists. Now I can use python-bioformats.