diff --git a/.coveragerc b/.coveragerc
deleted file mode 100755
index bdb9d85b8..000000000
--- a/.coveragerc
+++ /dev/null
@@ -1,4 +0,0 @@
-[run]
- branch = True
- source = Stoner
- relative_files = True
diff --git a/.github/workflows/build_conda.yaml b/.github/workflows/build_conda.yaml
index e2adc41bf..ef8b8b358 100755
--- a/.github/workflows/build_conda.yaml
+++ b/.github/workflows/build_conda.yaml
@@ -1,35 +1,35 @@
-
-name: Conda
-
-on:
- release:
- types: ['released', 'prereleased']
-
-# workflow_dispatch: # Un comment line if you also want to trigger action manually
-
-jobs:
- conda_deployment_with_new_tag:
- name: Conda deployment of package for platform ${{ matrix.os }} with Python ${{ matrix.python-version }}
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- - name: Conda environment creation and activation
- uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830
- with:
- python-version: "3.12"
- environment-file: recipe/build-env.yml
- activate-environment: build-environment
- auto-update-conda: true
- auto-activate-base: false
- show-channel-urls: true
- - name: Build and upload the conda packages
- uses: uibcdf/action-build-and-upload-conda-packages@4940704d2be7906d3bda5b00e3c3e4472fd7808f
- with:
- meta_yaml_dir: recipe
- overwrite: true
- python-version: "3.12"
- user: phygbu
- label: main
- token: ${{ secrets.ANACONDA }} # Replace with the right name of your secret
+
+name: Conda
+
+on:
+ release:
+ types: ['released', 'prereleased']
+
+# workflow_dispatch: # Un comment line if you also want to trigger action manually
+
+jobs:
+ conda_deployment_with_new_tag:
+ name: Conda deployment of package for platform ${{ matrix.os }} with Python ${{ matrix.python-version }}
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - name: Conda environment creation and activation
+ uses: mamba-org/setup-micromamba@add3a49764cedee8ee24e82dfde87f5bc2914462 # v2.0.7
+ with:
+ environment-file: recipe/build-env.yml
+ environment-name: build-environment
+ create-args: python=3.12
+ init-shell: bash
+ - name: Build and upload the conda packages
+ uses: uibcdf/action-build-and-upload-conda-packages@4940704d2be7906d3bda5b00e3c3e4472fd7808f
+ with:
+ meta_yaml_dir: recipe
+ overwrite: true
+ python-version: "3.12"
+ user: phygbu
+ label: main
+ token: ${{ secrets.ANACONDA }} # Replace with the right name of your secret
diff --git a/.github/workflows/run-tests-action.yaml b/.github/workflows/run-tests-action.yaml
index 9aeffcb4f..f1742b35a 100755
--- a/.github/workflows/run-tests-action.yaml
+++ b/.github/workflows/run-tests-action.yaml
@@ -1,92 +1,100 @@
-name: pytest
-on: push
-jobs:
- run_pytest:
- name: run-tests (${{ matrix.python-version }}, ${{ matrix.os }})
- runs-on: ${{ matrix.os }}
- defaults:
- run:
- shell: bash -l {0}
- strategy:
- fail-fast: false
- matrix:
- python-version: ["3.11", "3.12","3.13", "3.14"]
- os: ["ubuntu-latest"]
- steps:
- - name: Check out repository code
- uses: actions/checkout@v4
- - name: Install Conda environment with Micromamba
- uses: conda-incubator/setup-miniconda@v3
- with:
- environment-file: tests/test-env.yml
- python: ${{ matrix.python-version }}
- channels: conda-forge,phygbu
- channel-priority: flexible
- activate-environment: test-environment
- auto-activate-base: false
- - name: Conda information
- run: |
- conda info
- conda list
- conda config --show-sources
- conda config --show
- - name: install package
- run: pip install --no-deps .
- - name: Install headless server
- run: |
- sudo apt-get update
- sudo apt-get install xvfb
- sudo apt-get install qtbase5-dev
- - name: Test with xvfb
- run: |
- xvfb-run --auto-servernum /usr/share/miniconda/envs/test-environment/bin/pytest -n 2 --cov-report= --cov=Stoner --junitxml pytest.xml
- coverage xml
- env:
- TZ: Europe/London
- LC_CTYPE: en_GB.UTF-8
- GH_ACTION: True
- - name: Cleanup X11 server
- uses: bcomnes/cleanup-xvfb@v1
- - name: Coveralls Parallel
- uses: coverallsapp/github-action@v2
- with:
- flag-name: run-${{ join(matrix.*, '-') }}
- format: cobertura
- github-token: ${{ secrets.GITHUB_TOKEN }}
- - name: Upload Unit Test Results
- if: always()
- uses: actions/upload-artifact@v4
- with:
- name: Unit Test Results (Python ${{ matrix.python-version }})
- path: pytest.xml
- - name: Post Coveraage result to Codacy
- run: |
- export CODACY_PROJECT_TOKEN=${{ secrets.CODACY_PROJECT_TOKEN }}
- bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r coverage.xml
-
- publish-test-results:
- name: "Publish Unit Tests Results"
- needs: run_pytest
- runs-on: ubuntu-latest
- if: always()
-
- steps:
- - name: Download Artifacts
- uses: actions/download-artifact@v4
- with:
- path: artifacts
-
- - name: Publish Unit Test Results
- uses: EnricoMi/publish-unit-test-result-action@v2
- with:
- files: artifacts/**/*.xml
-
- coverage-finish:
- needs: run_pytest
- runs-on: ubuntu-latest
- steps:
- - name: Coveralls Finished
- uses: coverallsapp/github-action@v2
- with:
- parallel-finished: true
- carryforward: "run-1,run-2"
+name: pytest
+on: push
+jobs:
+ run_pytest:
+ name: run-tests (${{ matrix.python-version }}, ${{ matrix.os }})
+ runs-on: ${{ matrix.os }}
+ permissions:
+ contents: read
+ checks: write
+ defaults:
+ run:
+ shell: bash -l {0}
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: ["3.11", "3.12","3.13", "3.14"]
+ os: ["ubuntu-latest"]
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
+ - name: Install Mamba environment
+ uses: mamba-org/setup-micromamba@add3a49764cedee8ee24e82dfde87f5bc2914462 # v2.0.7
+ with:
+ environment-file: tests/test-env.yml
+ environment-name: test-environment
+ create-args: >-
+ python=${{ matrix.python-version }}
+ --channel-priority flexible
+ init-shell: bash
+ cache-downloads: true
+ cache-environment: true
+ - name: Mamba information
+ run: |
+ micromamba info
+ micromamba list
+ - name: install package
+ run: pip install --no-deps .
+ - name: Install headless server
+ run: |
+ sudo apt-get update
+ sudo apt-get install xvfb
+ sudo apt-get install qtbase5-dev
+ - name: Test with xvfb
+ run: |
+ xvfb-run --auto-servernum pytest -n 2 --cov-report= --cov=Stoner --junitxml pytest.xml
+ coverage xml
+ env:
+ TZ: Europe/London
+ LC_CTYPE: en_GB.UTF-8
+ GH_ACTION: True
+ - name: Cleanup X11 server
+ uses: bcomnes/cleanup-xvfb@9e016c43bb8d73fe7d5933d2ef00fd770c1a7c50 # v1.0.9
+ - name: Coveralls Parallel
+ uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2.3.7
+ with:
+ flag-name: run-${{ join(matrix.*, '-') }}
+ format: cobertura
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ - name: Upload Unit Test Results
+ if: always()
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ with:
+ name: Unit Test Results (Python ${{ matrix.python-version }})
+ path: pytest.xml
+ - name: Post Coveraage result to Codacy
+ run: |
+ export CODACY_PROJECT_TOKEN=${{ secrets.CODACY_PROJECT_TOKEN }}
+ bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r coverage.xml
+
+ publish-test-results:
+ name: "Publish Unit Tests Results"
+ needs: run_pytest
+ runs-on: ubuntu-latest
+ if: always()
+ permissions:
+ checks: write
+ pull-requests: write
+
+ steps:
+ - name: Download Artifacts
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+ with:
+ path: artifacts
+
+ - name: Publish Unit Test Results
+ uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2.23.0
+ with:
+ files: artifacts/**/*.xml
+
+ coverage-finish:
+ needs: run_pytest
+ runs-on: ubuntu-latest
+ permissions:
+ checks: write
+ steps:
+ - name: Coveralls Finished
+ uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2.3.7
+ with:
+ parallel-finished: true
+ carryforward: "run-1,run-2"
diff --git a/.idea/PythonCode.iml b/.idea/PythonCode.iml
new file mode 100755
index 000000000..d9e6024fc
--- /dev/null
+++ b/.idea/PythonCode.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100755
index 000000000..a5ae99b32
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.ipynb_checkpoints/Makefile-checkpoint b/.ipynb_checkpoints/Makefile-checkpoint
new file mode 100755
index 000000000..56dcc6bf5
--- /dev/null
+++ b/.ipynb_checkpoints/Makefile-checkpoint
@@ -0,0 +1,57 @@
+ifeq ($(OS),"Windows_NT")
+ SPHINX_BUILD = sphinx-build.bat
+else
+ SPHINX_BUILD = sphinx-build
+endif
+PYTHON_SETUP = python setup.py
+
+BRANCH = `git branch | grep '*' | cut -d ' ' -f 2`
+
+clean:
+ $(MAKE) -C doc clean
+ - rm dist/*
+ - rm -rf build/*
+ - find -name '__pycache__' -exec rm -rf {} \;
+
+test:
+ pytest -n `python -c 'import os;print(min(8,os.cpu_count()))'`
+
+check:
+ prospector -E -0 --profile-path=. -P .landscape.yml Stoner > prospector-report.txt
+
+black:
+ find Stoner -name '*.py' | xargs -d "\n" black -l 119
+ find doc/samples -name '*.py' | xargs -d "\n" black -l 80
+ find scripts -name '*.py' | xargs -d "\n" black -l 80
+
+commit: black
+ $(MAKE) -C doc readme
+ git add tests
+ git add Stoner
+ git add doc/samples
+ git commit -a
+ git push origin $(BRANCH)
+
+_build_wheel:
+ $(MAKE) -C doc readme
+ $(PYTHON_SETUP) sdist bdist_wheel --universal
+ twine upload dist/*
+
+wheel: clean test _build_wheel
+
+docbuild: FORCE
+ $(MAKE) -C doc clean
+ $(MAKE) -C doc html
+ ( cd ../gh-pages; git pull )
+ rsync -rcm --perms --chmod=ugo=rwX --delete --filter="P .git" --filter="P .nojekyll" doc/_build/html/ ../gh-pages/
+
+conda:
+ conda build --python=3.6 recipe &
+ conda build --python=3.7 recipe &
+ conda build --python 3.8 recipe &
+
+
+rtdbuild: export READTHEDOCS=1
+rtdbuild: docbuild
+
+FORCE:
diff --git a/.ipynb_checkpoints/README-checkpoint.rst b/.ipynb_checkpoints/README-checkpoint.rst
new file mode 100755
index 000000000..0e6a96796
--- /dev/null
+++ b/.ipynb_checkpoints/README-checkpoint.rst
@@ -0,0 +1,257 @@
+.. image:: https://travis-ci.com/stonerlab/Stoner-PythonCode.svg?branch=master
+ :target: https://travis-ci.com/stonerlab/Stoner-PythonCode
+
+.. image:: https://coveralls.io/repos/github/stonerlab/Stoner-PythonCode/badge.svg?branch=master
+ :target: https://coveralls.io/github/stonerlab/Stoner-PythonCode?branch=master
+
+.. image:: https://api.codacy.com/project/badge/Grade/372f2f9227134fab9c6c2f2ba83962ba
+ :target: https://www.codacy.com/app/stonerlab/Stoner-PythonCode?utm_source=github.com&utm_medium=referral&utm_content=stonerlab/Stoner-PythonCode&utm_campaign=Badge_Grade
+
+.. image:: https://badge.fury.io/py/Stoner.svg
+ :target: https://badge.fury.io/py/Stoner
+
+.. image:: https://anaconda.org/phygbu/stoner/badges/version.svg
+ :target: https://anaconda.org/phygbu/stoner
+
+.. image:: https://readthedocs.org/projects/stoner-pythoncode/badge/?version=latest
+ :target: http://stoner-pythoncode.readthedocs.io/en/latest/?badge=latest
+ :alt: Documentation Status
+
+.. image:: https://zenodo.org/badge/10057055.svg
+ :target: https://zenodo.org/badge/latestdoi/10057055
+
+
+Introduction
+============
+
+
+The *Stoner* Python package is a set of utility classes for writing data analysis code. It was written within
+the Condensed Matter Physics group at the University of Leeds as a shared resource for quickly writing simple
+programs to do things like fitting functions to data, extract curve parameters, churn through large numbers of
+small text data files and work with certain types of scientific image files.
+
+For a general introduction, users are referred to the Users Guide, which is part of the `online documentation`_ along with the
+API Reference guide. The `github repository`_ also contains some example scripts.
+
+Getting this Code
+==================
+
+.. image:: https://i.imgur.com/h4mWwM0.png
+ :target: https://www.youtube.com/watch?v=uZ_yKs11W18
+ :alt: Introduction and Installation Guide to Stoner Pythin Package
+ :width: 320
+
+The *Stoner* package requires h5py>=2.7.0, lmfit>=0.9.7, matplotlib>=2.0,numpy>=1.13, Pillow>=4.0,
+scikit-image>=0.13.0 & scipy>=1.0.0 and also optional depends on filemagic, npTDMS, imreg_dft and numba.
+
+Ananconda Python (and probably other scientific Python distributions) include nearly all of the dependencies, and the remaining
+dependencies are collected together in the **phygbu** repositry on anaconda cloud. The easiest way to install the Stoner package is,
+therefore, to install the most recent Anaconda Python distribution.
+
+Compatibility
+--------------
+
+Versions 0.9.x (stable branch) are compatible with Python 2.7, 3.5, 3.6 and 3.7. The latest 0.9.6 version is also compatible with Python 3.8
+The development verstion (0.10, master branch) is compatible with Python 3.6, 3.7 and 3.8 but not 2.7.
+
+Conda packages are prepared for the stable branch and when the development branch enters beta testing. Pip wheels are prepared for selected stable releases only.
+
+Installation
+------------
+
+After installing the current Anaconda version, open a terminal (Mac/Linux) or Anaconda Prompt (Windows) an do:
+
+.. code-block:: sh
+
+ conda install -c phygbu Stoner
+
+If you are not using Anaconda python, then pip should also work:
+
+.. code-block:: sh
+
+ pip install Stoner
+
+This will install the Stoner package and any missing dependencies into your current Python environment. Since the package is under fairly
+constant updates, you might want to follow the development with git. The source code, along with example scripts
+and some sample data files can be obtained from the github repository: https://github.com/stonerlab/Stoner-PythonCode
+
+Overview
+========
+
+The main part of the **Stoner** package provides four basic top-level classes that describe:
+ - an individual file of experimental data (**Stoner.Data**),
+ - an individual experimental image (**Stoner.ImageFile**),
+ - a list (such as a directory tree on disc) of many experimental files (**Stoner.DataFolder**)
+ - a list (such as a directory tree on disc) of many image files (**Stoner.ImageFolder**).
+
+For our research, a typical single experimental data file is essentially a single 2D table of floating point
+numbers with associated metadata, usually saved in some ASCII text format. This seems to cover most experiments
+in the physical sciences, but it you need a more complex format with more dimensions of data, we suggest
+you look elsewhere.
+
+Increasingly we seem also to need process image files and so partnering the experimental measurement file classes,
+we have a parallel set of classes for interacting with image data.
+
+The general philosophy used in the package is to work with data by using methods that transform the data in place.
+Additionally, many of the analysis methods pass a copy of the data as their return value, allowing a sequence of
+operations to be chained together in one line.
+
+This is a *data-centric* approach - we have some data and we do various operations on it to get to our result. In
+contrasr, traditional functional programming thinks in terms of various functions into which you pass data.
+
+
+Data and Friends
+----------------
+
+**Stoner.Data** is the core class for representing individual experimental data sets.
+It is actually composed of several mixin classes that provide different functionality, with methods
+to examine and manipulate data, manage metadata, load and save data files, plot results and carry out various analysis tasks.
+It has a large number of sub classes - most of these are in Stoner.formats and are used to handle the loading of specific
+file formats.
+
+ImageFile
+---------
+
+**Stoner.ImageFile** is the top-level class for managing image data. It is the equivalent of **Stoner.Data** and maintains
+metadta and comes with a number of methods to manipulate image data. The image data is stored internally as a masked numpy
+array and where possible the masking is taken into account when carrying out image analysis tasks. Through some abuse of
+the Python class system, functions in the scpy.ndimage and scikit-image modules are mapped into methods of the ImageFile
+class allowing a very rich set of operations on the data sets. The default IO methods handle tiff and png images and can
+store the metadata of the ImageFile within those file formats.
+
+DataFolder
+----------
+
+**Stoner.DataFolder** is a class for assisting with the work of processing lots of files in a common directory
+structure. It provides methods to list. filter and group data according to filename patterns or metadata and then to execute
+a function on each file or group of files and then collect metadata from each file in turn. A key feature of DataFolder is
+its ability to work with the collated metadata from the individual files that are held in the DataFolder.
+In combination with its ability to walk through a complete heirarchy of groups of
+**Data** objects, the handling of the common metadata provides powerful tools for quickly writing data reduction scripts.
+
+ImageFolder
+-----------
+
+**Stoner.ImageFolder** is the equivalent of DataFolder but for images (although technically a DataFolder can contain ImageFile
+objects, the ImageFolder class offers additional Image specific functionality). There is a subclass of ImageFolder,
+**Stoner.Image.ImageStack** that uses a 3D numpy array as it's primary image store which permits faster access
+(at the expense of a larger memory footprint) than the lazy loading ordered dictionary of **ImageFolder**
+
+Other Modules and Classes
+-------------------------
+
+The **Stoner.HDF5** module provides some additional classes to manipulate *Data* and *DataFolder* objects within HDF5
+format files. HDF5 is a common chouse for storing data from large scale facilties, although providing a way to handle
+arbitary HDF5 files is beyond the scope of this package at this time - the format is much too complex and flexible to make that
+an easy task. Rather it provides a way to work with large numbers of experimental sets using just a single file which may be less
+brutal to your computer's OS than having directory trees with millions of individual files.
+
+The module also provides some classes to support loading some particular HDF5 flavoured files into **Data** and **ImageFile**
+objects.
+
+The **Stoner.Zip** module provides a similar set of classes to **Stoner.HDF5** but working with the ubiquitous zip compressed file format.
+
+Resources
+==========
+
+Included in the `github repository`_ are a (small) collection of sample scripts
+for carrying out various operations and some sample data files for testing the loading and processing of data. There is also a
+`User_Guide`_ as part of this documentation, along with a :doc:`complete API reference `
+
+Contact and Licensing
+=====================
+
+The lead developer for this code is `Dr Gavin Burnell`_ , but many current and former members of
+the CM Physics group have contributed code, ideas and bug testing.
+
+The User Guide gives the current list of other contributors to the project.
+
+This code and the sample data are all (C) The University of Leeds 2008-2021 unless otherwise indficated in the source
+file. The contents of this package are licensed under the terms of the GNU Public License v3
+
+Recent Changes
+==============
+
+Current PyPi Version
+--------------------
+
+The current version of the package on PyPi will be the stable branch until the development branch enters beta testing, when we start
+making beta packages available.
+
+Development Version
+-------------------
+
+The current development version is hosted in the master branch of the repository and will become version 0.10.
+
+New Features in 0.10-dev include:
+
+ * Refactor Stoner.Core.DataFile to move functionality to mixin classes
+ * Start implementing PEP484 Type hinting
+ * Support pathlib for paths
+ * Switch from Tk based dialogs to Qt5 ones
+ * Refactoring the **baseFolder** class so that sub-groups are stored in an attribute that is an instance of a custom
+ dictionary with methods to prune and filter in the virtual tree of sub-folders.
+ * Refactoring of the **ImageArray** and **ImageFile** so that binding of external functions as methods is done at
+ class definition time rather than at runtime with overly complex __getattr__ methods. The longer term goal is to
+ depricate the use of ImageArray in favour of just using ImageFile.
+ * Introduce interactive selection of boxes, lines and mask regions for interactive Matplotlib backends.
+
+Build Status
+~~~~~~~~~~~~
+
+Version 0.7 onwards are tested using the Travis-CI services with unit test coverage assessed by Coveralls.
+
+Version 0.9 is tested with Python 2.7, 3.5, 3.6 using the standard unittest module.
+
+The development version - which will be 0.10 is tested using **pytest** with Python 3.6, Python 3.7 and Python 3.8.
+
+
+Citing the Stoner Package
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We maintain a digital object identifier (doi) for this package (linked to on the status bar at the top of this readme) and
+encourage any users to cite this package via that doi.
+
+Stable Versions
+---------------
+
+Online documentation for all versions can be found on the ReadTheDocs pages `online documentation`_
+
+Version 0.9 is the current stable version. This is the last version to support Python 2 and 3<3.6. Features of this release are:
+
+ * Refactoring of the package into a more granual core, plot, formats, folders packages with submodules
+ * Overhaul of the documentation and user guide
+ * Dropping support for the older Stoner.Image.stack.ImageStack class
+ * Droppping support for matplotlib<2.0
+ * Support for Python 3.7 (and 3.8 from 0.9.6)
+ * Unit tests now > 80% coverage across the package.
+
+Version 0.8 is the previous stable release. The main new features were:
+
+ * Reworking of the ImageArray, ImageFile and ImageFolder with many updates and new features.
+ * New mixin based ImageStack2 that can manipulate a large number of images in a 3D numpy array
+ * Continued re-factoring of DataFolder using the mixin approach
+ * Further increases to unit-test coverage, bug fixes and refactoring of some parts of the code.
+ * _setas objects implement a more complete MutableMapping interface and also support +/- operators.
+ * conda packages now being prepared as the preferred package format
+
+0.8.2 was the final release of the 0.8.0 branch
+
+The old stable version is 0.7.2. Features of 0.7.2 include
+
+ * Replace older AnalyseFile and PlotFile with mixin based versions AnalysisMixin and PlotMixin
+ * Addition of Stoner.Image package to handle image analysis
+ * Refactor DataFolder to use Mixin classes
+ * DataFolder now defaults to using :py:class:`Stoner.Core.Data`
+ * DataFolder has an options to skip iterating over empty Data files
+ * Further improvements to :py:attr:`Stoner.Core.DataFile.setas` handline.
+
+No further relases will be made to 0.7.x.
+
+0.6, 0.7 should work on Python 2.7 and 3.5
+0.8 is also tested on Python 3.6
+
+.. _online documentation: http://stoner-pythoncode.readthedocs.io/en/latest/
+.. _github repository: http://www.github.com/stonerlab/Stoner-PythonCode/
+.. _Dr Gavin Burnell: http://www.stoner.leeds.ac.uk/people/gb
+.. _User_Guide: http://stoner-pythoncode.readthedocs.io/en/latest/UserGuide/ugindex.html
\ No newline at end of file
diff --git a/.spyproject/config/backups/codestyle.ini.bak b/.spyproject/config/backups/codestyle.ini.bak
new file mode 100755
index 000000000..71eedf943
--- /dev/null
+++ b/.spyproject/config/backups/codestyle.ini.bak
@@ -0,0 +1,8 @@
+[codestyle]
+indentation = True
+edge_line = True
+edge_line_columns = 79
+
+[main]
+version = 0.2.0
+
diff --git a/.spyproject/config/backups/encoding.ini.bak b/.spyproject/config/backups/encoding.ini.bak
new file mode 100755
index 000000000..44707b046
--- /dev/null
+++ b/.spyproject/config/backups/encoding.ini.bak
@@ -0,0 +1,6 @@
+[encoding]
+text_encoding = utf-8
+
+[main]
+version = 0.2.0
+
diff --git a/.spyproject/config/backups/vcs.ini.bak b/.spyproject/config/backups/vcs.ini.bak
new file mode 100755
index 000000000..6b8d7a36d
--- /dev/null
+++ b/.spyproject/config/backups/vcs.ini.bak
@@ -0,0 +1,7 @@
+[vcs]
+use_version_control = False
+version_control_system =
+
+[main]
+version = 0.2.0
+
diff --git a/.spyproject/config/backups/workspace.ini.bak b/.spyproject/config/backups/workspace.ini.bak
new file mode 100755
index 000000000..17dc6fa0c
--- /dev/null
+++ b/.spyproject/config/backups/workspace.ini.bak
@@ -0,0 +1,12 @@
+[workspace]
+restore_data_on_startup = True
+save_data_on_exit = True
+save_history = True
+save_non_project_files = False
+project_type = 'empty-project-type'
+recent_files = ['Stoner\\folders\\methods.py', 'scripts\\VSManalysis_v2.py', 'Stoner\\tools\\widgets.py', 'tests\\stoner\\tools\\test_widgets.py', 'Stoner\\core\\base.py', 'Stoner\\analysis\\utils.py']
+
+[main]
+version = 0.2.0
+recent_files = []
+
diff --git a/.spyproject/config/codestyle.ini b/.spyproject/config/codestyle.ini
new file mode 100755
index 000000000..71eedf943
--- /dev/null
+++ b/.spyproject/config/codestyle.ini
@@ -0,0 +1,8 @@
+[codestyle]
+indentation = True
+edge_line = True
+edge_line_columns = 79
+
+[main]
+version = 0.2.0
+
diff --git a/.spyproject/config/defaults/defaults-codestyle-0.2.0.ini b/.spyproject/config/defaults/defaults-codestyle-0.2.0.ini
new file mode 100755
index 000000000..3772dc99e
--- /dev/null
+++ b/.spyproject/config/defaults/defaults-codestyle-0.2.0.ini
@@ -0,0 +1,5 @@
+[codestyle]
+indentation = True
+edge_line = True
+edge_line_columns = 79
+
diff --git a/.spyproject/config/defaults/defaults-encoding-0.2.0.ini b/.spyproject/config/defaults/defaults-encoding-0.2.0.ini
new file mode 100755
index 000000000..d76cad0db
--- /dev/null
+++ b/.spyproject/config/defaults/defaults-encoding-0.2.0.ini
@@ -0,0 +1,3 @@
+[encoding]
+text_encoding = utf-8
+
diff --git a/.spyproject/config/defaults/defaults-vcs-0.2.0.ini b/.spyproject/config/defaults/defaults-vcs-0.2.0.ini
new file mode 100755
index 000000000..782612f7d
--- /dev/null
+++ b/.spyproject/config/defaults/defaults-vcs-0.2.0.ini
@@ -0,0 +1,4 @@
+[vcs]
+use_version_control = False
+version_control_system =
+
diff --git a/.spyproject/config/defaults/defaults-workspace-0.2.0.ini b/.spyproject/config/defaults/defaults-workspace-0.2.0.ini
new file mode 100755
index 000000000..d4bbff1bb
--- /dev/null
+++ b/.spyproject/config/defaults/defaults-workspace-0.2.0.ini
@@ -0,0 +1,6 @@
+[workspace]
+restore_data_on_startup = True
+save_data_on_exit = True
+save_history = True
+save_non_project_files = False
+
diff --git a/.spyproject/config/encoding.ini b/.spyproject/config/encoding.ini
new file mode 100755
index 000000000..44707b046
--- /dev/null
+++ b/.spyproject/config/encoding.ini
@@ -0,0 +1,6 @@
+[encoding]
+text_encoding = utf-8
+
+[main]
+version = 0.2.0
+
diff --git a/.spyproject/config/vcs.ini b/.spyproject/config/vcs.ini
new file mode 100755
index 000000000..6b8d7a36d
--- /dev/null
+++ b/.spyproject/config/vcs.ini
@@ -0,0 +1,7 @@
+[vcs]
+use_version_control = False
+version_control_system =
+
+[main]
+version = 0.2.0
+
diff --git a/.spyproject/config/workspace.ini b/.spyproject/config/workspace.ini
new file mode 100755
index 000000000..17dc6fa0c
--- /dev/null
+++ b/.spyproject/config/workspace.ini
@@ -0,0 +1,12 @@
+[workspace]
+restore_data_on_startup = True
+save_data_on_exit = True
+save_history = True
+save_non_project_files = False
+project_type = 'empty-project-type'
+recent_files = ['Stoner\\folders\\methods.py', 'scripts\\VSManalysis_v2.py', 'Stoner\\tools\\widgets.py', 'tests\\stoner\\tools\\test_widgets.py', 'Stoner\\core\\base.py', 'Stoner\\analysis\\utils.py']
+
+[main]
+version = 0.2.0
+recent_files = []
+
diff --git a/Stoner/__init__.py b/Stoner/__init__.py
index eb586de48..b33e05ff4 100755
--- a/Stoner/__init__.py
+++ b/Stoner/__init__.py
@@ -37,8 +37,8 @@
Options = _Options()
-__version_info__ = ("0", "11", "1")
-__version__ = ".".join(__version_info__)
+__version__ = "0.11.1"
+__version_info__ = tuple(__version__.split("."))
__homepath__ = pathlib.Path(__file__).parent.resolve()
__datapath__ = (__homepath__ / ".." / "sample-data").resolve()
diff --git a/Stoner/folders/core.py b/Stoner/folders/core.py
index 84339c316..47fc807a5 100755
--- a/Stoner/folders/core.py
+++ b/Stoner/folders/core.py
@@ -220,6 +220,7 @@ def __new__(cls, *args, **kwargs):
self._root = "."
self._default_store = None
self.directory = None
+ self.executor = None
return self
def __init__(self, *args, **kwargs):
@@ -654,6 +655,11 @@ def __clone__(self, other=None, attrs_only=False):
######## Methods to implement the MutableMapping abstract methods #########
######## And to provide a mapping interface that mainly access groups #####
+ def __del__(self):
+ """Clean up the exececutor if it is defined."""
+ if self.executor:
+ self.executor.shutdown()
+
def __getitem__(self, name):
"""Try to get either a group or an object.
diff --git a/Stoner/tools/file.py b/Stoner/tools/file.py
index e4e9e864a..f0ae36bca 100755
--- a/Stoner/tools/file.py
+++ b/Stoner/tools/file.py
@@ -67,7 +67,13 @@ def test_is_zip(filename, member=""):
"""
if not filename or str(filename) == "":
return False
- if zipfile.is_zipfile(filename):
+ if isinstance(filename, (bytes, bytearray)) and b"\x00" in filename:
+ return False
+ try:
+ is_zip = zipfile.is_zipfile(filename)
+ except (ValueError, TypeError, OSError):
+ return False
+ if is_zip:
return filename, member
part = os.path.basename(filename)
newfile = os.path.dirname(filename)
diff --git a/doc/UserGuide/install.rst b/doc/UserGuide/install.rst
index 5ebce8e2b..35a0984d0 100755
--- a/doc/UserGuide/install.rst
+++ b/doc/UserGuide/install.rst
@@ -55,9 +55,9 @@ machine then::
should install the current master branch. Otherwise download the zip file from the github site and do::
- python setup.py install
+ pip install .
-to insatall it locally.
+to install it locally.
Using the Development Version of the Stoner Package
===================================================
diff --git a/doc/conf.py b/doc/conf.py
index 0b0f5b41e..7edda995d 100755
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -71,10 +71,13 @@
# |version| and |release|, also used in various other places throughout the
# built documents.
#
+try:
+ from importlib.metadata import PackageNotFoundError, version as _pkg_version
+ release = _pkg_version("Stoner")
+except PackageNotFoundError:
+ release = "unknown"
# The short X.Y version.
-version = '1'
-# The full version, including alpha/beta/rc tags.
-release = '1'
+version = ".".join(release.split(".")[:2])
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 000000000..6c25c2b82
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,85 @@
+[build-system]
+requires = ["setuptools>=61.0", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "Stoner"
+dynamic = ["version"]
+description = "Library to help write data analysis tools for experimental condensed matter physics."
+readme = {file = "README.rst", content-type = "text/x-rst"}
+requires-python = ">=3.11"
+license = {text = "GPLv3"}
+authors = [
+ {name = "Gavin Burnell", email = "g.burnell@leeds.ac.uk"},
+]
+keywords = ["Data-Analysis", "Physics"]
+classifiers = [
+ "Development Status :: 4 - Beta",
+ "Intended Audience :: Science/Research",
+ "Topic :: Scientific/Engineering",
+ "Topic :: Scientific/Engineering :: Physics",
+ "Operating System :: MacOS :: MacOS X",
+ "Operating System :: Microsoft :: Windows",
+ "Operating System :: POSIX",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: 3.14",
+ "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
+]
+dependencies = [
+ "scipy>=1.14",
+ "numpy>=2.0",
+ "matplotlib>=3.8",
+ "scikit-image>=0.24",
+ "h5py",
+ "cycler>=0.10.0",
+ "filemagic>=1.6",
+ "image-registration>=0.2.1",
+ "lmfit>=1.3",
+ "memoization>=0.1.4",
+ "npTDMS>=1.9.0",
+ "python-dateutil>=2.8.0",
+ "statsmodels",
+ "tabulate>=0.9",
+ "imreg_dft>=2.0",
+ "multiprocess>=0.70",
+ "dill>=0.2.8",
+ "urllib3>=1.26",
+ "seaborn>=0.13",
+ "looseversion>=1.0",
+ "chardet>=5.2.0",
+]
+
+[project.optional-dependencies]
+PrettyPrint = ["tabulate>=0.7.5"]
+mimetype_detection = ["magic"]
+TDMS = ["nptdms"]
+numba = ["numba"]
+cv2 = ["opencv-python"]
+image_alignment = ["imreg_dft", "image_registration"]
+
+[project.urls]
+Homepage = "https://github.com/gb119/Stoner-PythonCode"
+Repository = "https://github.com/gb119/Stoner-PythonCode"
+
+[tool.setuptools.dynamic]
+version = {attr = "Stoner.__version__"}
+
+[tool.setuptools.packages.find]
+where = ["."]
+include = ["Stoner*"]
+
+[tool.setuptools.package-data]
+Stoner = ["stylelib/*.mplstyle"]
+
+[tool.coverage.run]
+branch = true
+source = ["Stoner"]
+relative_files = true
+
+[tool.pydocstyle]
+ignore = ["D203"]
+
+[tool.pytest.ini_options]
+testpaths = ["tests"]
diff --git a/recipe/build-env.yml b/recipe/build-env.yml
index 0e2dd43ad..fb10f33ee 100755
--- a/recipe/build-env.yml
+++ b/recipe/build-env.yml
@@ -6,6 +6,7 @@ channels:
dependencies:
- conda-build
- anaconda-client
- - setuptools
+ - setuptools >=61.0
- wheel
+ - build
- twine
diff --git a/recipe/meta.yaml b/recipe/meta.yaml
index 995fa2f32..e5d24e432 100755
--- a/recipe/meta.yaml
+++ b/recipe/meta.yaml
@@ -1,11 +1,10 @@
-{% set data = load_setup_py_data() %}
+{% set version_match = load_file_regex(load_file="Stoner/__init__.py", regex_pattern='__version__\s*=\s*"([^"]+)"') %}
+{% set version = version_match[1] %}
{% set name = "Stoner" %}
-{% set file_ext = "tar.gz" %}
-
package:
name: '{{ name|lower }}'
- version: {{ data.get('version') }}
+ version: {{ version }}
source:
path: ..
@@ -13,13 +12,13 @@ source:
build:
noarch: python
number: 1
- script: {{ PYTHON }} setup.py install --single-version-externally-managed --record=record.txt
+ script: {{ PYTHON }} -m pip install . -vv --no-deps --no-build-isolation
requirements:
build:
- python >=3.11
- - pytest
- - pytest-runner
+ - pip
+ - setuptools >=61.0
run:
- python >=3.11
diff --git a/setup.cfg b/setup.cfg
index 85a389711..65aabd5e6 100755
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,16 +1,2 @@
-[build_sphinx]
-source-dir = doc/
-build-dir = doc/_build
-all_files = 1
-
-[upload_sphinx]
-upload-dir = doc/_build/html
-
-[bdist_wheel]
-universal=1
-
-[aliases]
-test=pytest
-
[pydocstyle]
ignore = D203
diff --git a/setup.py b/setup.py
deleted file mode 100755
index 552943be2..000000000
--- a/setup.py
+++ /dev/null
@@ -1,131 +0,0 @@
-import io
-import os
-import re
-import sys
-from os import environ as env
-
-from setuptools import find_packages, setup
-
-
-def get_version():
- init_name=os.path.join(os.path.dirname(__file__),"Stoner","__init__.py")
- with open(init_name,"r") as init:
- for line in init:
- line=line.strip()
- if line.startswith("__version_info__"):
- parts=line.split("=")
- __version_info__=eval(parts[1].strip())
- return '.'.join(__version_info__)
- raise ValueError(f"Failed to get version info from {init_name}")
-
-def yield_sphinx_only_markup(lines):
- """
- :param file_inp: a `filename` or ``sys.stdin``?
- :param file_out: a `filename` or ``sys.stdout`?`
-
- """
- substs = [
- ## Selected Sphinx-only Roles.
- #
- (r':abbr:`([^`]+)`', r'\1'),
- (r':ref:`([^`]+)`', r'`\1`_'),
- (r':term:`([^`]+)`', r'**\1**'),
- (r':dfn:`([^`]+)`', r'**\1**'),
- (r':(samp|guilabel|menuselection):`([^`]+)`', r'``\2``'),
- (r':py:[a-z]+:`([^`]+)`', r'\1'),
-
-
-
- ## Sphinx-only roles:
- # :foo:`bar` --> foo(``bar``)
- # :a:foo:`bar` XXX afoo(``bar``)
- #
- #(r'(:(\w+))?:(\w+):`([^`]*)`', r'\2\3(``\4``)'),
- (r':(\w+):`([^`]*)`', r'\1(``\2``)'),
-
-
- ## Sphinx-only Directives.
- #
- (r'\.\. doctest', r'code-block'),
- (r'\.\. plot::', r'.. '),
- (r'\.\. seealso', r'info'),
- (r'\.\. glossary', r'rubric'),
- (r'\.\. figure::', r'.. '),
-
-
- ## Other
- #
- (r'\|version\|', r'x.x.x'),
- ]
-
- regex_subs = [ (re.compile(regex, re.IGNORECASE), sub) for (regex, sub) in substs ]
-
- def clean_line(line):
- try:
- for (regex, sub) in regex_subs:
- line = regex.sub(sub, line)
- except Exception as ex:
- print("ERROR: %s, (line(%s)"%(regex, sub))
- raise ex
-
- return line
-
- for line in lines:
- yield clean_line(line)
-
-def read(fname):
- mydir=os.path.dirname(__file__)
- with io.open(os.path.join(mydir, fname)) as fd:
- return fd.readlines()
-
-def requires(fname):
- mydir=os.path.dirname(__file__)
- with io.open(os.path.join(mydir, fname)) as fd:
- entries=fd.readlines()
- entries=[entry for entry in entries if entry[0] not in " #\n\t"]
- return entries
-
-if "READTHEDOCS" in env:
- requyirements="doc/requirements.txt"
-else:
- requyirements="requirements.txt"
-
-setup(
- name = "Stoner",
- python_requires='>3.7',
- version = str(get_version()),
- author = "Gavin Burnell",
- author_email = "g.burnell@leeds.ac.uk",
- description = "Library to help write data analysis tools for experimental condensed matter physics.",
- license = "GPLv3",
- keywords = "Data-Analysis Physics",
- url = "http://github.com/~gb119/Stoner-PythonCode",
- packages=find_packages(),
- package_dir={'Stoner': 'Stoner'},
- package_data={'Stoner':['stylelib/*.mplstyle']},
- test_suite="tests",
- # setup_requires=['pytest-runner'],
- # tests_require=['pytest'],
- install_requires=requires(requyirements),
- extras_require = { "PrettyPrint":["tabulate>=0.7.5"],
- "mimetype_detection":["magic"],
- "TDMS":["nptdms"],
- "numba":["numba"],
- "cv2":["cv2"],
- "image_alignment":["imreg_dft","image_registration"]},
- long_description= ''.join(yield_sphinx_only_markup(read('README.rst'))),
- classifiers=[
- "Development Status :: 4 - Beta",
- "Intended Audience :: Science/Research",
- "Topic :: Scientific/Engineering",
- "Topic :: Scientific/Engineering :: Physics",
- 'Operating System :: MacOS :: MacOS X',
- 'Operating System :: Microsoft :: Windows',
- 'Operating System :: POSIX',
- "Programming Language :: Python :: 3.7",
- "Programming Language :: Python :: 3.8",
- "Programming Language :: Python :: 3.9",
- "Programming Language :: Python :: 3.10",
- "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
- ],
-)
diff --git a/tests/Stoner/Image/test_wdigets.py b/tests/Stoner/Image/test_wdigets.py
deleted file mode 100755
index 6abc66eb4..000000000
--- a/tests/Stoner/Image/test_wdigets.py
+++ /dev/null
@@ -1,138 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Test the Image Widgets used for selections
-
-@author: phygbu
-"""
-import os
-import threading
-import time
-
-import numpy as np
-import pytest
-from matplotlib.backend_bases import Event
-
-import Stoner
-from Stoner.Image.widgets import send_event as _event
-
-
-def _trigger(image):
- time.sleep(5)
- _event(image, "on_click", xdata=1, ydata=1, button=1)
- for coord in np.linspace(1, 100, 51):
- _event(image, "draw_line", xdata=coord, ydata=coord)
- _event(image, "on_click", xdata=coord, ydata=coord, button=1)
-
-
-def _trigger2(image):
- time.sleep(5)
- _event(image, "keypress", xdata=50, ydata=75, key="x")
- _event(image, "on_click", xdata=50, ydata=75, button=1)
-
-
-def _trigger3(image):
- time.sleep(5)
- _event(image, "keypress", xdata=50, ydata=75, key="y")
- _event(image, "on_click", xdata=50, ydata=75, button=1)
-
-
-def _trigger4(image):
- time.sleep(5)
- select = image._image._select
- event1 = Event("fake", select.fig.canvas)
- event1.xdata = 25
- event1.ydata = 25
- event2 = Event("fake", select.fig.canvas)
- event2.xdata = 75
- event2.ydata = 50
- select.on_select(event1, event2)
- time.sleep(2)
- _event(image, "finish", key="enter")
-
-
-def _trigger5(image, mode):
- time.sleep(5)
- _event(image, ["draw", "on_click"], xdata=50, ydata=25, button=1, dblclick=False)
- _event(image, ["draw", "on_click"], xdata=75, ydata=50, button=1, dblclick=False)
- _event(image, "keypress", xdata=50, ydata=75, key=mode.lower()[0])
- if mode == "c": # add some extra points:
- _event(image, ["draw", "on_click"], xdata=30, ydata=40, button=1, dblclick=False)
- _event(image, ["draw", "on_click"], xdata=30, ydata=30, button=1, dblclick=False)
- _event(image, "keypress", xdata=50, ydata=75, key="i")
- time.sleep(2)
- _event(image, "keypress", xdata=50, ydata=75, key="enter")
-
-
-def _trigger6(image, mode):
- time.sleep(5)
- _event(image, ["draw", "on_click"], xdata=50, ydata=25, button=1, dblclick=False)
- _event(image, ["draw", "on_click"], xdata=75, ydata=50, button=1, dblclick=False)
- time.sleep(2)
- _event(image, "keypress", xdata=50, ydata=75, key="escape")
-
-
-def test_profile_line():
- os.chdir(Stoner.__homepath__ / ".." / "sample-data")
- img = Stoner.ImageFile("Sample_Image_2017-10-15_100.hdf5")
- thread = threading.Thread(target=_trigger, args=(img,))
- thread.start()
- result = img.profile_line()
- assert len(result) == 142
- assert result.x.min() == 0.0
- assert np.isclose(result.x.max(), 140, atol=0.01)
- assert np.isclose(result.y.mean(), 26548.72, atol=0.01)
- thread = threading.Thread(target=_trigger2, args=(img,))
- thread.start()
- result = img.profile_line()
- assert len(result) == 101
- assert result.x.min() == 0.0
- assert result.x.max() == 100.0
- assert np.isclose(result.y.mean(), 20022.16, atol=0.01)
- thread = threading.Thread(target=_trigger3, args=(img,))
- thread.start()
- result = img.profile_line()
- assert len(result) == 101
- assert result.x.min() == 0.0
- assert result.x.max() == 100.0
- assert np.isclose(result.y.mean(), 27029.16, atol=0.01)
-
-
-def test_crop_with_ui():
- os.chdir(Stoner.__homepath__ / ".." / "sample-data")
- img = Stoner.ImageFile("Sample_Image_2017-10-15_100.hdf5")
- thread = threading.Thread(target=_trigger4, args=(img,))
- thread.start()
- result = img.crop()
- assert result.shape == (25, 50)
-
-
-def test_mask_select():
- os.chdir(Stoner.__homepath__ / ".." / "sample-data")
- img = Stoner.ImageFile("Sample_Image_2017-10-15_100.hdf5")
- thread = threading.Thread(target=_trigger5, args=(img, "p"))
- thread.start()
- img.mask.select()
- result = img.mask.sum()
- assert result == 9324, f"Mask selection by polygon failed result={result}"
- img.mask = False
- thread = threading.Thread(target=_trigger5, args=(img, "c"))
- thread.start()
- img.mask.select()
- result = img.mask.sum()
- assert result in (3664, 7489), f"Mask selection by circle failed result={result}"
- img.mask = False
- thread = threading.Thread(target=_trigger5, args=(img, "r"))
- thread.start()
- img.mask.select()
- result = img.mask.sum()
- assert result == 8699, f"Mask selection by reverse failed result={result}"
- img.mask = False
- thread = threading.Thread(target=_trigger6, args=(img, "c"))
- thread.start()
- img.mask.select()
- result = img.mask.sum()
- assert result == 0, f"Cancelling selkection failed with result={result}"
-
-
-if __name__ == "__main__": # Run some tests manually to allow debugging
- pytest.main(["--pdb", __file__])
diff --git a/tests/Stoner/core/test_typeHintedDict.py b/tests/Stoner/core/test_typeHintedDict.py
deleted file mode 100755
index c4738af25..000000000
--- a/tests/Stoner/core/test_typeHintedDict.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-Created on Sat Dec 8 15:20:15 2018
-
-@author: phygbu
-"""
-
-import os.path as path
-
-import pytest
-
-from Stoner.core.base import TypeHintedDict
-
-pth = path.dirname(__file__)
-pth = path.realpath(path.join(pth, "../../"))
-# sys.path.insert(0,pth)
-
-
-def test_ops():
- d = TypeHintedDict([("el1", 1), ("el2", 2), ("el3", 3), ("other", 4)])
- d.filter("el")
- assert len(d) == 3
- d.filter(lambda x: x.endswith("3"))
- assert len(d) == 1
- assert d["el3"] == 3
- d["munge"] = None
- assert d.types["munge"] == "Void", "Setting type for None value failed."
- d["munge"] = 1
- assert d["munge{String}"] == "1", "Munging return type in getitem failed."
- assert (
- repr(d)
- == """'el3':I32:3
-'munge':I32:1"""
- ), "Repr failed \n{}".format(d)
- assert len(d | {"test": 2}) == len(d) + 1
- assert len(d | {"munge": 2}) == len(d)
- e = d.copy()
- e |= {"test": 4}
- assert d != e
- d.update({"test": 4})
- assert d == e
-
-
-if __name__ == "__main__": # Run some tests manually to allow debugging
- pytest.main(["--pdb", __file__])
diff --git a/tests/Stoner/test_Zip.py b/tests/Stoner/test_Zip.py
deleted file mode 100755
index 51fc7a574..000000000
--- a/tests/Stoner/test_Zip.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Test the ZIP module for zipfile compressed objects."""
-
-
-import os.path as path
-import tempfile
-import zipfile as zf
-import numpy as np
-
-import pytest
-
-import Stoner
-
-pth = path.dirname(__file__)
-
-root = path.realpath(path.join(Stoner.__home__, ".."))
-sample_data = path.realpath(path.join(root, "sample-data", "NLIV"))
-tmpdir = tempfile.mkdtemp()
-
-
-def test_zipFile(tmpdir):
- d = Stoner.Data(Stoner.__datapath__ / "TDI_Format_RT.txt")
- d.save(path.join(tmpdir, "TDI_Format_RT.zip"), filetype="ZippedFile")
-
- z2 = Stoner.Data(path.join(tmpdir, "TDI_Format_RT.zip"))
- d["Loaded as"] = z2["Loaded as"]
- d["Stoner.class"] = z2["Stoner.class"]
- assert d == z2
- with zf.ZipFile(path.join(tmpdir, "TDI_Format_RT.zip"), "r") as open_zipfile:
- z3 = Stoner.Data().load(open_zipfile, filetype="ZippedFile")
- z3["Stoner.class"] = z2["Stoner.class"]
- z3["Loaded as"] = z2["Loaded as"]
- assert z2 == z3
-
-
-def test_zipfolder():
- # Test constructor from DataFolder
- sf = Stoner.DataFolder(sample_data, pattern="*.txt")
- szf = Stoner.folders.zip.ZipFolder(sf)
- assert sf.shape == szf.shape, "ZipFolder created from DataFolder didn't keep the same shape"
- assert sf[0] == szf[0], "First element of ZipFolder created from DataFolder changed!"
- zipname = path.join(tmpdir, "test-zipfolder.zip")
- szf.save(zipname)
- assert sf.shape == szf.shape, "ZipFolder Changed shape when saving!"
- szf_2 = Stoner.folders.zip.ZipFolder(zipname).compress()
- assert szf_2.shape == szf.shape, "ZipFolder loaded from disc not same shape as ZipFolder in memory!"
- fname = path.basename(szf[0].filename)
- m1=szf[fname]
- m2=szf_2[fname]
- assert np.all(np.isclose(m1.data,m2.data)), "Data from two zip files is too different."
- m2["Loaded from"]=m1["Loaded from"]
- assert m1.metadata==m2.metadata, f"Metadata differes {m1.metadata^m2.metadata}"
-
-
-if __name__ == "__main__": # Run some tests manually to allow debugging
- pytest.main(["--pdb", __file__])
diff --git a/tests/test-env.yml b/tests/test-env.yml
index 736314d68..158ed51e0 100755
--- a/tests/test-env.yml
+++ b/tests/test-env.yml
@@ -10,7 +10,6 @@ dependencies:
- pytest
- pytest-cov
- pytest-forked
- - pytest-runner
- pytest-xdist
- python-dateutil
- pip