Repository: qutip/qutip

Issue:
Husimi Q and Wigner spin functions don't give correct results
The Husimi Q function for spins gives incorrect output for the states |J, -J>, for all J.
Generating a spin-coherent state with some theta and phi, and then calculating the Husimi Q function for the same theta and phi should always give 1/pi, but this value tends toward 0 the closer to the bottom of the Bloch sphere you go.

A similar problem exists for the spin wigner function, where a the spin-coherent state |J, -J> has some negativity in the wigner function.


Discussion:
Could you please post a code snippet to reproduce this? I am working with the Husimi Q and Wigner functions now and could look into it more. 

Resolving patch:
diff --git a/qutip/wigner.py b/qutip/wigner.py
--- a/qutip/wigner.py
+++ b/qutip/wigner.py
@@ -561,10 +561,10 @@ def qfunc(state, xvec, yvec, g=sqrt(2)):
         A state vector or density matrix.
 
     xvec : array_like
-        x-coordinates at which to calculate the Wigner function.
+        x-coordinates at which to calculate the Husimi-Q function.
 
     yvec : array_like
-        y-coordinates at which to calculate the Wigner function.
+        y-coordinates at which to calculate the Husimi-Q function.
 
     g : float
         Scaling factor for `a = 0.5 * g * (x + iy)`, default `g = sqrt(2)`.
@@ -637,14 +637,14 @@ def spin_q_function(rho, theta, phi):
     state : qobj
         A state vector or density matrix for a spin-j quantum system.
     theta : array_like
-        theta-coordinates at which to calculate the Q function.
+        Polar angle at which to calculate the Husimi-Q function.
     phi : array_like
-        phi-coordinates at which to calculate the Q function.
+        Azimuthal angle at which to calculate the Husimi-Q function.
 
     Returns
     -------
     Q, THETA, PHI : 2d-array
-        Values representing the spin Q function at the values specified
+        Values representing the spin Husimi Q function at the values specified
         by THETA and PHI.
 
     """
@@ -656,32 +656,31 @@ def spin_q_function(rho, theta, phi):
         rho = ket2dm(rho)
 
     J = rho.shape[0]
-    j = int((J - 1) / 2)
+    j = (J - 1) / 2
 
     THETA, PHI = meshgrid(theta, phi)
 
     Q = np.zeros_like(THETA, dtype=complex)
 
-    for m1 in range(-j, j+1):
+    for m1 in arange(-j, j+1):
 
         Q += binom(2*j, j+m1) * cos(THETA/2) ** (2*(j-m1)) * sin(THETA/2) ** (2*(j+m1)) * \
-            rho.data[int(j-m1), int(j-m1)]
+             rho.data[int(j-m1), int(j-m1)]
 
-        for m2 in range(m1+1, j+1):
+        for m2 in arange(m1+1, j+1):
 
             Q += (sqrt(binom(2*j, j+m1)) * sqrt(binom(2*j, j+m2)) *
                   cos(THETA/2) ** (2*j-m1-m2) * sin(THETA/2) ** (2*j+m1+m2)) * \
-                (exp(1j * (m2-m1) * PHI) * rho.data[int(j-m1), int(j-m2)] +
-                 exp(1j * (m1-m2) * PHI) * rho.data[int(j-m2), int(j-m1)])
-
-    return Q.real, THETA, PHI
+                  (exp(1j * (m2-m1) * PHI) * rho.data[int(j-m1), int(j-m2)] +
+                   exp(1j * (m1-m2) * PHI) * rho.data[int(j-m2), int(j-m1)])
 
+    return Q.real/pi, THETA, PHI
 
 def _rho_kq(rho, j, k, q):
     v = 0j
 
-    for m1 in range(-j, j+1):
-        for m2 in range(-j, j+1):
+    for m1 in arange(-j, j+1):
+        for m2 in arange(-j, j+1):
             v += (-1)**(j - m1 - q) * clebsch(j, j, k, m1, -m2,
                                               q) * rho.data[m1 + j, m2 + j]
 
@@ -689,16 +688,17 @@ def _rho_kq(rho, j, k, q):
 
 
 def spin_wigner(rho, theta, phi):
-    """Wigner function for spins on the Bloch sphere.
+    """Wigner function for a spin-j system on the 2-sphere of radius j
+       (for j = 1/2 this is the Bloch sphere).
 
     Parameters
     ----------
     state : qobj
         A state vector or density matrix for a spin-j quantum system.
     theta : array_like
-        theta-coordinates at which to calculate the Q function.
+        Polar angle at which to calculate the W function.
     phi : array_like
-        phi-coordinates at which to calculate the Q function.
+        Azimuthal angle at which to calculate the W function.
 
     Returns
     -------
@@ -719,14 +719,15 @@ def spin_wigner(rho, theta, phi):
         rho = ket2dm(rho)
 
     J = rho.shape[0]
-    j = int((J - 1) / 2)
+    j = (J - 1) / 2
 
     THETA, PHI = meshgrid(theta, phi)
 
     W = np.zeros_like(THETA, dtype=complex)
 
     for k in range(int(2 * j)+1):
-        for q in range(-k, k+1):
+        for q in arange(-k, k+1):
+            # sph_harm takes azimuthal angle then polar angle as arguments
             W += _rho_kq(rho, j, k, q) * sph_harm(q, k, PHI, THETA)
 
     return W, THETA, PHI


Test patch: