To help with understanding the volume rendering orientation issues, here's a self-contained test that I've been using.

This puts a single cube on +x, two cubes on +y, and three cubes on +z.  North is set to +z.

The save_annotated image has the right orientation and handedness.

The write_png image is upside down.

I found this data very helpful in understanding and testing orientations.

Mike

------

import pylab
import yt
import numpy as np

N = 128

xmin = ymin = zmin = -1.0
xmax = ymax = zmax = 1.0

arr = np.zeros((N,N,N), dtype=np.float64)
arr[:,:,:] = 1.e-4

bbox = np.array([ [xmin, xmax], [ymin, ymax], [zmin, zmax] ])

# coordinates -- in the notation data[i, j, k]
x = (np.arange(N) + 0.5)*(xmax - xmin)/N + xmin
y = (np.arange(N) + 0.5)*(ymax - ymin)/N + ymin
z = (np.arange(N) + 0.5)*(zmax - zmin)/N + zmin

x3d, y3d, z3d = np.meshgrid(x, y, z, indexing="ij")

# single cube on +x
xc = 0.75
dx = 0.05
idx = np.logical_and(np.logical_and(x3d > xc-dx, x3d < xc+dx),
np.logical_and(np.logical_and(y3d > -dx, y3d < dx),
np.logical_and(z3d > -dx, z3d < dx)) )

arr[idx] = 1.0

# two cubes on +y
dy = 0.05
for yc in [0.65, 0.85]:

idx = np.logical_and(np.logical_and(y3d > yc-dy, y3d < yc+dy),
np.logical_and(np.logical_and(x3d > -dy, x3d < dy),
np.logical_and(z3d > -dy, z3d < dy)) )

arr[idx] = 0.8

# three cubes on +z
dz = 0.05
for zc in [0.5, 0.7, 0.9]:

idx = np.logical_and(np.logical_and(z3d > zc-dz, z3d < zc+dz),
np.logical_and(np.logical_and(x3d > -dz, x3d < dz),
np.logical_and(y3d > -dz, y3d < dz)) )

arr[idx] = 0.6

data = dict(Density = arr)

import yt.visualization.volume_rendering.api as vr

c = np.array([0, 0, 0])
L = np.array([1.0, 1.0, 1.0])
W = 2.0*ds.domain_width
N = 720

north = np.array([0, 0, 1])

tf = vr.ColorTransferFunction((0.1,1.0))
tf.sample_colormap(1.0, 0.05, colormap="coolwarm")
tf.sample_colormap(0.8, 0.05, colormap="coolwarm")
tf.sample_colormap(0.6, 0.05, colormap="coolwarm")

cam = vr.Camera(c, L, W, N, transfer_function=tf,
north_vector = north,
ds=ds, fields=[('gas', 'Density')],
log_fields=[False])

im = cam.snapshot()
nim = cam.draw_domain(im)

nim.write_png("test.png")

cam.save_annotated("test_annotated.png", nim)

------

--
Michael Zingale
Associate Professor

Dept. of Physics & Astronomy • Stony Brook University • Stony Brook, NY 11794-3800
phone:  631-632-8225