Metadata-Version: 2.4
Name: psyspin
Version: 1.1.2
Summary: Generalized Ising / Blume-Capel / Blume-Emery-Griffiths inference and sampling for ordinal questionnaire data.
Author: Miguel Ibañez-Berganza
Author-email: Arianna Armanetti <arianna.armanetti@imtlucca.it>
License: MIT License
        
        Copyright (c) 2026 Miguel Ibañez-Berganza & Arianna Armanetti
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in
        all copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        THE SOFTWARE.
        
        ------------------------------------------------------------------------------
        Citation request (not legally binding under the MIT License above)
        ------------------------------------------------------------------------------
        
        If you use this software, or any derivative of it, in academic work, you are
        kindly requested to:
        
          1. cite the accompanying paper:
        
               Armanetti, A. et al.,
               "Generalized Ising models for ordinal questionnaire data"
               (in preparation, 2026).
        
          2. cite this software:
        
               Ibañez-Berganza, M. & Armanetti, A., "psyspin: Generalized Ising / Blume-Capel / Blume-Emery-Griffiths inference for ordinal questionnaires data," version 0.1.0,
               1.     https://github.com/armanetti/psyspin
        
          3. contact the author at arianna.armanetti@imtlucca.it to discuss usage,
             collaboration, or questions regarding the package or the paper.
        
        These requests are made on top of the permissions granted by the MIT
        License above; they do not modify or restrict those permissions.
        
Project-URL: Homepage, https://github.com/armanetti/psyspin
Project-URL: Repository, https://github.com/armanetti/psyspin
Project-URL: Issues, https://github.com/armanetti/psyspin/issues
Keywords: ising,blume-capel,blume-emery-griffiths,BEG,inverse problem,pseudo-likelihood,persistent contrastive divergence,questionnaire,ordinal data,psychometrics
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.22
Requires-Dist: scipy>=1.10
Requires-Dist: scikit-learn>=1.1
Requires-Dist: pandas>=1.5
Requires-Dist: matplotlib>=3.6
Requires-Dist: tqdm>=4.64
Requires-Dist: statsmodels>=0.13
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: jupyter; extra == "dev"
Requires-Dist: ipykernel; extra == "dev"
Requires-Dist: openpyxl; extra == "dev"
Dynamic: license-file

# psyspin

**Generalized Ising / Blume–Capel / Blume–Emery–Griffiths inference and
sampling for ordinal questionnaire data.**

`psyspin` fits energy-based models with discrete spin variables
`x ∈ {-(Q-1)/2, ..., (Q-1)/2}` (Q odd) or `{-(Q-1), -(Q-1)+2, ..., Q-1}` (Q even)
to ordinal datasets — for instance Likert-scale questionnaire responses. The
package provides three model families of increasing expressive power:

| model | Hamiltonian | comment |
|------|-------------|---------|
| **Ising** | `H(x) = -h·x - ½ xᵀ J x`, `diag(J)=0` | minimal pairwise model |
| **Blume–Capel (BC)** | `H(x) = -h·x - ½ xᵀ J x`, `diag(J)` free | adds a per-site anisotropy on `x_i²` |
| **Blume–Emery–Griffiths (BEG)** | `H(x) = -h·x - ½ xᵀ J x - ½ ∑_{i≠j} K_{ij} x_i² x_j²` | adds a biquadratic coupling, captures variance correlations |

For each model the package offers two inference strategies:

- **Pseudo-likelihood** (PL): closed-form gradient, L-BFGS-B optimization
  (`generalizedIsing_inference`, `generalizedBC_inference`,
  `generalizedBEG_inference`).
- **Persistent Contrastive Divergence** (PCD): persistent Gibbs chains, Adam
  gradient updates (`generalizedIsing_inferencePCD`,
  `generalizedBC_inferencePCD`, `generalizedBEG_inferencePCD`).

It also includes optimized random-sequential Gibbs samplers (`mcmc_ising`,
`mcmc_beg`), null models for comparison (Gaussian, Gaussian copula,
categorical-independent, GMM spectral cleaning), and plotting helpers used to
build the figures of the accompanying paper.

---

## Installation

The package targets Python ≥ 3.10 (uses structural `match`/`case`).

From PyPI:

```bash
pip install psyspin
```

For development (editable install from source):

```bash
git clone https://github.com/armanetti/psyspin.git
cd psyspin
pip install -e .
```

The optional dev extras add Jupyter and openpyxl (the latter is needed only by
the DASS data loader):

```bash
pip install -e .[dev]
```

### Dependencies

`numpy`, `scipy`, `scikit-learn`, `pandas`, `matplotlib`, `tqdm`,
`statsmodels`.

---

## Quickstart

```python
import numpy as np
from psyspin import (
    gaugefixing_data,
    generalizedBEG_inference,
    generalizedBEG_inferencePCD,
    mcmc_beg,
    sample_configurations_likelearning,
)

# X is your raw integer-coded Likert-scale data, shape (N_subjects, M_items),
# with values in {1, ..., Q}.
Q = 5
X_gf = gaugefixing_data(X, Q)            # centre the spin alphabet to zero sum

# 1) Fast warm-start with pseudo-likelihood
pl = generalizedBEG_inference(Q=Q, l2_lambda=1e-2)
J_pl, h_pl, K_pl = pl.fit(X_gf)

# 2) Refine with persistent Contrastive Divergence
pcd = generalizedBEG_inferencePCD(Q=Q, l2_lambda=0.)
J, h, K = pcd.naif_fit_euler(
    X_gf,
    niterations=120, learning_rate=1e-4,
    ncopies=100, tau_PCD=100, tau_therm=100,
    iicc='given', J0=J_pl, h0=h_pl, K0=K_pl,
)

# 3) Sample from the inferred model
sampler = mcmc_beg(-J, -h, -K, Q=Q)        # note the sign convention
sampler.thermalize(betai=0., betaf=1., nsweeps=1000, iicc='random', nb_chunks=100)
sim = sample_configurations_likelearning(
    sampler, X=X_gf, states=pcd.states,
    N_configurations=10_000, n_intersample_sweeps=1000, reset='emp',
)
configs = sim['configurations']           # synthetic dataset, shape (10_000, M)
```

`tutorials/tutorial.ipynb` walks through the full workflow on a single
dataset, with diagnostic plots.

---

## Module map

| submodule | what it provides |
|-----------|-----------------|
| `psyspin.gauge` | `bins`, `possible_states`, `gaugefixing_data`, `gaugefixing_data_float` |
| `psyspin.inference` | `generalizedIsing_inference`, `generalizedBC_inference`, `generalizedBEG_inference` (pseudo-likelihood) |
| `psyspin.inference_pcd` | `generalizedIsing_inferencePCD`, `generalizedBC_inferencePCD`, `generalizedBEG_inferencePCD`, `Adam` |
| `psyspin.mcmc` | `gibbssampling_ising`, `gibbssampling_BC`, `gibbssampling_BC_pseudolikelihood`, `gibbssampling_beg`, `gibbssampling_beg_pseudolikelihood`, `mcmc_ising`, `mcmc_beg`, energy / magnetization helpers |
| `psyspin.sampling` | `sample_configurations`, `sample_configurations_likelearning` |
| `psyspin.jackknife` | `JKerror` — block-Jackknife integrated autocorrelation time |
| `psyspin.histograms` | `wilson_score_interval`, `agresti_coull_interval`, `bootstrap_histogram` |
| `psyspin.outliers` | `outlier_analysis_means`, `outlier_analysis_factormeans` |
| `psyspin.nullmodels` | `catind_model`, `null_gaussian_copula`, `model_gaussdisc`, `newmanmodularity`, `modularity_general`, `modularity_GMM`, `mixture_chisquared_characteristicfunction`, ... |
| `psyspin.data` | `load_data`, `discretize`, `reshuffle`, `compare2matrices`, `plot2matrices`, `remove_diagonal` |
| `psyspin.figures` | `plot_losses`, `plot_moment_matching_*`, `plot_item_histogram`, `plot_E2d_histogram_*`, `plot_mahalanobis_*`, `plot_pc_histogram_maxent`, `plot_correlation_time_analysis`, default `DEFAULT_COLORS` / `DEFAULT_CFG` |

The most commonly used names are re-exported at the package root for convenience
(e.g. `from psyspin import generalizedBEG_inferencePCD, mcmc_beg`).

---

## Sign conventions

A quick reminder, since it bites everyone the first time:

- The **inference** classes parametrize the energy with `-h·x` and `-½ xᵀ J x`
  (and `-½ xᵀ K x²` for BEG). The `J_fit`, `h_fit`, `K_fit` returned by `fit()`
  refer to that energy.
- The **MCMC** wrappers `mcmc_ising` and `mcmc_beg` take `J`, `h`, (`K`) as
  *positive-energy* coefficients: `E = ½ σᵀ J σ + h·σ`. So when you sample
  from a fitted model, pass `-J_fit`, `-h_fit`, `-K_fit` to the MCMC
  constructor (see the quickstart above).

---

## Reproducing the paper

The original repository ships the per-dataset scripts that produced every
figure in the paper. They are kept as reference under
`inverse_spinmodel/learning_cd_3rdattempt/`. The tutorial notebook is a
compact substitute for the most common workflow; it does not run every
combination of hyperparameters/resets/models that the paper explored.

---

## Citation

If you use `psyspin` in academic work, please cite **both** the paper and the
software:

```bibtex
@unpublished{Armanetti2026_psyspin_paper,
  author    = {Armanetti, Arianna and Cecchetti, Luca and Sarti, Paolo and Garlaschelli, Diego and Ibañez-Berganzam Miguel},
  title     = {Generalized Ising models for ordinal questionnaire data},
  note      = {In preparation},
  year      = {2026},
}

@software{Armanetti2026_psyspin_pkg,
  author    = {Ibañez-Berganza, Miguel and Armanetti, Arianna},
  title     = {{psyspin}: Generalized Ising / Blume--Capel /
                Blume--Emery--Griffiths inference for ordinal questionnaire data},
  year      = {2026},
  version   = {1.1.1},
  url       = {https://github.com/armanetti/psyspin},
  doi       = {10.5281/zenodo.XXXXXXX},
}
```

Citation details for the paper will be updated once it is published. The DOI
above will be filled in automatically by Zenodo the first time a GitHub
release is archived (see the DOI section of the setup guide) — replace
`XXXXXXX` once you have the real record number, or better, point people to
the "concept DOI" that always resolves to the latest version.

---

## License & contact

Released under the [MIT License](LICENSE), with an additional **citation
request** and a **friendly note**: please drop me a line at
<arianna.armanetti@imtlucca.it> if you use this package — I would be glad to hear about your application, answer questions, or discuss collaborations.

The citation request is not legally binding under MIT, but it matters to me
that the work is credited.
