Repository: scikit-hep/particle

Issue:
spin of SUSY partners
While checking out the package, I found that some of the SUSY partners of the SM quarks are assigned a spin value of 2 (that in the 2s+1 scheme represents a spin-1/2 particle). For instance, the left-handed partner of up-quark `suL`, which is usually represented by id 1000002, is assigned a value of 2 for its `j_spin`. 
But the squarks are bosons, so their spins are integral and should be 1 or 3.

Am I missing something? Please let me know if this is a known (and intentional) issue.

Comments:

Patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3856a5d..46130ae 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -24,13 +24,13 @@ repos:
   - id: black-jupyter
 
 - repo: https://github.com/charliermarsh/ruff-pre-commit
-  rev: "v0.0.265"
+  rev: "v0.0.269"
   hooks:
     - id: ruff
       args: ["--fix", "--show-fixes"]
 
 - repo: https://github.com/pre-commit/mirrors-mypy
-  rev: v1.2.0
+  rev: v1.3.0
   hooks:
   - id: mypy
     files: src
diff --git a/src/particle/pdgid/functions.py b/src/particle/pdgid/functions.py
index 7208195..8d52ddb 100644
--- a/src/particle/pdgid/functions.py
+++ b/src/particle/pdgid/functions.py
@@ -703,17 +703,27 @@ def j_spin(pdgid: PDGID_TYPE) -> int | None:
         return None
     if _fundamental_id(pdgid) > 0:
         fund = _fundamental_id(pdgid)
-        if 0 < fund < 7:  # 4th generation quarks not dealt with !
-            return 2
-        if (
-            fund == 9
-        ):  # Alternative ID for the gluon in codes for glueballs to allow a notation in close analogy with that of hadrons
-            return 3
-        if 10 < fund < 17:  # 4th generation leptons not dealt with !
-            return 2
-        if 20 < fund < 25:
-            return 3
-        return None
+        if is_SUSY(pdgid):  # susy particles
+            if 0 < fund < 17:
+                return 1
+            if fund == 21:
+                return 2
+            if 22 <= fund < 38:
+                return 2
+            if fund == 39:
+                return 4
+        else:  # other particles
+            if 0 < fund < 7:  # 4th generation quarks not dealt with !
+                return 2
+            if (
+                fund == 9
+            ):  # Alternative ID for the gluon in codes for glueballs to allow a notation in close analogy with that of hadrons
+                return 3
+            if 10 < fund < 17:  # 4th generation leptons not dealt with !
+                return 2
+            if 20 < fund < 25:
+                return 3
+            return None
     if abs(int(pdgid)) in {1000000010, 1000010010}:  # neutron, proton
         return 2
     if _extra_bits(pdgid) > 0:


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
index 91fe687..95aa0d5 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -112,6 +112,8 @@ class PDGIDsEnum(IntEnum):
     Gravitino = 1000039
     STildeL = 1000003
     CTildeR = 2000004
+    Neutralino_1 = 1000022
+    Chargino_1 = 1000024
     # R-hadrons
     R0_1000017 = 1000017
     RPlus_TTildeDbar = 1000612
diff --git a/tests/pdgid/test_functions.py b/tests/pdgid/test_functions.py
index 8992ef3..e4d850c 100644
--- a/tests/pdgid/test_functions.py
+++ b/tests/pdgid/test_functions.py
@@ -431,6 +431,8 @@ def test_is_SUSY(PDGIDs):
         PDGIDs.Gravitino,
         PDGIDs.STildeL,
         PDGIDs.CTildeR,
+        PDGIDs.Chargino_1,
+        PDGIDs.Neutralino_1,
         PDGIDs.R0_1000017,
     )
     _non_susy = [pid for pid in PDGIDs if pid not in _susy]
@@ -611,6 +613,7 @@ def test_has_fundamental_anti(PDGIDs):
         PDGIDs.AntiElectronStar,
         PDGIDs.STildeL,
         PDGIDs.CTildeR,
+        PDGIDs.Chargino_1,
         PDGIDs.AntiCHadron,
         PDGIDs.R0_1000017,
     )
@@ -767,7 +770,8 @@ def test_JSL_badly_known_mesons(PDGIDs):
 
 def test_J_non_mesons(PDGIDs):
     # TODO:  test special particles, supersymmetric particles, R-hadrons, di-quarks, nuclei and pentaquarks
-    _J_eq_0 = ()
+    _J_eq_0 = (PDGIDs.STildeL, PDGIDs.CTildeR)
+
     _J_eq_1 = (
         PDGIDs.Gluon,
         PDGIDs.Photon,
@@ -803,10 +807,11 @@ def test_J_non_mesons(PDGIDs):
         PDGIDs.LcPlus,
         PDGIDs.Lb,
         PDGIDs.LtPlus,
-        PDGIDs.STildeL,
-        PDGIDs.CTildeR,
+        PDGIDs.Gluino,
+        PDGIDs.Neutralino_1,
+        PDGIDs.Chargino_1,
     )
-    _J_eq_3over2 = (PDGIDs.OmegaMinus,)
+    _J_eq_3over2 = (PDGIDs.OmegaMinus, PDGIDs.Gravitino)
     _invalid_pdgids = (PDGIDs.Invalid1, PDGIDs.Invalid2)
     # cases not dealt with in the code, where None is returned
     _J_eq_None = (PDGIDs.TauPrime, PDGIDs.BPrimeQuark, PDGIDs.TPrimeQuark)