COHESIVM

COHESIVM: Combinatorial h+/e- Sample Investigation using Voltaic Measurements - Published in JOSS (2025)

https://github.com/mxwalbert/cohesivm

Science Score: 98.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
    Found 8 DOI reference(s) in README and JOSS metadata
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
    Published in Journal of Open Source Software

Keywords

combinatorial-approach high-throughput-analysis lab-automation materials-science python
Last synced: 4 months ago · JSON representation ·

Repository

Combinatorial h+/e- Sample Investigation using Voltaic Measurements

Basic Info
  • Host: GitHub
  • Owner: mxwalbert
  • License: mit
  • Language: Python
  • Default Branch: main
  • Homepage:
  • Size: 3.26 MB
Statistics
  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • Open Issues: 0
  • Releases: 2
Topics
combinatorial-approach high-throughput-analysis lab-automation materials-science python
Created over 2 years ago · Last pushed 6 months ago
Metadata Files
Readme Contributing License Citation

README.md

COHESIVM: Combinatorial h+/e- Sample Investigation using Voltaic Measurements

Introduction

The COHESIVM Python package provides a generalized framework for conducting combinatorial voltaic measurements in scientific research and development. The modular architecture enables researchers to adapt it to diverse experimental setups by extending its components to support custom configurations. These components are cohesively put together in an Experiment class which runs compatibility checks, manages data storage, and executes the measurements.

Key Features:

  • Modular Design: COHESIVM adopts a module-oriented approach where components such as measurement devices (Device), contacting interfaces (Interface), and measurement routines (Measurement) are abstracted into interchangeable units. This modular architecture enhances flexibility in experimental setups and makes it easy to add new component implementations. The tutorials in the documentation provide an extensive description of implementing custom components.
  • Combinatorial Flexibility: By abstracting the class for the contacting interface, COHESIVM enables diverse configurations for sample investigation. The MA8X8 measurement array, as implemented in the current core version, is only one example for an electrode contact array. Researchers can add custom implementations of the Interface class to support other configurations or, for example, robotic contacting systems.
  • Data Handling: Collected data is stored in a structured HDF5 database format using the Database class, ensuring efficient data management and accessibility. Metadata is collected based on the DCMI standard which is extended by COHESIVM-specific metadata terms.
  • Analysis and GUIs: Alongside the measurement routines, analysis functions and plots can be implemented, extending the Analysis base class. Together with the graphical user interface (also available for conducting experiments and reviewing the database contents), initial screening of the data is facilitated.

Table of Contents

Getting Started

Dependencies

The current core version of COHESIVM is tested for Python 3.9–3.12 and requires the following dependencies:

  • h5py (~=3.8)
  • numpy (~=1.21)
  • matplotlib (~=3.7)
  • tqdm (~=4.65)

Apart from the core package, extras exist for modules with additional dependencies (check the pyproject.toml for a complete listing):

| Extra | Module | Dependency | |---------|---------------------------|------------------| | gui | cohesivm.gui | bqplot~=0.12 | | ma8x8 | cohesivm.interfaces.ma8x8 | pyserial~=3.5 | | ossila | cohesivm.devices.ossila | xtralien~=2.10 | | agilent | cohesivm.devices.agilent | pyvisa~=1.13 | | full | – | all from above |

Installation

Using pip

To install the core COHESIVM package from the Python Package Index (PyPI), simply run:

console pip install cohesivm

This command will download and install the latest stable version of COHESIVM and its core dependencies.

[!IMPORTANT]

If you want to use the GUIs inside your Jupyter environment, make sure to specify the gui extra:

console pip install cohesivm[gui]

Cloning from GitHub

If you want to install the development version of the package from the GitHub repository, follow these steps: 1. Clone the repository to your local machine: console git clone https://github.com/mxwalbert/cohesivm.git 2. Navigate into the cloned directory: console cd cohesivm 3. Install the package and its dependencies: console pip install .[dev]

Configuration

A config.ini file should be placed in the root of your project to configure the hardware ports/addresses of the contact interfaces and measurement devices. Some DCMI metadata terms also need to be defined there. COHESIVM implements a config parser which allows to access these values, e.g.:

```pycon

import cohesivm cohesivm.config.get_option('DCMI', 'creator') Dow, John ```

Template

A preconfigured file with the currently implemented interfaces and devices can be copied from the repository, or you can create your own from this template:

```ini

This file is used to configure the project as well as the devices and interfaces (e.g., COM ports, addresses, ...).

METADATA ------------------------------------------------------------------------------------------------------------

[DCMI]

The following options correspond to the terms defined by the Dublin Core Metadata Initiative.

See https://purl.org/dc/terms/ for detailed descriptions.

publisher = "Your Company Ltd." creator = "Dow, John" rights = https://link.to/licence subject = "modular design"; "combinatorial flexibility"; "data handling"; "analysis and gui"

---------------------------------------------------------------------------------------------------------------------

INTERFACES ----------------------------------------------------------------------------------------------------------

[NAMEOFUSBINTERFACE] comport = 42

---------------------------------------------------------------------------------------------------------------------

DEVICES -------------------------------------------------------------------------------------------------------------

[NAMEOFNETWORK_DEVICE] address = localhost port = 8888 timeout = 0.1

---------------------------------------------------------------------------------------------------------------------

```

The names of the sections (e.g., NAME_OF_USB_INTERFACE) must be unique but can be chosen freely since they are referenced manually. The options (e.g., com_port), on the other hand, should follow the signature of the class constructor to use them efficiently. For example, an Interface implementation DemoInterface which requires the com_port parameter could be initialized using the configuration template from above:

python interface = DemoInterface(**config.get_section('NAME_OF_USB_INTERFACE'))

Example

In a common scenario, you probably want to configure multiple devices to use them at once. Let's consider the case where you need two OssilaX200 devices which are both connected via USB. Then, in the DEVICES part of the configuration, you would define two distinctive sections and set the required address option:

```ini

DEVICES -------------------------------------------------------------------------------------------------------------

[OssilaX200_1] address = COM4

[OssilaX200_2] address = COM5

---------------------------------------------------------------------------------------------------------------------

```

To initialize the devices, you could do something similar to the Basic Usage example:

python from cohesivm import config from cohesivm.devices.ossila import OssilaX200 smu1 = OssilaX200.VoltageSMUChannel() device1 = OssilaX200.OssilaX200(channels=[smu1], **config.get_section('OssilaX200_1')) smu2 = OssilaX200.VoltageSMUChannel() device2 = OssilaX200.OssilaX200(channels=[smu2], **config.get_section('OssilaX200_2'))

Basic Usage

[!IMPORTANT] If you only installed the core package, the following example will raise import errors from missing dependencies. To use the Agilent4156C, MA8X8, and OssilaX200 classes, you need to install the agilent, ma8x8, and ossila extras, respectively. To add all dependencies at once, install the full extra with this command: console pip install cohesivm[full]

With working implementations of the main components (Device, Interface, Measurement), setting up and running an experiment only takes a few lines of code:

```python from cohesivm import config from cohesivm.database import Database, Dimensions from cohesivm.experiment import Experiment from cohesivm.progressbar import ProgressBar from cohesivm.devices.agilent import Agilent4156C from cohesivm.interfaces import MA8X8 from cohesivm.measurements.iv import CurrentVoltageCharacteristic

Create a new or load an existing database

db = Database('Test.h5')

Configure the components

smu = Agilent4156C.SweepVoltageSMUChannel() device = Agilent4156C.Agilent4156C(channels=[smu], **config.getsection('Agilent4156C')) interface = MA8X8(comport=config.getoption('MA8X8', 'comport'), pixeldimensions=Dimensions.Circle(radius=0.425)) measurement = CurrentVoltageCharacteristic(startvoltage=-2.0, endvoltage=2.0, voltagestep=0.01, illuminated=True)

Combine the components in an experiment

experiment = Experiment( database=db, device=device, interface=interface, measurement=measurement, sampleid='testsample42', selectedcontacts=None )

Optionally set up a progressbar

pbar = ProgressBar(experiment)

Run the experiment

with pbar.show(): experiment.quickstart() ```

If you want to change the measurement device to a different one, you only need to adjust the lines for the Channel and the Device accordingly:

python from cohesivm.devices.ossila import OssilaX200 smu = OssilaX200.VoltageSMUChannel() device = OssilaX200.OssilaX200(channels=[smu], **config.get_section('OssilaX200'))

Graphical User Interfaces

If you work with Jupyter, you may use the Graphical User Interfaces (GUIs) which are implemented in the form of Jupyter Widgets.

Currently, three GUIs are available:

Experiment GUI

experiment-gui On the left panel "Control", you see the current ExperimentState, followed by a representation of the Interface and the control buttons at the bottom. The circles are annotated with the contact_ids and the colors correspond to their current state. On the right panel "Plot", the currently running Measurement is displayed. The plot is automatically updated as soon as new measurement data arrives in the data_stream of the Experiment object.

Database GUI

database-gui This GUI enables to display and filter the measurement data which is stored in an HDF5 file. At the top, you select to display the data grouped in terms of the Measurement or by the sample_name of the Experiment object. If you choose the former one, you may additionally filter the data by means of measurement parameters. The button to the very right of each data row enables you to copy the dataset path, to access it in the Database.

Analysis GUI

analysis-gui Similar to the Experiment GUI, the "Interface" panel represents the contacts with their respective IDs. They can be clicked to display the measured data in the "Plot" panel to the right. There, the arrows can be used to switch between functions that are defined in the Analysis class. The results of the functions, which are also implemented there, are shown in the table below.

Detailed guides to work with the GUIs can be found in the documentation.

Examples

[!NOTE] For a practical example, read the Real-World Example.

Run an Experiment

Follow the Basic Usage example to set up and run an Experiment. If you do not have all components ready yet, follow these tutorials:

To follow the other examples, you may just run the code from the Basic Usage example even if you do not have access to the hardware. This will fail but create an HDF5 file and store an empty dataset entry.

Manage the Data

List Datasets

After you collected some data and stored it in an HDF5 file, you can use the Database class to work with it. First, initialise the Database object and list the samples which are stored there:

```pycon

from cohesivm.database import Database db = Database('Test.h5') db.getsampleids() ['testsample42'] ```

This is exactly the sample_id which was specified when the Experiment was configured, and it can be used to retrieve the actual dataset path in the Database object:

```pycon

db.filterbysampleid('testsample42') ['/CurrentVoltageCharacteristic/55d96687ee75aa11:26464063430fe52f:a69a946e7a02e547:c8965a35118ce6fc:67a8bfb44702cfc7:8131a44cea4d4bb8/2024-07-01T10:44:59.033161-testsample_42'] ```

The resulting list contains the path strings for all Datasets with the specified sample_id (currently only one entry). These strings get quite long because they contain the name of the Measurement procedure, followed by a hashed representation of the settings dictionary, and finally the datetime combined with the sample_id.

Access Metadata

With a dataset path, you can retrieve information from the Metadata object which was created by the Experiment:

```pycon

dataset = db.filterbysampleid('testsample42')[0] metadata = db.loadmetadata(dataset) metadata.sampleid, metadata.device, metadata.interface, metadata.measurement ('testsample_42', 'Agilent4156C', 'MA8X8', 'CurrentVoltageCharacteristic') ```

Creating a new Dataset is less trivial because you need a fully qualified Metadata object, which asks for a large number of arguments. Anyway, this is usually handled by the Experiment class which also guarantees that the specified components are compatible.

As a test, you can use the Metadata object from above to initialize a new Dataset in the database:

```pycon

db.initializedataset(metadata) '/CurrentVoltageCharacteristic/55d96687ee75aa11:26464063430fe52f:a69a946e7a02e547:c8965a35118ce6fc:67a8bfb44702cfc7:8131a44cea4d4bb8/2024-07-01T10:46:05.910371-testsample_42' ```

This yields practically the same dataset path as before, only the datetime is different.

Work with Data Entries

Adding data entries to a Dataset is fairly simple since you only need to specify the dataset path and the contact_id (alongside the data of course):

```pycon

db.savedata(np.array([1], dtype=[('Quantity (Unit)', int)]), dataset) db.savedata(np.array([42], dtype=[('Quantity (Unit)', int)]), dataset, '1') ```

You should use a structured array by providing a dtype with named fields because it facilitates to store the quantity and the unit alongside the data.

Finally, you can load a data entry by specifying the contact_id, several entries by using a list of IDs, or load an entire Dataset, including the Metadata:

```pycon

db.loaddata(dataset, '0') array([(1,)], dtype=[('Quantity (Unit)', '<i4')]) db.loaddata(dataset, ['0', '1']) [array([(1,)], dtype=[('Quantity (Unit)', '<i4')]), array([(42,)], dtype=[('Quantity (Unit)', '<i4')])] db.load_dataset(dataset) ({'0': array([(1,)], dtype=[('Quantity (Unit)', '<i4')]), '1': array([(42,)], dtype=[('Quantity (Unit)', '<i4')])}, 'Metadata(CurrentVoltageCharacteristic, Agilent4156C, MA8X8)') ```

To work with a structured array, you need to know the names of the fields which are stored in the dtype property. With this name, you can access the data of an individual field:

```pycon

a = np.array([(1, 42)], dtype=[('Quantity1 (Unit1)', int), ('Quantity2 (Unit2)', int)]) a.dtype dtype([('Quantity1 (Unit1)', '<i4'), ('Quantity2 (Unit2)', '<i4')]) a['Quantity1 (Unit1)'] array([1]) ```

The Database class also implements methods for filtering datasets based on the settings of the Measurement. Check out the documentation of the filter_by_settings and filter_by_settings_batch to learn more.

Analyse the Results

The Analysis is tightly bound with the Measurement because this will determine how the data is shaped and which features you want to extract from it. Therefore, the base class should be extended as explained in this tutorial:

However, in the following example, the base class will be used to show the basic functionality.

Generate Data

Since the MA8X8 interface was used in the previous examples, the initialized Dataset should be filled with data accordingly. With the HDF5 file from the Basic Usage example, this script should do the job:

```python import numpy as np from cohesivm.database import Database

load existing data and corresponding metadata

db = Database('Test.h5') dataset = db.filterbysampleid('testsample42')[0] metadata = db.loadmetadata(dataset)

create a new dataset to not interfere with previous examples

dataset = db.initialize_dataset(metadata)

iterate over contact_ids and save data arrays

for contactid in metadata.contactids: db.savedata(np.array(range(10), dtype=[('Voltage (V)', float)]), dataset, contactid)

load the data

data, metadata = db.load_dataset(dataset) ```

Define Functions

Next, functions and plots must be defined:

```pycon

def maximum(contact_id: str) -> float: ... return max(data[contact_id]['Voltage (V)']) functions = {'Maximum': maximum} plots = {} # will be spared for simplicity (refer to the tutorial instead) ```

This approach seems too complex for what the function does, but it makes sense if you consider that this should be implemented in a separate Analysis class. There, the data is stored as a property and the functions (i.e., methods) have direct access to it. Due to the use of structured arrays, the label also needs to be stated explicitly. But, again, this will normally be available as a property of the class.

With vs. without Metadata

In the following, the class is initialized with and without using the Metadata from the dataset. The former approach has the advantage that all available fields could be accessed by the functions, e.g., values that are stored in the measurement_settings.

```pycon

from cohesivm.analysis import Analysis

without metadata, the contactpositiondict must be provided

analysis = Analysis(functions, plots, data, metadata.contactpositiondict)

with metadata, additional metadata fields can be used in the analysis

analysis = Analysis(functions, plots, (data, metadata)) analysis.metadata.measurement_settings['illuminated'] True ```

Use the Class

The main purposes of the Analysis are bundling functions for quick data analysis and providing the framework for the Analysis GUI. But it is also useful to generate maps of analysis results:

```pycon

analysis.generateresultmaps('Maximum')[0] array([[9., 9., 9., 9., 9., 9., 9., 9.], [9., 9., 9., 9., 9., 9., 9., 9.], [9., 9., 9., 9., 9., 9., 9., 9.], [9., 9., 9., 9., 9., 9., 9., 9.], [9., 9., 9., 9., 9., 9., 9., 9.], [9., 9., 9., 9., 9., 9., 9., 9.], [9., 9., 9., 9., 9., 9., 9., 9.], [9., 9., 9., 9., 9., 9., 9., 9.]]) ```

As expected, the maximum value of the generated data is placed in a 2D numpy array on locations corresponding to the contact_positions.

Package Reference

The package reference can be found in the documentation.

License

The source code of this project is licensed under the MIT license, and the hardware design and schematics are licensed under the CERN OHL v2 Permissive license.

Contributing

The contributing guidelines can be found here.

Citation

If you use this package for your research, please cite:

Wolf et al., (2025). COHESIVM: Combinatorial h+/e- Sample Investigation using Voltaic Measurements. Journal of Open Source Software, 10(106), 7291, https://doi.org/10.21105/joss.07291

BibTeX

@article{ Wolf2025, doi = {10.21105/joss.07291}, url = {https://doi.org/10.21105/joss.07291}, year = {2025}, publisher = {The Open Journal}, volume = {10}, number = {106}, pages = {7291}, author = {Maximilian Wolf and Selina Götz and Georg K.h. Madsen and Theodoros Dimopoulos}, title = {COHESIVM: Combinatorial h+/e- Sample Investigation using Voltaic Measurements}, journal = {Journal of Open Source Software} }

Contact

This project is developed by AIT Austrian Institute of Technology and TU Wien.

For questions, feedback, or support regarding COHESIVM, feel free to open an issue or reach out via email at maximilian.wolf@ait.ac.at.

Owner

  • Login: mxwalbert
  • Kind: user

JOSS Publication

COHESIVM: Combinatorial h+/e- Sample Investigation using Voltaic Measurements
Published
February 05, 2025
Volume 10, Issue 106, Page 7291
Authors
Maximilian Wolf ORCID
Center for Energy, AIT Austrian Institute of Technology GmbH, Austria, Institute of Materials Chemistry, TU Wien, Austria
Selina Götz ORCID
Center for Energy, AIT Austrian Institute of Technology GmbH, Austria
Georg K.h. Madsen ORCID
Institute of Materials Chemistry, TU Wien, Austria
Theodoros Dimopoulos ORCID
Center for Energy, AIT Austrian Institute of Technology GmbH, Austria
Editor
Rocco Meli ORCID
Tags
materials science combinatorial approach high-throughput analysis lab automation

Citation (CITATION.cff)

cff-version: "1.2.0"
authors:
- family-names: Wolf
  given-names: Maximilian
  orcid: "https://orcid.org/0000-0003-4917-7547"
- family-names: Götz
  given-names: Selina
  orcid: "https://orcid.org/0000-0003-4962-153X"
- family-names: Madsen
  given-names: Georg K. H.
  orcid: "https://orcid.org/0000-0001-9844-9145"
- family-names: Dimopoulos
  given-names: Theodoros
  orcid: "https://orcid.org/0000-0002-3620-9645"
doi: 10.5281/zenodo.14747442
message: If you use this software, please cite our article in the
  Journal of Open Source Software.
preferred-citation:
  authors:
  - family-names: Wolf
    given-names: Maximilian
    orcid: "https://orcid.org/0000-0003-4917-7547"
  - family-names: Götz
    given-names: Selina
    orcid: "https://orcid.org/0000-0003-4962-153X"
  - family-names: Madsen
    given-names: Georg K. H.
    orcid: "https://orcid.org/0000-0001-9844-9145"
  - family-names: Dimopoulos
    given-names: Theodoros
    orcid: "https://orcid.org/0000-0002-3620-9645"
  date-published: 2025-02-05
  doi: 10.21105/joss.07291
  issn: 2475-9066
  issue: 106
  journal: Journal of Open Source Software
  publisher:
    name: Open Journals
  start: 7291
  title: "COHESIVM: Combinatorial h+/e- Sample Investigation using
    Voltaic Measurements"
  type: article
  url: "https://joss.theoj.org/papers/10.21105/joss.07291"
  volume: 10
title: "COHESIVM: Combinatorial h+/e- Sample Investigation using Voltaic
  Measurements"

GitHub Events

Total
  • Create event: 4
  • Release event: 3
  • Issues event: 11
  • Delete event: 1
  • Issue comment event: 11
  • Push event: 9
  • Pull request event: 2
Last Year
  • Create event: 4
  • Release event: 3
  • Issues event: 11
  • Delete event: 1
  • Issue comment event: 11
  • Push event: 9
  • Pull request event: 2

Committers

Last synced: 5 months ago

All Time
  • Total Commits: 46
  • Total Committers: 2
  • Avg Commits per committer: 23.0
  • Development Distribution Score (DDS): 0.065
Past Year
  • Commits: 32
  • Committers: 1
  • Avg Commits per committer: 32.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
mxwalbert w****i@g****m 43
selinawillswissen s****g@c****t 3
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 4 months ago

All Time
  • Total issues: 7
  • Total pull requests: 1
  • Average time to close issues: 18 days
  • Average time to close pull requests: 4 minutes
  • Total issue authors: 2
  • Total pull request authors: 1
  • Average comments per issue: 1.86
  • Average comments per pull request: 0.0
  • Merged pull requests: 1
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 7
  • Pull requests: 1
  • Average time to close issues: 18 days
  • Average time to close pull requests: 4 minutes
  • Issue authors: 2
  • Pull request authors: 1
  • Average comments per issue: 1.86
  • Average comments per pull request: 0.0
  • Merged pull requests: 1
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • ericfell (6)
  • enricgrau (1)
Pull Request Authors
  • mxwalbert (2)
Top Labels
Issue Labels
Pull Request Labels

Packages

  • Total packages: 1
  • Total downloads:
    • pypi 19 last-month
  • Total dependent packages: 0
  • Total dependent repositories: 0
  • Total versions: 2
  • Total maintainers: 1
pypi.org: cohesivm

Combinatorial h+/e- Sample Investigation using Voltaic Measurements

  • Versions: 2
  • Dependent Packages: 0
  • Dependent Repositories: 0
  • Downloads: 19 Last month
Rankings
Dependent packages count: 10.5%
Average: 34.8%
Dependent repos count: 59.1%
Maintainers (1)
Last synced: 4 months ago

Dependencies

.github/workflows/paper.yml actions
  • actions/checkout v4 composite
  • actions/upload-artifact v4 composite
  • openjournals/openjournals-draft-action master composite
.github/workflows/pytest.yml actions
  • actions/checkout v4 composite
  • actions/setup-python v5 composite
docs/requirements.in pypi
  • bqplot *
  • h5py *
  • matplotlib *
  • myst-parser *
  • numpy <2.0
  • pyserial *
  • pyvisa *
  • sphinx *
  • sphinx-rtd-theme *
  • tqdm *
  • xtralien *
docs/requirements.txt pypi
  • alabaster ==0.7.16
  • asttokens ==2.4.1
  • babel ==2.16.0
  • bqplot ==0.12.43
  • certifi ==2024.7.4
  • charset-normalizer ==3.3.2
  • colorama ==0.4.6
  • comm ==0.2.2
  • contourpy ==1.2.1
  • cycler ==0.12.1
  • decorator ==5.1.1
  • docutils ==0.20.1
  • exceptiongroup ==1.2.2
  • executing ==2.0.1
  • fonttools ==4.53.1
  • h5py ==3.11.0
  • idna ==3.7
  • imagesize ==1.4.1
  • importlib-metadata ==8.2.0
  • importlib-resources ==6.4.0
  • ipython ==8.18.1
  • ipywidgets ==8.1.3
  • jedi ==0.19.1
  • jinja2 ==3.1.4
  • jupyterlab-widgets ==3.0.11
  • kiwisolver ==1.4.5
  • markdown-it-py ==3.0.0
  • markupsafe ==2.1.5
  • matplotlib ==3.9.1.post1
  • matplotlib-inline ==0.1.7
  • mdit-py-plugins ==0.4.1
  • mdurl ==0.1.2
  • myst-parser ==3.0.1
  • numpy ==1.26.4
  • packaging ==24.1
  • pandas ==2.2.2
  • parso ==0.8.4
  • pillow ==10.4.0
  • prompt-toolkit ==3.0.47
  • pure-eval ==0.2.3
  • pygments ==2.18.0
  • pyparsing ==3.1.2
  • pyserial ==3.5
  • python-dateutil ==2.9.0.post0
  • pytz ==2024.1
  • pyvisa ==1.14.1
  • pyyaml ==6.0.2
  • requests ==2.32.3
  • six ==1.16.0
  • snowballstemmer ==2.2.0
  • sphinx ==7.3.7
  • sphinx-rtd-theme ==2.0.0
  • sphinxcontrib-applehelp ==2.0.0
  • sphinxcontrib-devhelp ==2.0.0
  • sphinxcontrib-htmlhelp ==2.1.0
  • sphinxcontrib-jquery ==4.1
  • sphinxcontrib-jsmath ==1.0.1
  • sphinxcontrib-qthelp ==2.0.0
  • sphinxcontrib-serializinghtml ==2.0.0
  • stack-data ==0.6.3
  • tomli ==2.0.1
  • tqdm ==4.66.5
  • traitlets ==5.14.3
  • traittypes ==0.2.1
  • typing-extensions ==4.12.2
  • tzdata ==2024.1
  • urllib3 ==2.2.2
  • wcwidth ==0.2.13
  • widgetsnbextension ==4.0.11
  • xtralien ==2.11.0
  • zipp ==3.20.0
pyproject.toml pypi
  • h5py ~=3.8
  • matplotlib ~=3.7
  • numpy ~=1.21
  • tqdm ~=4.65