Metadata-Version: 2.4
Name: hgh
Version: 0.1.0
Summary: Hierarchical grid heatmap visualization and bibliometric analytics
Project-URL: Repository, https://github.com/r-calero/hgh
Author-email: Romel Calero Ramos <romel.calero@c3.unam.mx>
License: MIT License
        
        Copyright (c) 2026 Romel Calero Ramos
        
        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.
License-File: LICENSE
Keywords: bibliometrics,heatmap,plotly,scientometrics,visualization
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
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 :: Information Analysis
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.10
Requires-Dist: numpy
Requires-Dist: openpyxl
Requires-Dist: pandas
Requires-Dist: plotly
Requires-Dist: rich
Requires-Dist: scipy
Requires-Dist: typer
Provides-Extra: all
Requires-Dist: dash; extra == 'all'
Requires-Dist: kaleido; extra == 'all'
Requires-Dist: pytest; extra == 'all'
Provides-Extra: dev
Requires-Dist: dash; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Provides-Extra: export
Requires-Dist: kaleido; extra == 'export'
Description-Content-Type: text/markdown

# hgh - Hierarchical Grid Heatmap

Python package for building hierarchical evolution heatmaps from bibliometric data.
Designed for visualizing how thematic structures evolve across time at micro, meso,
and macro levels of a topic taxonomy.

## Installation

```bash
pip install hgh
```

Static image export (PDF, PNG, SVG) requires kaleido:

```bash
pip install hgh[export]
```

## Quick start

### Single workbook (Excel)

```python
from hgh.main import build_hgh

build_hgh(
    source="workbook.xlsx",
    taxonomy="taxonomy.csv",
    kind="impact",
    normalization="coverage",
    out_html="output.html",
)
```

### Multi-unit comparison from CSV

```python
from hgh.main import build_hgh_multiple

build_hgh_multiple(
    source="multi_long.csv",
    taxonomy="taxonomy.csv",
    focal_units=["Unit A", "Unit B"],
    kinds=["production", "impact"],
    normalization="coverage",
    export={"html": "comparison.html", "pdf": True, "paper": "a4-landscape", "dpi": 300},
    show=False,
)
```

### Two-unit comparison with delta

```python
from hgh import MultipleCSVEvolutionWorkbook
from hgh.main import build_hgh_comparison

mewb = MultipleCSVEvolutionWorkbook("multi_long.csv")

build_hgh_comparison(
    left_source=mewb.get("Unit A"),
    right_source=mewb.get("Unit B"),
    taxonomy="taxonomy.csv",
    measure="impact",
    normalization="coverage",
    show_delta=True,
    export={"html": "delta.html", "png": True, "paper": "double-column", "dpi": 300},
    show=False,
)
```

### Direct workbook mode (no CSV intermediate)

```python
from hgh import EvolutionWorkbook
from hgh.main import build_hgh_multiple

build_hgh_multiple(
    source=[
        (EvolutionWorkbook("unit_a.xlsx"), "Unit A"),
        (EvolutionWorkbook("unit_b.xlsx"), "Unit B"),
    ],
    taxonomy="taxonomy.csv",
    kinds=["production", "impact"],
    normalization="hill",
    hill_q=1.0,
    export={"html": "output.html"},
)
```

## Data sources

### EvolutionWorkbook

Reads an Excel file with period sheets (`YYYY` for production, `YYYY_c` for impact).
Each sheet must have columns `topic`, `count`, `percent`.

```python
from hgh import EvolutionWorkbook

wb = EvolutionWorkbook("workbook.xlsx")
print(wb.periods("impact"))   # ['2010', '2011', ...]
```

Export to long-format CSV:

```python
wb.to_long_csv("output.csv", focal_unit="My Unit", fill_empty_years=True)
```

### CSVEvolutionWorkbook

Reads the long-format CSV produced by `to_long_csv()`.
Columns: `focal_unit` (optional), `year`, `event_type`, `topic`, `count`, `percent`.

```python
from hgh import CSVEvolutionWorkbook

wb = CSVEvolutionWorkbook("long.csv")
```

### MultipleCSVEvolutionWorkbook

Loads a multi-unit long-format CSV once and exposes per-unit workbook views.

```python
from hgh import MultipleCSVEvolutionWorkbook

mewb = MultipleCSVEvolutionWorkbook("multi_long.csv")
print(mewb.focal_units())       # ['Unit A', 'Unit B']

wb_a = mewb.get("Unit A")      # CSVEvolutionWorkbook
```

## Normalization modes

| Mode | Description |
|---|---|
| `coverage` | Active micro-topics / possible micro-topics under each meso |
| `hill` | Normalized Hill diversity number (order `hill_q`); q=1 equals Shannon |
| `max_row` | Each meso divided by its maximum across all periods |
| `period_max` | Each period divided by its maximum across all meso topics |
| `impacted_max_row` | Active micro-topics per period / max active in span |

`coverage` and `hill` require a taxonomy with at least three levels and
`target_level != leaf_level_in_data`.

## Taxonomy format

A CSV with one column per hierarchy level. The default level names are
`macro`, `meso`, `micro` - each row defines one leaf topic path.

```
macro,meso,micro
1 Clinical Sciences,1.1 Cardiology,1.1.4 Heart failure biomarkers
1 Clinical Sciences,1.1 Cardiology,1.1.7 Cardiac imaging
1 Clinical Sciences,1.2 Neurology,1.2.1 Stroke rehabilitation
```

## Export

All `build_*` functions accept an `export` dict:

```python
export={
    "html":         "figure.html",   # interactive
    "pdf":          True,            # same stem as html
    "png":          True,
    "svg":          "/path/to/fig.svg",
    "paper":        "a4-landscape",  # size preset
    "dpi":          300,
    "matrices_dir": "matrices/",     # export evolution matrices as CSV
}
```

Paper presets: `single-column`, `double-column`, `a4`, `a4-landscape`,
`a3`, `a3-landscape`, `letter`, `letter-landscape`.

Static formats require `pip install hgh[export]`.

## CLI

```bash
# Single workbook heatmap
hgh heneh --excel workbook.xlsx --taxonomy taxonomy.csv \
          --measure impact --normalization coverage --output output.html

# Side-by-side comparison
hgh heneh-compare --source a.xlsx --source b.xlsx \
                  --label "Unit A" --label "Unit B" \
                  --taxonomy taxonomy.csv --output comparison.html
```

## Use in notebooks and applications

### Jupyter

```python
from hgh import MultipleCSVEvolutionWorkbook
from hgh.main import build_hgh_comparison

mewb = MultipleCSVEvolutionWorkbook("multi_long.csv")

fig = build_hgh_comparison(
    left_source=mewb.get("Unit A"),
    right_source=mewb.get("Unit B"),
    taxonomy="taxonomy.csv",
    measure="impact",
    show_delta=True,
    show=False,
)
fig.show()
```

### Dash

```python
import dash
from dash import dcc, html, Input, Output
from hgh import EvolutionWorkbook
from hgh.io.hierarchy import HierarchyIndex
from hgh.viz.figure import plot_hierarchical_heatmap

wb = EvolutionWorkbook("workbook.xlsx")
hierarchy = HierarchyIndex.from_csv("taxonomy.csv")

app = dash.Dash(__name__)
app.layout = html.Div([
    dcc.Dropdown(
        id="normalization",
        options=["coverage", "hill", "max_row"],
        value="coverage",
    ),
    dcc.Graph(id="heatmap"),
])

@app.callback(Output("heatmap", "figure"), Input("normalization", "value"))
def update(normalization):
    import pandas as pd
    mat = wb.evolution_matrix(
        hierarchy=hierarchy,
        leaf_level_in_data="micro",
        target_level="meso",
        kind="impact",
        normalization_mode=normalization,
    )
    return plot_hierarchical_heatmap(
        evolution_matrix=mat,
        classification_df=pd.read_csv("taxonomy.csv"),
        title=f"Impact evolution ({normalization})",
        return_figure=True,
    )

if __name__ == "__main__":
    app.run(debug=True)
```

### Streamlit

```python
import streamlit as st
import pandas as pd
from hgh import EvolutionWorkbook
from hgh.io.hierarchy import HierarchyIndex
from hgh.viz.figure import plot_hierarchical_heatmap

@st.cache_resource
def load_data():
    wb = EvolutionWorkbook("workbook.xlsx")
    hierarchy = HierarchyIndex.from_csv("taxonomy.csv")
    taxonomy = pd.read_csv("taxonomy.csv")
    return wb, hierarchy, taxonomy

wb, hierarchy, taxonomy = load_data()

normalization = st.selectbox("Normalization", ["coverage", "hill", "max_row"])
kind = st.radio("Measure", ["impact", "production"], horizontal=True)

mat = wb.evolution_matrix(
    hierarchy=hierarchy,
    leaf_level_in_data="micro",
    target_level="meso",
    kind=kind,
    normalization_mode=normalization,
)

fig = plot_hierarchical_heatmap(
    evolution_matrix=mat,
    classification_df=taxonomy,
    title=f"{kind.title()} evolution ({normalization})",
    return_figure=True,
)
st.plotly_chart(fig, use_container_width=True)
```

## API reference

### High-level functions (`hgh.main`)

| Function | Description |
|---|---|
| `build_hgh` | Single workbook heatmap (Excel or CSV) |
| `build_hgh_multiple` | N-unit side-by-side from CSV or workbook list |
| `build_hgh_comparison` | Two-unit comparison with optional delta panel |
| `run_temporal_analysis` | Pivot years, adoption waves, trend detection |
| `run_persistence_analysis` | Core/emerging/declining/sporadic classification |
| `run_delta_analysis` | Cell-level delta and dominance between two matrices |

### Workbooks

| Class | Source |
|---|---|
| `EvolutionWorkbook` | Excel file (`.xlsx`) |
| `CSVEvolutionWorkbook` | Long-format CSV |
| `MultipleCSVEvolutionWorkbook` | Multi-unit long-format CSV |

### Analytics

| Class | Description |
|---|---|
| `TemporalDynamicsAnalyzer` | Pivot years, waves, growth rates |
| `PersistenceAnalyzer` | Topic persistence profiles and bands |
| `DeltaAnalyzer` | Delta matrix and dominance analysis |

## License

MIT
