{
 "cranqe_package": "qe-ena",
 "files": {
  "qe_ena-0.1.5-py3-none-any.whl": {
   "published": "2026-10-06",
   "sha256": "b054cf130b2811286327a2087051306cd505dbbf5e145e79bda3f3c7539c16ea",
   "size": 17969,
   "version": "0.1.5"
  },
  "qe_ena-0.1.5.tar.gz": {
   "published": "2026-10-06",
   "sha256": "4fc5fc6836f9eabc533b7bef23cf8ba194f1c38ae66086d6e383b04768478cf9",
   "size": 23842,
   "version": "0.1.5"
  },
  "qe_ena-0.1.6-cp311-cp311-macosx_26_0_arm64.whl": {
   "published": "2026-10-09",
   "sha256": "8cb5d566e6c5ae4849f2b0f25443baa2800f2455aa80072f1761f8a7016840de",
   "size": 164400,
   "version": "0.1.6"
  },
  "qe_ena-0.1.6-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl": {
   "published": "2026-10-09",
   "sha256": "152e180d9c4c0a8962ba4b0857a6d62b021dcbb85e8971761ef870ca555fc490",
   "size": 12142231,
   "version": "0.1.6"
  },
  "qe_ena-0.1.6-cp311-cp311-win_amd64.whl": {
   "published": "2026-10-10",
   "sha256": "81ce501feaa33693e8089ec269e76706318a67abab9098fc662c50a0dce38aaf",
   "size": 5894002,
   "version": "0.1.6"
  },
  "qe_ena-0.1.6-cp312-cp312-macosx_26_0_arm64.whl": {
   "published": "2026-10-09",
   "sha256": "4471a2a79423e82eb103b45bb4e742bdf44cc3964246ebdcbcf72579c0cac863",
   "size": 163689,
   "version": "0.1.6"
  },
  "qe_ena-0.1.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl": {
   "published": "2026-10-09",
   "sha256": "b3b8c9b9d39106494bb2b4b3ee90b7426c56aad8af8accb3c9c310127e4b3190",
   "size": 12141871,
   "version": "0.1.6"
  },
  "qe_ena-0.1.6-cp312-cp312-win_amd64.whl": {
   "published": "2026-10-10",
   "sha256": "0c7a2de41e650d95e96687f23c732ef3ea936b18d1b6dc4216eeca4e8a65ef50",
   "size": 5894250,
   "version": "0.1.6"
  },
  "qe_ena-0.1.6-cp313-cp313-macosx_26_0_arm64.whl": {
   "published": "2026-10-09",
   "sha256": "aa7967f545465c8d8bbbd21ce926cc50a00d19375d3338ee3fdfdfa72f087769",
   "size": 163701,
   "version": "0.1.6"
  },
  "qe_ena-0.1.6-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl": {
   "published": "2026-10-09",
   "sha256": "39f246a85c8385f273f6817372e46976bd9cb50ae7a1cdca71fc9e086efd62b0",
   "size": 12141800,
   "version": "0.1.6"
  },
  "qe_ena-0.1.6-cp313-cp313-win_amd64.whl": {
   "published": "2026-10-10",
   "sha256": "f950c8c87954c7294dec88312832d56b8e03587b1674112e8c23a26febce9165",
   "size": 5894159,
   "version": "0.1.6"
  },
  "qe_ena-0.1.6.9004-cp311-cp311-macosx_26_0_arm64.whl": {
   "published": "2026-10-09",
   "sha256": "a8ea9956f279fc6926fe655699fa17e3deb031c5dc8a4997abd7faa9f5f86610",
   "size": 164440,
   "version": "0.1.6.9004"
  },
  "qe_ena-0.1.6.9004-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl": {
   "published": "2026-10-09",
   "sha256": "85e9d088735b4c32b66e6f33fe027328218204da0c5c080cbd85c97ee8265bac",
   "size": 12142308,
   "version": "0.1.6.9004"
  },
  "qe_ena-0.1.6.9004-cp311-cp311-win_amd64.whl": {
   "published": "2026-10-10",
   "sha256": "a17f4f31dd6a71d62b0f7e8a054a11ede14ee30713f757a57fe8abd67dfd586c",
   "size": 5894089,
   "version": "0.1.6.9004"
  },
  "qe_ena-0.1.6.9004-cp312-cp312-macosx_26_0_arm64.whl": {
   "published": "2026-10-09",
   "sha256": "ba27c6772e8c4ceac894814676900f5dd2d3a177851825c67f8acd0994b221f9",
   "size": 163728,
   "version": "0.1.6.9004"
  },
  "qe_ena-0.1.6.9004-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl": {
   "published": "2026-10-09",
   "sha256": "14e45a9e554d455ed5665fd6124088a63cae931858ca835af3874c005950db95",
   "size": 12141945,
   "version": "0.1.6.9004"
  },
  "qe_ena-0.1.6.9004-cp312-cp312-win_amd64.whl": {
   "published": "2026-10-10",
   "sha256": "0a122badbc1e1998dad02e73ed54f23717758212527ac6bf73f1aa85bc056c18",
   "size": 5894300,
   "version": "0.1.6.9004"
  },
  "qe_ena-0.1.6.9004-cp313-cp313-macosx_26_0_arm64.whl": {
   "published": "2026-10-09",
   "sha256": "c9ea8c5c751998f2fe93509be01a52357c1537b38ae70c92c18ee075af4fe977",
   "size": 163741,
   "version": "0.1.6.9004"
  },
  "qe_ena-0.1.6.9004-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl": {
   "published": "2026-10-09",
   "sha256": "12f2d0aa988f7816bc10a90f496546b92df07e1c2207b2a0920924d6ac2dd911",
   "size": 12141875,
   "version": "0.1.6.9004"
  },
  "qe_ena-0.1.6.9004-cp313-cp313-win_amd64.whl": {
   "published": "2026-10-10",
   "sha256": "eef7a455d8e6c5fb7fad2714156baf9050214b7835ddf6313fbc20c1c6a96d5d",
   "size": 5894212,
   "version": "0.1.6.9004"
  },
  "qe_ena-0.1.6.9004.tar.gz": {
   "published": "2026-10-09",
   "sha256": "c636da0d0207fdd80667f7f94b82e18aeb7b1b9898a00d81b0dbf3ff7ac943f6",
   "size": 191221,
   "version": "0.1.6.9004"
  },
  "qe_ena-0.1.6.tar.gz": {
   "published": "2026-10-09",
   "sha256": "f0828d6320f61dee4513c13c60fbd7297c01e6990d62fb52e69251db772d4153",
   "size": 191208,
   "version": "0.1.6"
  }
 },
 "metadata": {
  "author": "Cody L Marquart <cody.marquart@wisc.edu>",
  "description": "# qe-ena\n\nPython implementation of Epistemic Network Analysis (ENA) \u2014 sister package to [`rENA`](../README.md).\nInstall it as `qe-ena`; import it as `ena`.\n\n> Previously published as `pyENA` (`import pyena`). The `pyena` project on PyPI is an\n> unrelated package \u2014 install `qe-ena` from the QE index as shown below.\n\n`ena` runs its math in C++ shared with rENA: the ENA model code (rotations, node\npositions, window estimation) is libena, compiled into `qe-ena` itself (`ena.libena`)\ntogether with the accumulation it uses (tma's libtma), and generic numerics come from\n[`qe-lib`](https://gitlab.com/epistemic-analytics/qe-packages/libqe) (`import qe`).\n\n---\n\n## Installation\n\n`qe-ena` requires `qe-lib`, which is also on the QE package index; other\ndependencies (numpy, pandas) come from PyPI.\n\n```bash\nuv add qe-ena --index qe-libs=https://qe-libs.org/py/simple/\n# or\npip install qe-ena --extra-index-url https://qe-libs.org/py/simple/\n```\n\nDevelopment builds from `main` are on a separate index,\n`https://qe-libs.org/py/dev/simple/`. See https://qe-libs.org/py/project/qe-ena/.\n\n### Development install\n\nBuilding from a checkout compiles the libena extension: it needs a C++17\ncompiler, CMake and [Armadillo](https://arma.sourceforge.net/) (`brew install\narmadillo`, `apt install libarmadillo-dev`), plus the headers that\n`scripts/sync-headers.sh` vendors into `python/include/` (libena from this repo,\nlibqe and libtma from Conan; `LIBQE_INCLUDE` / `LIBTMA_INCLUDE` point at local\ncheckouts instead, and a `../tma` checkout is used while libtma is unpublished).\n\n```bash\nsh scripts/sync-headers.sh                 # from the repo root\npip install qe-lib --extra-index-url https://qe-libs.org/py/simple/\npip install \"./python[dev]\"\npytest python/tests --import-mode=importlib   # tests the installed package\n```\n\n---\n\n## Quick Start\n\n```python\nimport pandas as pd\nfrom ena import ENA\n\nrs = pd.read_csv(\"../inst/extdata/rs.data.csv\")   # rENA's RS.data\n\nCODES = [\"Data\", \"Technical Constraints\", \"Performance Parameters\",\n         \"Client and Consultant Requests\", \"Design Reasoning\", \"Collaboration\"]\n\n# Units and conversations as rENA's RS.data examples: units by Condition +\n# UserName, conversations by Condition + GroupName.\nrs[\"unit_key\"]  = rs[\"Condition\"] + \"::\" + rs[\"UserName\"]\nrs[\"convo_key\"] = rs[\"Condition\"] + \"::\" + rs[\"GroupName\"]\n\nmodel = ENA().fit(rs, \"unit_key\", \"convo_key\", CODES, window_size=4)\n```\n\n---\n\n## Plotting\n\nqe-ena models plot with [qe-viz](https://qe-libs.org/py/project/qe-viz/) (`import qeviz`), the\ninteractive ENA / ONA network viewer used by rENA (`pip install qe-viz\n--extra-index-url https://qe-libs.org/py/simple/`). The two conditions compared \u2014\nFirstGame \u2212 SecondGame, with each group's mean and 95% confidence interval:\n\n```python\nimport qeviz\n\np = (qeviz.from_pyena(model, group_col=\"Condition\", title=\"FirstGame \u2212 SecondGame\")\n       .edges(\"FirstGame\", compare=\"SecondGame\", color_scale=\"plot\", magnify=3)\n       .group())\np                              # displays inline in Jupyter\np.export_html(\"rs-data.html\")  # or a self-contained HTML file\n```\n\n![FirstGame \u2212 SecondGame network subtraction of RS.data with both group means](https://gitlab.com/epistemic-analytics/qe-packages/rENA/-/raw/main/python/docs/pyena-rs-subtraction.png)\n\nBlue edges are stronger in FirstGame, red in SecondGame. `magnify=3` widens\nthe edges to make a subtraction's small differences readable (the plot says so).\nSee the [qeviz README](https://qe-libs.org/py/project/qe-viz/) for single-group\nnetworks, unit points, and networks or means from your own data.\n\n---\n\n## Accessing Results\n\n```python\nmodel.line_weights_           # normalised adjacency vectors  (n_units \u00d7 n_connections)\nmodel.row_connection_counts_  # row-level raw adjacency vectors (n_rows \u00d7 n_connections)\nmodel.points_                 # unit positions in ENA space   (n_units \u00d7 dims)\nmodel.centroids_              # network centroids             (n_units \u00d7 dims)\nmodel.rotation_nodes_         # code node positions           (n_codes \u00d7 dims)\nmodel.connection_counts_      # raw unit adjacency vectors    (n_units \u00d7 n_connections)\nmodel.unit_labels_            # unit labels in order\nmodel.connection_names_       # e.g. [\"Data & Technical Constraints\", ...]\nmodel.variance_               # variance explained per dimension (= rENA's model$variance)\n```\n\n---\n\n## Separate Accumulation\n\n```python\nfrom ena import ENA, accumulate\n\naccum = accumulate(rs, \"unit_key\", \"convo_key\", CODES, window_size=4)\n\naccum.connection_counts_      # raw unit co-occurrence matrix\naccum.row_connection_counts_  # raw row co-occurrence matrix\naccum.unit_labels_            # unit labels\naccum.connection_names_       # connection labels\naccum.meta                    # per-unit metadata DataFrame\n\n# Reuse the same accumulation with different rotations\nfrom ena import mean_rotation, generalized_rotation\n\nmodel_svd = ENA().fit(accum)\nmodel_mr  = ENA().fit(accum, rotation=mean_rotation(g1_mask, g2_mask))\nmodel_gmr = ENA().fit(accum, rotation=generalized_rotation(meta[\"Condition\"]))\n```\n\n---\n\n## Rotation Methods\n\n| Rotation | Argument |\n|---|---|\n| SVD (default) | `rotation=None` |\n| Means | `mean_rotation(g1, g2)` |\n| Generalised (GMR) | `generalized_rotation(x_var)` |\n| Regression (V ~ x) | `regression_rotation(x_var)` |\n| Regression (x ~ V) | `regression_rotation_2(x_var)` |\n| Custom matrix | `rotation=my_ndarray` |\n\n```python\nfrom ena import ENA, mean_rotation, generalized_rotation, regression_rotation\n\nmeta = (rs.drop_duplicates(\"unit_key\")\n          .set_index(\"unit_key\")\n          .reindex(model.unit_labels_)\n          .reset_index())\n\n# Means rotation\nmodel_mr = ENA().accumulate(rs, \"unit_key\", \"convo_key\", CODES).fit(\n    rotation=mean_rotation(\n        meta[\"Condition\"] == \"FirstGame\",\n        meta[\"Condition\"] == \"SecondGame\",\n    )\n)\n\n# Generalised rotation\nmodel_gmr = ENA().accumulate(rs, \"unit_key\", \"convo_key\", CODES).fit(\n    rotation=generalized_rotation(meta[\"Condition\"])\n)\n\n# Regression rotation\nimport numpy as np\ncondition_bin = (meta[\"Condition\"] == \"FirstGame\").astype(float).to_numpy()\nmodel_reg = ENA().accumulate(rs, \"unit_key\", \"convo_key\", CODES).fit(\n    rotation=regression_rotation(condition_bin)\n)\n```\n\n---\n\n## Window Options\n\n| Option | Argument |\n|---|---|\n| Window back | `window_size=4` |\n| Window forward | `window_forward=2` |\n| Infinite window | `window_size=sys.maxsize` |\n| Binary co-occurrence | `binary=True` |\n| Weighted co-occurrence | `binary=False` |\n\n---\n\n## Further Reading\n\n- [ENA resources page](https://www.epistemicnetwork.org/resources/)\n- [Epistemic Analytics](https://www.epistemicnetwork.org/)",
  "description_content_type": "text/markdown",
  "license": "GPL-3.0-only",
  "name": "qe-ena",
  "project_urls": [
   [
    "Homepage",
    "https://qe-libs.org/py/project/qe-ena/"
   ],
   [
    "Source",
    "https://gitlab.com/epistemic-analytics/qe-packages/rENA/-/tree/main/python"
   ],
   [
    "Issues",
    "https://gitlab.com/epistemic-analytics/qe-packages/rENA/-/issues"
   ]
  ],
  "requires_dist": [
   "qe-lib<0.2,>=0.1.7",
   "numpy>=1.24",
   "pandas>=1.5",
   "pytest>=7; extra == \"dev\""
  ],
  "requires_python": ">=3.10",
  "summary": "Python ENA (Epistemic Network Analysis) modeling \u2014 sister package to rENA",
  "version": "0.1.6"
 },
 "metadata_from": "0.1.6",
 "name": "qe-ena"
}
