# Supplementary material for Information-Drive Design of Imaging Systems

This zip contains code, documentation, and a PDF of a concurrent manuscript referenced in the Discussion section, "Computationally Efficient Information-Driven Optical
Design with Interchanging Optimization"

## Contents

- `code/`: Contains the library implementation and experiments used to generate the figures in the paper. 
  - `encoding_information/`: Core library with models and estimation tools
  - Other folders contain contain experiments and code for reproducing paper figures, organized by application area. See `code/reproduction/README.md` for detailed instructions on: required datasets, experiment configuration, figure generation scripts

- `docs/`: Documentation for using the library. Open `docs/index.html` in a browser to view.

## Installation

You can install the package by navigating into the code directory and using pip:

```bash
pip install -e .
```

## Quick Start

Here's a basic example of how to use the library to estimate information in microscopy images of cells.

First, install the data management library with `pip install bsccm`


```python

from bsccm import download_dataset
from encoding_information.datasets import BSCCMDataset


data_path = download_dataset(tiny=True) # Download the tiny, demo version of the dataset


dataset = BSCCMDataset(data_path)
# load a 300 x H x W numpy array of 300 images of cells, with intensity counts in units of photons
measurements = dataset.get_measurements(300)


from encoding_information.models import PixelCNN, PoissonNoiseModel
from encoding_information import estimate_information, extract_patches

# Split into training/test sets and extract patches
# Breaking large images into patches increases computational efficiency
# Test set is used to evaluate information estimates
patches = extract_patches(measurements[:-100], patch_size=16)
test_patches = extract_patches(measurements[-100:], patch_size=16) 

# Initialize and fit model to training data
model = PixelCNN()  # Also supports FullGaussianProcess, StationaryGaussianProcess
noise_model = PoissonNoiseModel()
model.fit(patches)

# Estimate information content with confidence bounds
# Error bars are calculated based on test set size
info, lower_bound, upper_bound = estimate_information(
   model, 
   noise_model,
   patches,
   test_patches,
   confidence_interval=0.95
)

print(f"Information: {info:.2f} ± {(upper_bound-lower_bound)/2:.2f} bits/pixel")
```

