## Hinode/EIS Level-0 Spectra Visualization

Hinode EUV Imaging Spectrometer (EIS) Level-0 data contain raw EUV spectra of the solar corona
across multiple emission line windows (2006–present).
Each file covers one raster observation and stores spectra from up to ~25 emission lines
as a binary table in gzip-compressed FITS format.
The dataset page is at [DARTS](https://darts.isas.jaxa.jp/datasets/darts:hinode-eis-level0/).

---

### Data Files

Files are organized by observation date under:

```
https://data.darts.isas.jaxa.jp/pub/hinode/eis/level0/{YYYY}/{MM}/{DD}/
```

Each file covers one raster sequence:

```
eis_l0_{YYYYMMDD}_{HHMMSS}.fits.gz
```

The FITS file contains a Primary HDU (metadata only) and a `DATA` binary table extension.
Each row in the table corresponds to one slit position in the raster (`NEXP` rows total).
Spectral windows are stored as 2D arrays `[n_wavelength × n_spatial]` per row.

#### Key Primary HDU header keywords

| Keyword     | Example value               | Description |
|-------------|-----------------------------|-------------|
| `DATE_OBS`  | `2017-10-12T06:13:19`       | Observation start time (UTC) |
| `DATE_END`  | `2017-10-12T06:16:15`       | Observation end time (UTC) |
| `XCEN`      | `-203.9`                    | FOV center Solar-X (arcsec) |
| `YCEN`      | `43.1`                      | FOV center Solar-Y (arcsec) |
| `FOVX`      | `479.2`                     | Field of view in X (arcsec) |
| `FOVY`      | `488.0`                     | Field of view in Y (arcsec) |
| `SLIT_ID`   | `40"`                       | Slit/slot width |
| `NWIN`      | `10`                        | Number of spectral windows |
| `NEXP`      | `15`                        | Number of raster slit positions |
| `OBSTITLE`  | `HOP323 (plage)`            | Observation title |
| `TARGET`    | `Active Region`             | Observation target |
| `DATA_LEV`  | `0`                         | Processing level |

#### Binary table columns (DATA extension)

Each spectral window column is named after the emission line (e.g., `Fe XII 195.120`)
and has shape `(n_wavelength, n_spatial)` — typically `(40, 488)` pixels.
Additional scalar columns per row include:

| Column      | Description |
|-------------|-------------|
| `TI_1`      | Exposure start time (seconds from DATE_OBS) |
| `exp_dur`   | Exposure duration (seconds) |
| `XCEN_TI1`  | Solar-X center at exposure start (arcsec) |
| `YCEN_TI1`  | Solar-Y center at exposure start (arcsec) |
| `fmirr`     | Fine mirror position (scan step) |

---

### Visualization with Python

#### Requirements

```
pip install astropy matplotlib numpy requests
```

#### Helper functions

```python
import re
import gzip
import io
import requests
import numpy as np
import matplotlib.pyplot as plt
from astropy.io import fits

BASE = "https://data.darts.isas.jaxa.jp/pub/hinode/eis/level0"

def list_eis_files(year, month, day):
    """Return list of file URLs for a given date."""
    date_url = f"{BASE}/{year:04d}/{month:02d}/{day:02d}/"
    resp = requests.get(date_url, timeout=30, verify=False)
    if resp.status_code != 200:
        return []
    names = re.findall(r'href="(eis_l0_\w+\.fits\.gz)"', resp.text)
    return [date_url + n for n in names]

def load_eis(url):
    """Download and open a gzip-compressed EIS Level-0 FITS file."""
    r = requests.get(url, timeout=120, verify=False)
    r.raise_for_status()
    return fits.open(io.BytesIO(gzip.decompress(r.content)))
```

#### Example 1: List spectral windows and print observation summary

```python
urls = list_eis_files(2017, 10, 12)
print(f"{len(urls)} files found")

with load_eis(urls[0]) as hdul:
    h = hdul[0].header
    print(f"Date:    {h['DATE_OBS']}  →  {h['DATE_END']}")
    print(f"Title:   {h['OBSTITLE']}")
    print(f"Target:  {h['TARGET']}")
    print(f"Center:  ({h['XCEN']:.1f}\", {h['YCEN']:.1f}\")")
    print(f"FOV:     {h['FOVX']:.1f}\" × {h['FOVY']:.1f}\"")
    print(f"Slit:    {h['SLIT_ID']}  |  {h['NEXP']} raster positions")
    print()
    print("Spectral windows:")
    for col in hdul[1].columns:
        if col.dim:   # spectral windows have dim set
            print(f"  {col.name:25s}  shape={col.dim}")
```

#### Example 2: Plot a spectrum for one emission line at one slit position

```python
with load_eis(urls[0]) as hdul:
    h = hdul[0].header
    data = hdul[1].data
    spec_cols = [col.name for col in hdul[1].columns if col.dim]

    # Pick the first available Fe XII window (name varies slightly between obs)
    line = next((c for c in spec_cols if "Fe XII" in c), spec_cols[0])
    cube = np.array([row[line] for row in data])  # shape: (NEXP, n_wave, n_spatial)

    # Mean spectrum averaged over all slit positions and spatial pixels
    mean_spec = cube.mean(axis=(0, 2))

    fig, ax = plt.subplots(figsize=(8, 4))
    ax.plot(mean_spec)
    ax.set_xlabel("Wavelength pixel")
    ax.set_ylabel("Intensity (raw counts)")
    ax.set_title(f"Hinode/EIS  {line}  —  {h['DATE_OBS'][:19]}")
    plt.tight_layout()
    plt.savefig("hinode_eis_spectrum.png", dpi=150, bbox_inches="tight")
    plt.close()
```

#### Example 3: Build a spatial intensity map (sum over wavelength)

```python
with load_eis(urls[0]) as hdul:
    h = hdul[0].header
    data = hdul[1].data
    spec_cols = [col.name for col in hdul[1].columns if col.dim]

    line = next((c for c in spec_cols if "Fe XII" in c), spec_cols[0])
    cube = np.array([row[line] for row in data])  # (NEXP, n_wave, n_spatial)

    # Integrate over wavelength axis → (NEXP, n_spatial) = (scan, slit)
    intensity_map = cube.sum(axis=1).T   # (n_spatial, NEXP)

    fig, ax = plt.subplots(figsize=(6, 8))
    vmin, vmax = np.percentile(intensity_map, [1, 99])
    im = ax.imshow(intensity_map, origin="lower", cmap="hot",
                   vmin=vmin, vmax=vmax, aspect="auto")
    fig.colorbar(im, ax=ax, label="Intensity (raw counts)")
    ax.set_xlabel("Raster position (slit step)")
    ax.set_ylabel("Spatial pixel (along slit)")
    ax.set_title(f"Hinode/EIS  {line}\n{h['DATE_OBS'][:19]}")
    plt.tight_layout()
    plt.savefig("hinode_eis_map.png", dpi=150, bbox_inches="tight")
    plt.close()
```

#### Example 4: Compare multiple emission lines side by side

```python
with load_eis(urls[0]) as hdul:
    h = hdul[0].header
    data = hdul[1].data
    spec_cols = [col.name for col in hdul[1].columns if col.dim]

    n = len(spec_cols)
    fig, axes = plt.subplots(2, (n + 1) // 2, figsize=(14, 6))
    for ax, line in zip(axes.flat, spec_cols):
        cube = np.array([row[line] for row in data])
        imap = cube.sum(axis=1).T
        vmin, vmax = np.percentile(imap, [1, 99])
        ax.imshow(imap, origin="lower", cmap="hot", vmin=vmin, vmax=vmax, aspect="auto")
        ax.set_title(line, fontsize=8)
        ax.set_axis_off()

    for ax in axes.flat[n:]:
        ax.set_visible(False)

    fig.suptitle(f"Hinode/EIS — {h['DATE_OBS'][:19]}")
    plt.tight_layout()
    plt.savefig("hinode_eis_all_lines.png", dpi=150, bbox_inches="tight")
    plt.close()
```

---

### Notes

- Level-0 data are raw telemetry with no radiometric calibration. For calibrated spectra (Level-1), use the IDL `eis_prep` routine from Solar Software (SSW) or the Python package `eispac`.
- The spectral window names in the binary table correspond to the dominant emission line in each window. Each window contains `n_wavelength` spectral pixels (typically 24–40) × `n_spatial` slit pixels (up to 512).
- The `SLIT_ID` keyword identifies the slit used: `1"`, `2"`, `40"` (slot), or `266"` (slot). The 40" and 266" slots produce context images rather than true spectra.
- SSL certificate verification may fail for `data.darts.isas.jaxa.jp`; pass `verify=False` to `requests.get` as a workaround.
- For absolute wavelength calibration, a dispersion of approximately 0.0223 Å/pixel applies to the short-wavelength channel (SW: 170–210 Å) and 0.0446 Å/pixel to the long-wavelength channel (LW: 250–290 Å).

---

### Acknowledgement

When using this data in publications, please follow the [Hinode data use guidelines](https://darts.isas.jaxa.jp/missions/hinode/guidelines.html) and cite:

- Kosugi, T. et al. (2007), Sol. Phys., 243, 3. [doi:10.1007/s11207-007-9014-6](https://doi.org/10.1007/s11207-007-9014-6) — Hinode mission
- Culhane, J.L. et al. (2007), Sol. Phys., 243, 19. [doi:10.1007/s11207-007-9996-1](https://doi.org/10.1007/s11207-007-9996-1) — EIS instrument
