{"id":49078691,"url":"https://github.com/openspyrit/spas","last_synced_at":"2026-04-20T11:13:39.833Z","repository":{"id":48352308,"uuid":"390662353","full_name":"openspyrit/spas","owner":"openspyrit","description":"Single-Pixel Acquisition Software","archived":false,"fork":false,"pushed_at":"2026-03-26T09:52:30.000Z","size":1601,"stargazers_count":9,"open_issues_count":10,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-03-27T03:38:45.109Z","etag":null,"topics":["acquisition","avantes","digital-micromirror-device","dmd","hadamard","hyperspectral-imaging","medical-imaging","python","single-pixel","single-pixel-camera","spectrometer","vialux"],"latest_commit_sha":null,"homepage":"https://spas.readthedocs.io/en/latest/","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openspyrit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-07-29T08:56:40.000Z","updated_at":"2025-03-20T14:59:12.000Z","dependencies_parsed_at":"2024-12-03T22:19:05.100Z","dependency_job_id":"d8f9126b-5ad5-45a9-b9b2-3a00b8c77783","html_url":"https://github.com/openspyrit/spas","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/openspyrit/spas","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openspyrit%2Fspas","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openspyrit%2Fspas/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openspyrit%2Fspas/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openspyrit%2Fspas/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openspyrit","download_url":"https://codeload.github.com/openspyrit/spas/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openspyrit%2Fspas/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32044449,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T10:33:29.490Z","status":"ssl_error","status_checked_at":"2026-04-20T10:32:30.107Z","response_time":94,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acquisition","avantes","digital-micromirror-device","dmd","hadamard","hyperspectral-imaging","medical-imaging","python","single-pixel","single-pixel-camera","spectrometer","vialux"],"created_at":"2026-04-20T11:13:39.114Z","updated_at":"2026-04-20T11:13:39.822Z","avatar_url":"https://github.com/openspyrit.png","language":"Jupyter Notebook","readme":"# Single-Pixel Acquisition Software (SPAS)\n\nSPAS is python package designed for single-pixel acquisition.\n\nSPAS has been tested for controlling a [DLP7000](https://www.vialux.de/en/hi-speed-v-modules.html) Spatial Light Modulator and an [AvaSpec-ULS2048CL-EVO](https://www.avantes.com/products/spectrometers/starline/avaspec-uls2048cl-evo/) spectrometer. It should work as well for for similar equipment with a few changes.\n\nSPAS is a companion package to the [SPyRiT](https://github.com/openspyrit/spyrit) package.\n\n\n# Installation\n\n## For users\nThe SPAS package can be installed on Linux, MacOs and Windows. \n\n```powershell\npip install git+https://github.com/openspyrit/spas.git\n```\n\nCheck your installation\n``` python\nfrom spas import read_metadata\n```\nThis functions reads the metadata an existing acquisition (e.g., available on [SPIHIM](https://pilot-warehouse.creatis.insa-lyon.fr/))\n\n## For developers\nThe SPAS package can be installed on Linux, MacOs and Windows. However, it will be fully functional on Windows only due to DLL dependencies required for harware control.\n\n* Clone the SPAS repository\n\n```powershell\ngit clone git@github.com:openspyrit/spas.git\n```\n\nNavigate to `./spas/` and install the SPAS package in editable mode\n\n```powershell\npip install -r requirements.txt\npip install -e .\n```\n\n* Add DLLs (optional, for instrumentation control only)\n\n    The following dynamic-link libraries (DLLs) were required to control our instrumentation\n\n    * `avaspecx64.dll` provided by your Avantes distributor\n    * `alpV42.dll` available [here](https://www.vialux.de/en/hi-speed-download.html) by installing the entire ALP4 library\n\n\n* The DLLs should be placed inside the  `lib` folder. The typical directory structure is\n\n```\n├───lib\n│   ├───alpV42\n│   │   └───x64\n│   │   │   └───alpV42.dll\n│   └───avaspec3\n│   │   └───avaspecx64.dll\n├───noise-calibration\n├───models\n├───scripts\n├───spas\n├───requirements.txt\n├───setup.py\n├───stats\n│   ├───Average_64x64.npy\n│   ├───Cov_64x64.npy\n```\n\n# API Documentation\nhttps://spas.readthedocs.io/\n\n# Contributors (alphabetical order)\n* Thomas Baudier\n* Guilherme Beneti-Martin\n* [Nicolas Ducros](https://www.creatis.insa-lyon.fr/~ducros/WebPage/index.html)\n* Laurent Mahieu Williame\n\n# How to cite?\nWhen using SPAS in scientific publications, please cite the following paper:\n\n* G. Beneti-Martin, L Mahieu-Williame, T Baudier, N Ducros, \"OpenSpyrit: an Ecosystem for Reproducible Single-Pixel Hyperspectral Imaging,\" Optics Express, Vol. 31, No. 10, (2023). https://doi.org/10.1364/OE.483937.\n\n# License\nThis project is licensed under the LGPL-3.0 license - see the [LICENSE.md](LICENSE.md) file for details\n\n# Getting started\n## Preparation (just once)\n### 1. Creating Walsh-Hadamard patterns\n\nRun in Python:\n``` python\nfrom spas.generate import walsh_patterns\nwalsh_patterns(save_data=True)\n```\nBy default the patterns are 1024x768 PNG images saved in `./Walsh_64_64/`.\n\n### 2. Get statistics\n\n   * Download covariance and mean matrices and save them both in `./stats/`:\n  \n        https://www.creatis.insa-lyon.fr/~ducros/spyritexamples/2021_ISTE/Average_64x64.npy\n\n        https://www.creatis.insa-lyon.fr/~ducros/spyritexamples/2021_ISTE/Cov_64x64.npy\n\n\n   * (Alternative, which takes much longer) compute covariance matrix.\n``` python \nfrom spyrit.misc.statistics import stat_walsh_stl10\nstat_walsh_stl10()\n```\n\n### 3. Generate the pattern order\nIt is necessary to generate an array that specifies the order in which the patterns are acquired. This can be done by running:\n\n``` python\nfrom spas import generate_hadamard_order\ngenerate_hadamard_order(N=64, name='pattern_order', cov_path='./stats/Cov_64x64.npy', pos_neg=True)\n```\n\nThe output array will be placed in `./stats/pattern_order.npz`. It may be necessary to change `cov_path` depending on the previous step.\n\n### 4. We recommend using spyder for acquisition\n\nIn a terminal :\n``` powershell\npip install spyder\nspyder\n```\n\nYou may experience an issue launcing spyder (July 2021). It is solved with:\n``` powershell\nconda install pywin32\n```\n\n  ## First Acquisition\n\nWe provides several script examples in `./scripts/`. A minimal working example is provided below.\n\n* Initialization (just once, two consecutively returns an error):\n``` python \nfrom spas import *\nspectrometer, DMD, DMD_initial_memory = init() \n```\n\n* Setup:\n``` python   \nmetadata = MetaData(\n    output_directory='./meas/',\n    pattern_order_source='./stats_download/pattern_order.npz',\n    pattern_source='./Walsh_64x64/',\n    pattern_prefix='Walsh_64x64',\n    experiment_name='my_first_measurement',\n    light_source='white_lamp',\n    object='no_object',\n    filter='no_filter',\n    description='my_first_description')\n    \nacquisition_parameters = AcquisitionParameters(\n    pattern_compression=1.0,\n    pattern_dimension_x=64,\n    pattern_dimension_y=64)\n    \nspectrometer_params, DMD_params = setup(\n    spectrometer=spectrometer, \n    DMD=DMD,\n    DMD_initial_memory=DMD_initial_memory,\n    metadata=metadata, \n    acquisition_params=acquisition_parameters,\n    integration_time=1.0)\n\n```\n\n* Acquisition:\n``` python \nmeas = acquire(\n    ava=spectrometer,\n    DMD=DMD,\n    metadata=metadata,\n    spectrometer_params=spectrometer_params,\n    DMD_params=DMD_params,\n    acquisition_params=acquisition_parameters,\n    repetitions=1,\n    reconstruct=False)\n\n```\n\n* Disconnect, otherwise it is possible to run setup and/or acquisition again.\n``` python \ndisconnect(spectrometer, DMD)\n```\n\n## First Reconstruction (No Neural Networks)\n\nHere, we consider an acquisition with `pattern_compression=1.0`, meaning all the patterns are acquired.\n\n* Measurements are in memory (fully sampled)\n  \n\nReconstruct the measurements contained in variable `meas`:\n``` python \nimport spyrit.misc.walsh_hadamard as wh\nfrom spas import reconstruction_hadamard\nH = wh.walsh2_matrix(64)\nrec = reconstruction_hadamard(acquisition_parameters.patterns, 'walsh', H, meas)\n```\n\nBin the reconstructed hypercube in 8 bins between 530 and 730 nm:\n\n``` python\nfrom spas import spectral_binning\nrec_bin, wavelengths_bin, _ = spectral_binning(rec.T, acquisition_parameters.wavelengths, 530, 730, 8)\n```\n\nPlot the 8 spectral bins:\n``` python\nfrom spas import plot_color\nplot_color(rec_bin, wavelengths_bin)\n```\n\n* Measurements are saved on the disk (fully sampled)\n\nReconstruct the measurements saved as `../meas/my_first_measurement`.\n\nRead the data from a file:\n``` python\nimport numpy as np\nfile = np.load('../meas/my_first_measurement' + '_spectraldata.npz')\nmeas = file['spectral_data']\n```\n\nRead the metadata (it is necessary to recover the acquisition order of the patterns from `acquisition_parameters`):\n``` python\nfrom spas import read_metadata, reconstruction_hadamard\n_, acquisition_parameters, _, _ = read_metadata('../meas/my_first_measurement' + '_metadata.json')\n```\n\nReconstruct:\n``` python\nimport spyrit.misc.walsh_hadamard as wh\nH = wh.walsh2_matrix(64)\nrec = reconstruction_hadamard(acquisition_metadata.patterns, 'walsh', H, meas)\n```\n## Reconstruction with a Neural Network\n\n* We consider an existing acquisition that was saved on the disk in the `../meas/` folder \n\nRead the data:\n``` python\nimport numpy as np\nfile = np.load('../meas/my_first_measurement' + '_spectraldata.npz')\nmeas = file['spectral_data']\n```\n\nRead the metadata (we need the get the acquisition order of the patterns):\n``` python\nfrom spas import read_metadata, reconstruction_hadamard\n_, acquisition_parameters, _, _ = read_metadata('../meas/my_first_measurement' + '_metadata.json')\n```\n\n* We consider that we have access to a trained network and the covariance matrix associated to it. \n\nAn example network can be downloaded [here](https://pilot-warehouse.creatis.insa-lyon.fr/#collection/6140ba6929e3fc10d47dbe3e/folder/622b5ea843258e76eab21740). It allows the reconstruction of a 128 x 128 image from only 4096 Hadamard coefficients (i.e., 8192 raw measurements) that correspond to a full acquisition at a 64 x 64  resolution. Its associated covariance matrix can be downloaded [here](https://pilot-warehouse.creatis.insa-lyon.fr/#collection/6140ba6929e3fc10d47dbe3e/folder/63d7f3620386da2747641e1b).\n\n``` python\nfrom spas import ReconstructionParameters, setup_reconstruction\n\nnetwork_param = ReconstructionParameters(\n    # Reconstruction network    \n    M = 64*64,          # Number of measurements\n    img_size = 128,     # Image size\n    arch = 'dc-net',    # Main architecture\n    denoi = 'unet',     # Image domain denoiser\n    subs = 'rect',      # Subsampling scheme\n    \n    # Training\n    data = 'imagenet',  # Training database\n    N0 = 10,            # Intensity (max of ph./pixel)\n    \n    # Optimisation (from train2.py)\n    num_epochs = 30,       # Number of training epochs\n    learning_rate = 0.001, # Learning Rate\n    step_size = 10,        # Scheduler Step Size\n    gamma = 0.5,           # Scheduler Decrease Rate   \n    batch_size = 256,      # Size of the training batch\n    regularization = 1e-7 # Regularisation Parameter\n    )\n        \ncov_path = '../stat/Cov_8_128x128.npy'\nmodel_folder = '../model/'\n      \nmodel, device = setup_reconstruction(cov_path, model_folder, network_param)\n```\n\nLoad noise calibration parameters (provided with the data or computed using tools in `/noise-calibration`). :warning: Noise parameters are not used anymore in the current implementation of `spas`.\n \n``` python\nfrom spas import load_noise\nnoise = load_noise('../noise-calibration/fit_model.npz')\n```\n\nBin the spectral measurements (here, 4 bins between 530 nm and 730 nm)\n\n``` python\nfrom spas import spectral_binning\nmeas_bin, wavelengths_bin, _ = spectral_binning(meas.T, wavelengths, 530, 730, 4)\n```\n\nReorder and subsample the spectral measurements\n``` python\nfrom spas.reconstruction_nn import reorder_subsample\nmeas_bin_2 = reorder_subsample(meas_bin, acquisition_param, network_param) \n```\n\nReconstruct the spectral images\n``` python\nfrom spas import reconstruct\nrec = reconstruct(model, device, meas_bin_2)\n```\n\nPlot the spectral images\n``` python\nfrom spas import plot_color           \nplot_color(rec, wavelengths_bin)\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenspyrit%2Fspas","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenspyrit%2Fspas","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenspyrit%2Fspas/lists"}