├── .flake8 ├── .github ├── ISSUE_TEMPLATE │ ├── FEATURE_REQUEST.md │ └── bug_report.md ├── dependabot.yml └── workflows │ ├── codeql-analysis.yml │ └── continuous-integration-pip.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── CHANGELOG ├── LICENSE ├── MANIFEST.in ├── conftest.py ├── csdmpy ├── __init__.py ├── __main__.py ├── abstract_list.py ├── csdm.py ├── dependent_variable │ ├── __init__.py │ ├── base_class.py │ ├── decoder.py │ ├── download.py │ ├── external.py │ ├── internal.py │ └── sparse.py ├── dimension │ ├── __init__.py │ ├── base.py │ ├── labeled.py │ ├── linear.py │ ├── monotonic.py │ └── quantitative.py ├── helper_functions.py ├── numpy_wrapper │ ├── __init__.py │ └── apodize.py ├── statistics.py ├── tests.py ├── units.py └── utils.py ├── docs ├── CSD_model.rst ├── CSDmodel_uml │ ├── csdm.rst │ ├── dependent_variables │ │ ├── dependent_variable.rst │ │ ├── external.rst │ │ ├── internal.rst │ │ └── sparse_sampling.rst │ ├── dimensions │ │ ├── dimension.rst │ │ ├── labeled.rst │ │ ├── linear.rst │ │ └── monotonic.rst │ ├── enumeration.rst │ └── scalarQuantity.rst ├── Makefile ├── _static │ ├── button.css │ ├── csdm.png │ ├── csdmpy.png │ └── style.css ├── _templates │ └── layout.html ├── api │ ├── CSDM.rst │ ├── DependentVariable.rst │ ├── Dimensions.rst │ ├── csdmpy.rst │ ├── dimension │ │ ├── labeled.rst │ │ ├── linear.rst │ │ └── monotonic.rst │ ├── numpy_wrappers.rst │ ├── plotting_function.rst │ ├── statistics.rst │ └── wrappers │ │ ├── apodization.rst │ │ └── element_wise_operation.rst ├── changelog.rst ├── conf.py ├── getting_started.rst ├── index.rst ├── installation.rst ├── make.bat ├── plotting_with_pyplot │ ├── one_D_plots.rst │ └── two_D_plots.rst ├── referenceAPI.rst ├── requirements.txt ├── startFromScratch │ ├── A fun example.rst │ ├── add_dependent_variable_object.rst │ ├── add_dimension_object.rst │ ├── dimension │ │ ├── generate │ │ │ ├── dimension_objects.rst │ │ │ ├── labeled.rst │ │ │ ├── linear.rst │ │ │ └── monotonic.rst │ │ └── interact │ │ │ ├── dimension_objects.rst │ │ │ ├── linear.rst │ │ │ └── monotonic.rst │ ├── generating_csdm_object.rst │ ├── generating_dependent_variable_object.rst │ ├── interacting_with_csdm.rst │ ├── interacting_with_csdmpy_objects.rst │ ├── save_dataset.rst │ └── start.rst └── using_csdm_with_pyplot.rst ├── examples ├── 1D_1_examples │ ├── README.rst │ ├── plot_0_gmsl.py │ ├── plot_1_NMR_bloch.py │ ├── plot_2_EPR.py │ ├── plot_3_GS.py │ ├── plot_4_FTIR.py │ ├── plot_5_UV-vis.py │ └── plot_6_Mass.py ├── 2D_1_examples │ ├── README.rst │ ├── plot_0_astronomy.py │ ├── plot_1_NMR_satrec.py │ ├── plot_2_TEM.py │ └── plot_3_labeled.py ├── README.rst ├── correlated_examples │ ├── README.rst │ ├── plot_0_0D11_dataset.py │ ├── plot_1_meteorology.py │ └── plot_2_astronomy.py ├── pixel │ ├── README.rst │ └── plot_0_image.py ├── sparse │ ├── README.rst │ ├── plot_0_1D_sparse.py │ └── plot_1_2D_sparse.py ├── tensor │ ├── README.rst │ └── plot_0_3D_diff_tensor_mri.py └── vector │ ├── README.rst │ ├── plot_0_vector.py │ └── plot_1_vector.py ├── pyplot ├── getting_started.py ├── oneD111_plot.py ├── oneD_plot.py ├── twoD111_plot.py └── twoD_plot.py ├── pyproject.toml ├── readme.md ├── requirements-dev.txt ├── requirements.txt ├── setup.cfg ├── setup.py ├── tests ├── csdm_indexing_test.py ├── csdm_new_test.py ├── csdm_test.py ├── csdmpy_test.py ├── dependent_variable_test.py ├── dimension_test.py ├── fft_test.py ├── file_read │ ├── fileread_test.py │ └── test_files │ │ ├── 1.csdfe │ │ ├── 10.csdfe │ │ ├── 11.csdfe │ │ ├── 12.csdfe │ │ ├── 13.csdfe │ │ ├── 14.csdfe │ │ ├── 15.csdfe │ │ ├── 16.csdfe │ │ ├── 2.csdfe │ │ ├── 3.csdfe │ │ ├── 4.csdfe │ │ ├── 5.csdfe │ │ ├── 6.csdfe │ │ ├── 7.csdfe │ │ ├── 8.csdfe │ │ └── 9.csdfe ├── import_test.py ├── nmr_freq_test.py ├── numpy_wrapper │ ├── apodization_test.py │ ├── change_shape_test.py │ ├── dimension_reduction_test.py │ ├── element_wise_test.py │ ├── np_pad_flip_test.py │ ├── np_tile_test.py │ └── numpy_csdm_test.py ├── save_file_test.py ├── serialization_test.py ├── sparse_test.py ├── statistics_test.py ├── unit_test.py └── utils_test.py └── tutorials ├── 1D_datasets ├── README.rst ├── plot_0_1D.py └── plot_1_1D.py ├── 2D_datasets ├── README.rst ├── plot_0_2D.py └── plot_1_2D.py └── README.rst /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore= E402 3 | max-line-length = 88 4 | max-complexity = 10 5 | select = B,C,E,F,W,T,N8 6 | count = True 7 | statistics = True 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "🚀 Feature request" 3 | about: Suggest an idea for improving csdmpy 4 | title: "" 5 | labels: "type:Enhancement" 6 | assignees: "" 7 | --- 8 | 9 | Provide a clear and concise description of your proposal. Your proposal should cover the following points. 10 | 11 | **Describe the reason for the request** 12 | 13 | - Is your proposal related to a problem? For example, "I'm always frustrated when...", 14 | - Is your proposal to improve a feature of `csdmpy`? For example, "The code will be more efficient if ...", 15 | - Is your proposal to request a new feature? For example, "The library is missing ... " 16 | 17 | (Write your answer here) 18 | 19 | **Describe the solution you'd like** 20 | 21 | (Write your answer here) 22 | 23 | **Describe what other alternatives you've considered** 24 | 25 | (Write your answer here) 26 | 27 | **Additional context** 28 | 29 | Is there anything else you would like to add to the proposal? 30 | If there are any open issues related to your proposed feature request, please add a link to 31 | related issues here, if you haven't already. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "🐞 Bug Report" 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: "type:Bug" 6 | assignees: "" 7 | --- 8 | 9 | Did you find a bug? Please help us improve by fill out the sections below. 👍 10 | 11 | **Describe the bug** 12 | 13 | A clear and concise description of what the bug is. 14 | 15 | **To Reproduce** 16 | 17 | Steps to reproduce the behavior: 18 | 19 | 1. Please include a minimal code to reproduce the bug. 20 | 2. Report python raised exception if any. Report the output, if any. 21 | 22 | **Expected behavior** 23 | 24 | A clear and concise description of what did you expect to happen. 25 | 26 | **Screenshots** 27 | 28 | If applicable, add screenshots to help explain your problem. 29 | 30 | **Desktop (please complete the following information):** 31 | 32 | - OS: [e.g. macOS] 33 | - Python version: [e.g. 3.10.1] 34 | - `csdmpy` version: [e.g. 0.6] 35 | 36 | **Additional context** 37 | 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | 9 | # Maintain dependencies for GitHub Actions 10 | - package-ecosystem: "github-actions" 11 | directory: "/" 12 | schedule: 13 | interval: "daily" 14 | 15 | # Maintain dependencies for pip 16 | - package-ecosystem: "pip" 17 | directory: "/" 18 | schedule: 19 | interval: "daily" 20 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | name: "CodeQL" 7 | 8 | on: 9 | # At the end of every day 10 | schedule: 11 | - cron: '0 0 * * *' 12 | 13 | jobs: 14 | analyze: 15 | name: Analyze 16 | runs-on: ubuntu-latest 17 | 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | # Override automatic language detection by changing the below list 22 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] 23 | language: ['python'] 24 | # Learn more... 25 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection 26 | 27 | steps: 28 | - name: Checkout repository 29 | uses: actions/checkout@v4 30 | 31 | # Initializes the CodeQL tools for scanning. 32 | - name: Initialize CodeQL 33 | uses: github/codeql-action/init@v3 34 | with: 35 | languages: ${{ matrix.language }} 36 | # If you wish to specify custom queries, you can do so here or in a config file. 37 | # By default, queries listed here will override any specified in a config file. 38 | # Prefix the list here with "+" to use these queries and those in the config file. 39 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 40 | 41 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 42 | # If this step fails, then you should remove it and run the build manually (see below) 43 | - name: Autobuild 44 | uses: github/codeql-action/autobuild@v3 45 | 46 | # ℹ️ Command-line programs to run using the OS shell. 47 | # 📚 https://git.io/JvXDl 48 | 49 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 50 | # and modify them (or add more) to build your code if your project 51 | # uses a compiled language 52 | 53 | #- run: | 54 | # make bootstrap 55 | # make release 56 | 57 | - name: Perform CodeQL Analysis 58 | uses: github/codeql-action/analyze@v3 59 | -------------------------------------------------------------------------------- /.github/workflows/continuous-integration-pip.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: CI (pip) 5 | 6 | on: 7 | push: 8 | branches: [master] 9 | pull_request: 10 | branches: [master] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | python-version: [3.9, "3.10", "3.11", "3.12"] 18 | 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | - name: Set up Python ${{ matrix.python-version }} 23 | uses: actions/setup-python@v5 24 | with: 25 | python-version: ${{ matrix.python-version }} 26 | - name: Install dependencies 27 | run: | 28 | python -m pip install --upgrade pip 29 | pip install flake8 pytest 30 | pip install -r requirements.txt 31 | pip install -r requirements-dev.txt 32 | - name: Lint with flake8 33 | run: | 34 | # stop the build if there are Python syntax errors or undefined names 35 | flake8 . --count --select=C,E,F,W,N8 --show-source --statistics --exclude="examples/* *.npy docs/* *.pyx *.pxd" 36 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 37 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics --exclude="examples/* *.npy docs/* *.pyx *.pxd" 38 | - name: Build and install package from source 39 | run: pip install -e . 40 | - name: Test with pytest 41 | run: pytest --cov=./ --cov-report=xml 42 | - name: Upload coverage 43 | uses: codecov/codecov-action@v5.4.3 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # folders # 2 | __pycache__/ 3 | csdmpy.egg-info/** 4 | .eggs/** 5 | build/** 6 | dist/** 7 | .ipynb_checkpoints/** 8 | archive/** 9 | .eggs/** 10 | .vscode 11 | .pytest_cache/** 12 | htmlcov/** 13 | Test_files/** 14 | */Test Files-CSDM-v1.0/** 15 | docs/_build/** 16 | docs/auto_examples/** 17 | docs/auto_tutorials/** 18 | 19 | # Compiled source # 20 | ################### 21 | *.com 22 | *.class 23 | *.dll 24 | *.exe 25 | *.o 26 | *.so 27 | *.pyc 28 | 29 | # Packages # 30 | ############ 31 | # it's better to unpack these files and commit the raw source 32 | # git has its own built in compression methods 33 | *.7z 34 | *.dmg 35 | *.gz 36 | *.iso 37 | *.jar 38 | *.rar 39 | *.tar 40 | *.zip 41 | 42 | # Logs and databases # 43 | ###################### 44 | *.log 45 | *.sql 46 | *.sqlite 47 | 48 | # OS generated files # 49 | ###################### 50 | .DS_Store 51 | .DS_Store? 52 | ._* 53 | .Spotlight-V100 54 | .Trashes 55 | ehthumbs.db 56 | Thumbs.db 57 | *.DS_Store* 58 | 59 | # files 60 | files.txt 61 | info.txt 62 | *.ipynb 63 | *schema 64 | *.csdf 65 | 66 | # files # 67 | ######### 68 | my_file** 69 | .coverage 70 | csdm.code-workspace 71 | csdmpy.pdf 72 | *.temp 73 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_language_version: 2 | python: python 3 | default_stages: [commit, push, manual] 4 | repos: 5 | - repo: https://github.com/ambv/black 6 | rev: 22.12.0 7 | hooks: 8 | - id: black 9 | name: black 10 | entry: black 11 | require_serial: true 12 | types: [python] 13 | files: \.pyi?$ 14 | 15 | - repo: https://github.com/asottile/pyupgrade 16 | rev: v3.3.1 17 | hooks: 18 | - id: pyupgrade 19 | args: ["--py36-plus"] 20 | 21 | - repo: https://github.com/asottile/blacken-docs 22 | rev: v1.12.1 23 | hooks: 24 | - id: blacken-docs 25 | additional_dependencies: [black] 26 | language: python 27 | 28 | - repo: https://github.com/pre-commit/pre-commit-hooks 29 | rev: v4.4.0 30 | hooks: 31 | - id: check-yaml 32 | - id: check-added-large-files 33 | - id: check-case-conflict 34 | - id: check-docstring-first 35 | - id: mixed-line-ending 36 | - id: detect-private-key 37 | - id: end-of-file-fixer 38 | exclude: docs/notebooks/ 39 | - id: trailing-whitespace 40 | types: [text] 41 | - id: debug-statements 42 | name: Debug Statements (Python) 43 | description: Check for debugger imports and py37+ `breakpoint()` calls in python source. 44 | entry: debug-statement-hook 45 | language: python 46 | types: [python] 47 | 48 | - repo: https://github.com/pycqa/flake8 49 | rev: "6.0.0" 50 | hooks: 51 | - id: flake8 52 | language: python 53 | args: 54 | [ 55 | "--exclude=.eggs/,*.egg,build", 56 | "--max-line-length=88", 57 | "--max-complexity=10", 58 | "--select=B,C,E,F,W,T,N8", 59 | "--count", 60 | "--statistics", 61 | ] 62 | 63 | - repo: https://github.com/asottile/reorder_python_imports 64 | rev: v3.9.0 65 | hooks: 66 | - id: reorder-python-imports 67 | entry: reorder-python-imports 68 | language: python 69 | types: [python] 70 | minimum_pre_commit_version: "0.15.0" 71 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Build documentation in the docs/ directory with Sphinx 9 | sphinx: 10 | configuration: docs/conf.py 11 | 12 | build: 13 | os: ubuntu-22.04 14 | tools: 15 | python: "3.12" 16 | 17 | # Optionally build your docs in additional formats such as PDF and ePub 18 | formats: [pdf] 19 | 20 | # conda: 21 | # environment: environment-doc.yml 22 | 23 | # Optionally set the version of Python and requirements required to build your docs 24 | python: 25 | install: 26 | - requirements: docs/requirements.txt 27 | - method: pip 28 | path: . 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Deepansh Srivastava 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | 2 | include README.md 3 | include LICENSE 4 | include CHANGELOG 5 | recursive-include tests * 6 | include requirements.txt 7 | include requirements-dev.txt 8 | recursive-include docs * 9 | recursive-exclude docs/_build * 10 | recursive-exclude docs/auto_examples * 11 | recursive-exclude docs/auto_tutorials * 12 | 13 | global-exclude *.pyc *.o *.csdf *.temp 14 | -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | import csdmpy as cp 5 | import csdmpy.statistics as stat 6 | from csdmpy.dependent_variable import DependentVariable 7 | from csdmpy.dimension import Dimension 8 | 9 | __all__ = [] 10 | 11 | 12 | @pytest.fixture(autouse=True) 13 | def add_cp_dimension(doctest_namespace): 14 | doctest_namespace["cp"] = cp 15 | doctest_namespace["np"] = np 16 | doctest_namespace["stat"] = stat 17 | doctest_namespace["Dimension"] = Dimension 18 | doctest_namespace["DependentVariable"] = DependentVariable 19 | doctest_namespace["x"] = Dimension( 20 | type="linear", 21 | description="This is a test", 22 | count=10, 23 | increment="5 G", 24 | coordinates_offset="10 mT", 25 | origin_offset="10 T", 26 | label="field strength", 27 | reciprocal={"quantity_name": "electrical mobility"}, 28 | ) 29 | 30 | doctest_namespace["dimension_dictionary"] = { 31 | "type": "linear", 32 | "description": "This is a test", 33 | "count": 10, 34 | "increment": "5 G", 35 | "coordinates_offset": "10 mT", 36 | "origin_offset": "10 T", 37 | "label": "field strength", 38 | } 39 | 40 | numpy_array = np.arange(30).reshape(3, 10).astype(np.float32) 41 | doctest_namespace["y"] = DependentVariable( 42 | type="internal", 43 | description="A test image", 44 | name="star", 45 | unit="W s", 46 | quantity_name="energy", 47 | quantity_type="pixel_3", 48 | components=numpy_array, 49 | ) 50 | 51 | doctest_namespace["dependent_variable_dictionary"] = { 52 | "type": "internal", 53 | "description": "A test image", 54 | "name": "star", 55 | "unit": "W s", 56 | "quantity_name": "energy", 57 | "quantity_type": "pixel_3", 58 | "components": numpy_array, 59 | } 60 | 61 | doctest_namespace["data"] = cp.load(cp.tests.test01) 62 | doctest_namespace["my_data"] = cp.load(cp.tests.test02) 63 | 64 | x = np.arange(100) * 2 - 100.0 65 | gauss = np.exp(-((x - 5.0) ** 2) / (2 * 4.0**2)) 66 | csdm = cp.as_csdm(gauss, unit="T") 67 | csdm.dimensions[0] = cp.as_dimension(x, unit="m") 68 | doctest_namespace["csdm"] = csdm 69 | -------------------------------------------------------------------------------- /csdmpy/__main__.py: -------------------------------------------------------------------------------- 1 | """CSDM main.""" 2 | import sys 3 | 4 | import matplotlib.pyplot as plt 5 | 6 | import csdmpy as cp 7 | from csdmpy.helper_functions import _preview 8 | 9 | __author__ = "Deepansh J. Srivastava" 10 | __email__ = "srivastava.89@osu.edu" 11 | 12 | 13 | if __name__ == "__main__": 14 | for i in range(len(sys.argv) - 1): 15 | data = cp.load(sys.argv[i + 1]) 16 | _preview(data) 17 | plt.show() 18 | -------------------------------------------------------------------------------- /csdmpy/abstract_list.py: -------------------------------------------------------------------------------- 1 | from collections.abc import MutableSequence 2 | 3 | import numpy as np 4 | 5 | from .dependent_variable import DependentVariable 6 | from .dimension import Dimension 7 | from .dimension import LabeledDimension 8 | from .dimension import LinearDimension 9 | from .dimension import MonotonicDimension 10 | 11 | __author__ = "Deepansh J. Srivastava" 12 | __email__ = "srivastava.89@osu.edu" 13 | 14 | __all__ = ["DimensionList", "DependentVariableList"] 15 | 16 | __dimensions_list__ = (Dimension, LinearDimension, MonotonicDimension, LabeledDimension) 17 | 18 | 19 | class AbstractList(MutableSequence): 20 | """Abstract list for objects""" 21 | 22 | def __init__(self, data=[]): 23 | """Store data list""" 24 | super().__init__() 25 | self._list = list(data) 26 | 27 | def __repr__(self): 28 | """String representation""" 29 | return self._list.__repr__() 30 | 31 | def __str__(self): 32 | """String representation""" 33 | string = ",\n".join([item.__repr__() for item in self._list]) 34 | return f"[{string}]" 35 | 36 | def __len__(self): 37 | """List length""" 38 | return len(self._list) 39 | 40 | def __getitem__(self, index): 41 | """Get a list item""" 42 | return self._list[index] 43 | 44 | def __delitem__(self, index): 45 | raise LookupError("Deleting items is not allowed.") 46 | 47 | def check_object(self, obj): 48 | """Abstract check""" 49 | 50 | def insert(self, index: int, value: object): 51 | """Insert a list item""" 52 | self._list.insert(index, self.check_object(value)) 53 | 54 | def append(self, value): 55 | """Append a list item""" 56 | self._list.append(self.check_object(value)) 57 | 58 | def __setitem__(self, index, item): 59 | """Set item at index""" 60 | self._list.__setitem__(index, self.check_object(item)) 61 | 62 | def __eq__(self, other): 63 | """Check equality of DependentVariableList.""" 64 | if not isinstance(other, self.__class__): 65 | return False 66 | if len(self._list) != len(other._list): 67 | return False 68 | 69 | check = [self_i == other_i for self_i, other_i in zip(self._list, other._list)] 70 | return np.all(check) 71 | 72 | 73 | class DimensionList(AbstractList): 74 | """List of Dimension objects""" 75 | 76 | def check_object(self, obj): 77 | """Validate dimension""" 78 | if isinstance(obj, dict): 79 | obj = Dimension(**obj) 80 | if not isinstance(obj, __dimensions_list__): 81 | name = obj.__class__.__name__ 82 | raise ValueError(f"Expecting a Dimension object, found {name}") 83 | return obj 84 | 85 | 86 | class DependentVariableList(AbstractList): 87 | """List of Dependent variable objects""" 88 | 89 | def check_object(self, obj): 90 | """Validate dependent variable""" 91 | if isinstance(obj, dict): 92 | obj = DependentVariable(**obj) 93 | if not isinstance(obj, DependentVariable): 94 | name = obj.__class__.__name__ 95 | raise ValueError(f"Expecting a DependentVariable object, found {name}") 96 | return obj 97 | -------------------------------------------------------------------------------- /csdmpy/dependent_variable/decoder.py: -------------------------------------------------------------------------------- 1 | """Decoder for components' encoding types.""" 2 | import base64 3 | 4 | import numpy as np 5 | 6 | 7 | __author__ = "Deepansh J. Srivastava" 8 | __email__ = "srivastava.89@osu.edu" 9 | __all__ = ["Decoder"] 10 | 11 | 12 | class Decoder: 13 | """Decoder class""" 14 | 15 | def __new__(cls, encoding, quantity_type, components, dtype): 16 | """Decode the components based on the encoding key value. 17 | 18 | The valid encodings are 'base64', 'none' (text), and 'raw' (binary). 19 | """ 20 | if encoding != "raw": 21 | check_number_of_components_and_encoding_type(len(components), quantity_type) 22 | component_len = quantity_type.p 23 | method = getattr(cls, "decode_" + encoding) 24 | return method(components, dtype, component_len) 25 | 26 | @staticmethod 27 | def decode_base64(components, dtype, component_len=None): 28 | """Read components form a base64 buffer""" 29 | components = np.asarray( 30 | [np.frombuffer(base64.b64decode(item), dtype=dtype) for item in components] 31 | ) 32 | return components 33 | 34 | @staticmethod 35 | def decode_none(components, dtype, component_len=None): 36 | """Read components form a text buffer""" 37 | return ( 38 | np.asarray( 39 | [ 40 | np.asarray(item[0::2]) + 1j * np.asarray(item[1::2]) 41 | for item in components 42 | ], 43 | dtype=dtype, 44 | ) 45 | if dtype in ["c8", ">c16"] 46 | else np.asarray(components, dtype=dtype) 47 | ) 48 | 49 | @staticmethod 50 | def decode_raw(components, dtype, component_len=None): 51 | """Read components form a binary buffer""" 52 | components = np.frombuffer(components, dtype=dtype) 53 | if not components.flags["WRITEABLE"]: 54 | components = components.copy() 55 | size = int(components.size / component_len) 56 | components = components.reshape(component_len, size) 57 | return components 58 | 59 | 60 | def check_number_of_components_and_encoding_type(length, quantity_type): 61 | """Verify the consistency of encoding wrt the number of components.""" 62 | if length != quantity_type.p: 63 | raise Exception( 64 | f"The quantity_type, '{quantity_type.value}', requires exactly " 65 | f"{quantity_type.p} component(s), found {length} components." 66 | ) 67 | -------------------------------------------------------------------------------- /csdmpy/dependent_variable/download.py: -------------------------------------------------------------------------------- 1 | """Utility functions for the csdmpy module.""" 2 | import sys 3 | from os import path 4 | from urllib.parse import quote 5 | from urllib.parse import urlparse 6 | 7 | import requests 8 | 9 | 10 | __author__ = "Deepansh J. Srivastava" 11 | __email__ = "srivastava.89@osu.edu" 12 | __all__ = ["parse_url", "download_file_from_url"] 13 | 14 | 15 | def parse_url(url): 16 | """Parse url""" 17 | res = urlparse(quote(url, safe="/?#@:")) 18 | return res 19 | 20 | 21 | def download_file_from_url(url, verbose=False): 22 | """Download file from url""" 23 | res = parse_url(url) 24 | filename = path.split(res[2])[1] 25 | if path.isfile(filename): 26 | if verbose: 27 | sys.stdout.write( 28 | f"Found a local file with the filename, {0}. Skipping download." 29 | ) 30 | return filename 31 | 32 | with open(filename, "wb") as file: 33 | response = requests.get(url, stream=True) 34 | total = response.headers.get("content-length") 35 | 36 | if total is None: 37 | file.write(response.content) 38 | else: 39 | downloaded = 0 40 | total = int(total) 41 | if verbose: 42 | sys.stdout.write( 43 | "Downloading '{}' from '{}' to file '{}'.\n".format( 44 | res[2], res[1], filename 45 | ) 46 | ) 47 | for data in response.iter_content( 48 | chunk_size=max(int(total / 1000), 1024 * 1024) 49 | ): 50 | downloaded += len(data) 51 | file.write(data) 52 | if verbose: 53 | done = int(20 * downloaded / total) 54 | sys.stdout.write("\r[{}{}]".format("█" * done, "." * (20 - done))) 55 | sys.stdout.flush() 56 | if verbose: 57 | sys.stdout.write("\n") 58 | 59 | return filename 60 | 61 | 62 | def _get_absolute_data_address(data_path, file): 63 | """Return the absolute path address of a local data file. 64 | 65 | :params: data_path: 66 | """ 67 | _file_abs_path = path.abspath(file) 68 | _path, _file = path.split(_file_abs_path) 69 | _join = path.join(_path, data_path) 70 | _join = path.normpath(_join) 71 | return "file:" + _join 72 | 73 | 74 | def get_absolute_url_path(url, file): 75 | """Return absolute path to url""" 76 | res = parse_url(url) 77 | url_path = res.geturl() 78 | if res.scheme in ["file", ""]: 79 | if res.netloc == "": 80 | url_path = _get_absolute_data_address(res.path, file) 81 | return url_path 82 | 83 | 84 | def get_relative_url_path(dataset_index, filename): 85 | """Return relative path to url""" 86 | index = str(dataset_index) 87 | absolute_path = get_absolute_url_path("", filename) 88 | 89 | name = path.splitext(path.split(filename)[1])[0] + "_" + index + ".dat" 90 | 91 | relative_url_path = path.join("file:.", name) 92 | 93 | absolute_path = path.abspath( 94 | urlparse(path.join(absolute_path, urlparse(relative_url_path).path)).path 95 | ) 96 | return relative_url_path, absolute_path 97 | -------------------------------------------------------------------------------- /csdmpy/dependent_variable/external.py: -------------------------------------------------------------------------------- 1 | """The External DependentVariable SubType class.""" 2 | from urllib.request import urlopen 3 | 4 | import numpy as np 5 | 6 | from csdmpy.dependent_variable.base_class import BaseDependentVariable 7 | from csdmpy.dependent_variable.decoder import Decoder 8 | from csdmpy.dependent_variable.download import get_absolute_url_path 9 | 10 | __author__ = "Deepansh J. Srivastava" 11 | __email__ = "srivastava.89@osu.edu" 12 | __all__ = ["ExternalDataset"] 13 | 14 | 15 | class ExternalDataset(BaseDependentVariable): 16 | """ExternalDataset class.""" 17 | 18 | __slots__ = ["_components_url"] 19 | 20 | def __init__(self, **kwargs): 21 | """Initialize.""" 22 | kwargs["encoding"] = "raw" 23 | if kwargs["numeric_type"] is None: 24 | raise KeyError( 25 | "Missing a required `numeric_type` key from the DependentVariable " 26 | "object." 27 | ) 28 | 29 | super().__init__(**kwargs) 30 | 31 | components_url = kwargs["components_url"] 32 | filename = kwargs["filename"] 33 | absolute_url = get_absolute_url_path(components_url, filename) 34 | self._components_url = components_url 35 | 36 | components = urlopen(absolute_url).read() 37 | self._components = Decoder( 38 | self._encoding, self._quantity_type, components, self._numeric_type.dtype 39 | ) 40 | 41 | if self._components.ndim == 1: 42 | self._components = self._components[np.newaxis, :] 43 | 44 | @property 45 | def components_url(self): 46 | """Return the components_url of the CSDM serialized file.""" 47 | return self._components_url 48 | 49 | def dict(self, filename=None, dataset_index=None, for_display=False): 50 | """Return ExternalDataset object as a python dictionary.""" 51 | dictionary = {} 52 | dictionary["type"] = "internal" 53 | dictionary.update(super().dict(filename, dataset_index, for_display)) 54 | return dictionary 55 | -------------------------------------------------------------------------------- /csdmpy/dependent_variable/internal.py: -------------------------------------------------------------------------------- 1 | """The Internal DependentVariable SubType class.""" 2 | import numpy as np 3 | 4 | from csdmpy.dependent_variable.base_class import BaseDependentVariable 5 | from csdmpy.dependent_variable.decoder import Decoder 6 | from csdmpy.utils import numpy_dtype_to_numeric_type 7 | 8 | 9 | __author__ = "Deepansh J. Srivastava" 10 | __email__ = "srivastava.89@osu.edu" 11 | __all__ = ["InternalDataset"] 12 | 13 | 14 | class InternalDataset(BaseDependentVariable): 15 | """InternalDataset class.""" 16 | 17 | def __init__(self, **kwargs): 18 | """Initialize.""" 19 | components = kwargs["components"] 20 | if isinstance(components, list) and components != []: 21 | if isinstance(components[0], np.ndarray): 22 | components = np.asarray(components) 23 | 24 | if isinstance(components, np.ndarray): 25 | if kwargs["numeric_type"] is None: 26 | kwargs["numeric_type"] = numpy_dtype_to_numeric_type( 27 | str(components.dtype) 28 | ) 29 | kwargs["components"] = components 30 | else: 31 | kwargs["components"] = components.astype(kwargs["numeric_type"]) 32 | 33 | if kwargs["numeric_type"] is None: 34 | raise KeyError( 35 | "Missing a required `numeric_type` key from the DependentVariable " 36 | "object." 37 | ) 38 | 39 | # super base class must be initialized before retrieving 40 | # the components array. 41 | super().__init__(**kwargs) 42 | 43 | if not isinstance(components, np.ndarray): 44 | self._components = Decoder( 45 | self._encoding, 46 | self._quantity_type, 47 | components, 48 | self._numeric_type.dtype, 49 | ) 50 | 51 | size = self._components.size 52 | p_1 = self.quantity_type.p 53 | self._components = self._components.reshape(p_1, int(size / p_1)) 54 | 55 | def dict(self, filename=None, dataset_index=None, for_display=False): 56 | """Return InternalDataset object as a python dictionary.""" 57 | dictionary = {} 58 | dictionary["type"] = "internal" 59 | dictionary.update(super().dict(filename, dataset_index, for_display)) 60 | return dictionary 61 | -------------------------------------------------------------------------------- /csdmpy/dimension/labeled.py: -------------------------------------------------------------------------------- 1 | """The Labeled Dimension sub type class.""" 2 | import numpy as np 3 | 4 | from .base import _copy_core_metadata 5 | from .base import BaseDimension 6 | from .base import check_count 7 | 8 | 9 | __author__ = "Deepansh J. Srivastava" 10 | __email__ = "srivastava.89@osu.edu" 11 | __all__ = ["LabeledDimension"] 12 | 13 | 14 | class LabeledDimension(BaseDimension): 15 | """A labeled dimension. 16 | 17 | Generates an object representing a non-physical dimension whose coordinates are 18 | labels. See :ref:`labeledDimension_uml` for details. 19 | """ 20 | 21 | __slots__ = ("_count", "_labels") 22 | 23 | _type = "labeled" 24 | 25 | def __init__(self, labels, label="", description="", application=None, **kwargs): 26 | """Instantiate a LabeledDimension class.""" 27 | super().__init__(label, application, description) 28 | self.labels = labels 29 | 30 | def __repr__(self): 31 | content = [f"{k}={v}" for k, v in self.dict().items() if k != "type"] 32 | properties = ", ".join(content) 33 | return f"LabeledDimension({properties})" 34 | 35 | def __str__(self): 36 | return f"LabeledDimension({self.coordinates.__str__()})" 37 | 38 | def __eq__(self, other): 39 | other = other.subtype if hasattr(other, "subtype") else other 40 | if not isinstance(other, LabeledDimension): 41 | return False 42 | check = [ 43 | self._count == other._count, 44 | np.all(self._labels == other._labels), 45 | super().__eq__(other), 46 | ] 47 | return np.all(check) 48 | 49 | def is_quantitative(self): 50 | """Return `True`, if the dimension is quantitative, otherwise `False`. 51 | :returns: A Boolean. 52 | """ 53 | return False 54 | 55 | # ----------------------------------------------------------------------- # 56 | # Attributes # 57 | # ----------------------------------------------------------------------- # 58 | 59 | @property 60 | def type(self): 61 | """Return the type of the dimension.""" 62 | return self.__class__._type 63 | 64 | @property 65 | def count(self): 66 | """Total number of labels along the dimension.""" 67 | return self._count 68 | 69 | @count.setter 70 | def count(self, value): 71 | self._count = check_count(value, self._count, "labeled") 72 | 73 | @property 74 | def labels(self): 75 | """Return a list of labels along the dimension.""" 76 | return self._labels 77 | 78 | @labels.setter 79 | def labels(self, labels): 80 | if not isinstance(labels, list): 81 | raise ValueError(f"A list of labels is required, found {type(labels)}.") 82 | 83 | items = np.asarray([isinstance(item, str) for item in labels]) 84 | if np.all(items): 85 | self._labels = np.asarray(labels) 86 | self._count = self._labels.size 87 | return 88 | 89 | i = np.where(items == 0)[0][0] 90 | name = labels[i].__class__.__name__ 91 | raise ValueError( 92 | f"A list of string labels are required, found {name} at index {i}." 93 | ) 94 | 95 | @property 96 | def coordinates(self): 97 | """Return the coordinates along the dimensions. This is an alias for labels.""" 98 | return self.labels[: self._count] 99 | 100 | @coordinates.setter 101 | def coordinates(self, value): 102 | self.labels = value 103 | 104 | # ----------------------------------------------------------------------- # 105 | # Methods # 106 | # ----------------------------------------------------------------------- # 107 | 108 | def copy_metadata(self, obj): 109 | """Copy LabeledDimension metadata.""" 110 | obj = obj.subtype if hasattr(obj, "subtype") else obj 111 | if isinstance(obj, LabeledDimension): 112 | _copy_core_metadata(self, obj, "labeled") 113 | 114 | def dict(self): 115 | """Return the LabeledDimension as a python dictionary.""" 116 | dictionary = {} 117 | dictionary["type"] = self.__class__._type 118 | dictionary["labels"] = self._labels.tolist() 119 | dictionary.update(super().dict()) 120 | return dictionary 121 | -------------------------------------------------------------------------------- /csdmpy/tests.py: -------------------------------------------------------------------------------- 1 | __all__ = ["test01", "test02", "test03", "test04"] 2 | 3 | test01 = "https://www.ssnmr.org/sites/default/files/CSDM/test/test01.csdf" 4 | test02 = "https://www.ssnmr.org/sites/default/files/CSDM/test/test02.csdf" 5 | test03 = "https://www.ssnmr.org/sites/default/files/CSDM/test/test03.csdf" 6 | test04 = "https://www.ssnmr.org/sites/default/files/CSDM/test/test04.csdf" 7 | -------------------------------------------------------------------------------- /docs/CSD_model.rst: -------------------------------------------------------------------------------- 1 | ########################### 2 | Introduction to CSDM format 3 | ########################### 4 | 5 | The core scientific dataset (CSD) model is a *light-weight*, *portable*, 6 | *versatile*, and *standalone* data model capable of handling a variety of 7 | scientific datasets. The model only encapsulates 8 | data values and the minimum metadata to accurately represent a `p`-component 9 | dependent variable, 10 | :math:`(\mathbf{U}_0, ... \mathbf{U}_q, ... \mathbf{U}_{p-1})`, 11 | discretely sampled at `M` unique points in a `d`-dimensional coordinate space, 12 | :math:`(\mathbf{X}_0, \mathbf{X}_1, ... \mathbf{X}_k, ... \mathbf{X}_{d-1})`. 13 | The model is not intended to encapsulate 14 | any information on how the data might be acquired, processed, or visualized. 15 | 16 | The data model is *versatile* in allowing many use cases for most spectroscopy, 17 | diffraction, and imaging techniques. As 18 | such the model supports multi-component datasets associated with continuous 19 | physical quantities that are discretely sampled in a multi-dimensional space 20 | associated with other carefully controlled quantities, for e.g., a mass as a 21 | function of temperature, a current as a function of voltage and time, a signal 22 | voltage as a function of magnetic field gradient strength, a color image with 23 | a red, green, and blue (RGB) light intensity components as a function of two 24 | independent spatial dimensions, or the six components of the symmetric 25 | second-rank diffusion tensor MRI as a function of three independent spatial 26 | dimensions. Additionally, the model supports multiple dependent variables 27 | sharing the same :math:`d`-dimensional coordinate space. For example, a 28 | simultaneous measurement of current and voltage as a function of time, 29 | simultaneous acquisition of air temperature, pressure, wind velocity, and 30 | solar-flux as a function of Earth’s latitude and longitude coordinates. We 31 | refer to these dependent variables as `correlated-datasets`. 32 | 33 | The CSD model is independent of the hardware, 34 | operating system, application software, programming language, and the 35 | object-oriented file-serialization format utilized in serializing the CSD model 36 | to the file. Out of numerous file serialization formats, XML, JSON, property 37 | list, we chose the data-exchange oriented JSON (JavaScript Object Notation) 38 | file-serialization format because it is `human-readable` and 39 | `easily integrable` with any number of programming languages 40 | and field related application-software. 41 | 42 | .. toctree:: 43 | :maxdepth: 2 44 | 45 | CSDmodel_uml/csdm 46 | CSDmodel_uml/dimensions/dimension 47 | CSDmodel_uml/dependent_variables/dependent_variable 48 | CSDmodel_uml/enumeration 49 | CSDmodel_uml/scalarQuantity 50 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/csdm.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _csdm_uml: 3 | 4 | CSDM 5 | ==== 6 | 7 | Description 8 | ----------- 9 | 10 | The root level object of the CSD model. 11 | 12 | 13 | Attributes 14 | ---------- 15 | 16 | .. cssclass:: table-bordered table-hover centered table-striped 17 | 18 | .. list-table:: 19 | :widths: 25 25 50 20 | :header-rows: 1 21 | 22 | * - Name 23 | - Type 24 | - Description 25 | 26 | * - version 27 | - String 28 | - A `required` version number of CSDM file-exchange format. 29 | 30 | * - dimensions 31 | - [:ref:`dimension_uml`, ...] 32 | - A `required` ordered and unique array of dimension objects. An empty 33 | array is a valid value. 34 | 35 | * - dependent_variables 36 | - [:ref:`dependent_var_uml`, ...] 37 | - A `required` array of dependent-variable objects. An empty array is a 38 | valid value. 39 | 40 | * - tags 41 | - [String, ...] 42 | - An `optional` list of keywords associated with the dataset. 43 | 44 | * - read_only 45 | - Boolean 46 | - An `optional` value with default as False. If true, the serialized file 47 | is archived. 48 | 49 | * - timestamp 50 | - String 51 | - An `optional` UTC ISO-8601 format timestamp from when the 52 | CSDM-compliant file was last serialized. 53 | 54 | * - geographic_coordinate 55 | - geographic_coordinate 56 | - An `optional` object with attributes required to describe the location 57 | from where the CSDM-compliant file was last serialized. 58 | 59 | * - description 60 | - String 61 | - An `optional` description of the datasets in the CSD model. 62 | 63 | * - application 64 | - Generic 65 | - An `optional` generic dictionary object containing application specific 66 | metadata describing the CSDM object. 67 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/dependent_variables/dependent_variable.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _dependent_var_uml: 3 | 4 | 5 | DependentVariable 6 | ================= 7 | 8 | 9 | Description 10 | ----------- 11 | 12 | A generalized object describing a dependent variable of the dataset, which 13 | holds an ordered list of `p` components, indexed as `q=0` to `p-1`, as 14 | 15 | .. math:: 16 | [\mathbf{U}_0, ... \mathbf{U}_q, ... \mathbf{U}_{p-1}]. 17 | 18 | .. only:: html 19 | 20 | Specialized Class 21 | ----------------- 22 | 23 | .. raw:: html 24 | 25 |
26 | 27 | 28 | InternalDependentVariable 29 | 30 | 31 | ExternalDependentVariable 32 | 33 |
34 | 35 | 36 | Attributes 37 | ---------- 38 | 39 | .. cssclass:: table-bordered table-hover centered table-striped 40 | 41 | .. list-table:: 42 | :widths: 25 25 50 43 | :header-rows: 1 44 | 45 | * - Name 46 | - Type 47 | - Description 48 | 49 | * - type 50 | - :ref:`DVObjectSubtype_uml` 51 | - An enumeration literal with a valid dependent variable subtype. 52 | 53 | * - name 54 | - String 55 | - Name of the dependent variable. 56 | 57 | * - unit 58 | - String 59 | - The unit associated with the physical quantities describing the dependent 60 | variable. 61 | 62 | * - quantity_name 63 | - String 64 | - Quantity name associated with the physical quantities describing the 65 | dependent variable. 66 | 67 | * - numeric_type 68 | - :ref:`numericType_uml` 69 | - An enumeration literal with a valid numeric type. 70 | 71 | * - quantity_type 72 | - :ref:`quantityType_uml` 73 | - An enumeration literal with a valid quantity type. 74 | 75 | * - component_labels 76 | - [String, String, ... ] 77 | - Ordered array of labels associated with ordered array of components of 78 | the dependent variable. 79 | 80 | * - sparse_sampling 81 | - :ref:`sparseSampling_uml` 82 | - Object with attribute required to describe a sparsely sampled dependent 83 | variable components. 84 | 85 | * - description 86 | - String 87 | - Description of the dependent variable. 88 | 89 | * - application 90 | - Generic 91 | - Generic dictionary object containing application specific metadata 92 | describing the dependent variable. 93 | 94 | .. only:: latex 95 | 96 | Specialized Class 97 | ----------------- 98 | .. _internal_uml: 99 | 100 | .. include:: internal.rst 101 | 102 | .. _external_uml: 103 | 104 | .. include:: external.rst 105 | 106 | .. _sparseSampling_uml: 107 | 108 | .. include:: sparse_sampling.rst 109 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/dependent_variables/external.rst: -------------------------------------------------------------------------------- 1 | 2 | ExternalDependentVariable 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | .. only:: html 6 | 7 | Generalized Class 8 | """"""""""""""""" 9 | 10 | .. raw:: html 11 | 12 | 13 | DependentVariable 14 | 15 | 16 | Description 17 | """"""""""" 18 | 19 | An ExternalDependentVariable is where the components of the dependent variable 20 | are defined in an external file whose location is defined as the value of the 21 | ``components_url`` key. 22 | 23 | 24 | Attributes 25 | """""""""" 26 | 27 | .. cssclass:: table-bordered table-hover centered table-striped 28 | 29 | .. list-table:: 30 | :widths: 25 25 50 31 | :header-rows: 1 32 | 33 | * - Name 34 | - Type 35 | - Description 36 | 37 | * - components_url 38 | - String 39 | - A `required` URL location where the components of the dependent variable 40 | are serialized as a binary data. 41 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/dependent_variables/internal.rst: -------------------------------------------------------------------------------- 1 | 2 | InternalDependentVariable 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | .. only:: html 6 | 7 | Generalized Class 8 | """"""""""""""""" 9 | 10 | .. raw:: html 11 | 12 | 13 | DependentVariable 14 | 15 | 16 | Description 17 | """"""""""" 18 | 19 | An InternalDependentVariable is where the components of the dependent variable 20 | are defined within the object as the value of the `components` key, along 21 | with other metadata describing the dependent variable. 22 | 23 | 24 | Attributes 25 | """""""""" 26 | 27 | .. cssclass:: table-bordered table-hover centered table-striped 28 | 29 | .. list-table:: 30 | :widths: 15 35 50 31 | :header-rows: 1 32 | 33 | * - Name 34 | - Type 35 | - Description 36 | 37 | * - components 38 | - [String, String, ... ] 39 | - A `required` attribute. The value is an array of base64 encoded strings 40 | where each string is a component of the dependent variable and decodes 41 | to a binary array of `M` data values. This value is only `valid` 42 | only when the corresponding value of the `encoding` attribute is `base64`. 43 | 44 | * - components 45 | - [[Float, Float, ...], [Float, Float, ...], ...] 46 | - A `required` attribute. The value is an array of arrays where each inner 47 | array is a component of the dependent variable with `M` data values. This 48 | value is `valid` only when the value of `encoding` is `none`. 49 | 50 | * - encoding 51 | - String 52 | - A required enumeration literal, where the valid literals are `none` or 53 | `base64`. 54 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/dependent_variables/sparse_sampling.rst: -------------------------------------------------------------------------------- 1 | 2 | SparseSampling 3 | ^^^^^^^^^^^^^^ 4 | 5 | 6 | Description 7 | """"""""""" 8 | 9 | A SparseSampling object describes the dimensions indexes and grid vertexes 10 | where the components of the dependent variable are sparsely sampled. 11 | 12 | 13 | Attributes 14 | """""""""" 15 | 16 | .. cssclass:: table-bordered table-hover centered table-striped 17 | 18 | .. list-table:: 19 | :widths: 25 25 50 20 | :header-rows: 1 21 | 22 | * - Name 23 | - Type 24 | - Description 25 | 26 | * - dimension_indexes 27 | - [Integer, Integer, ...] 28 | - A `required` array of integers indicating along which dimensions the 29 | :ref:`dependent_var_uml` is sparsely sampled. 30 | 31 | * - sparse_grid_vertexes 32 | - [Integer, Integer, ...] 33 | - A required flattened array of integer indexes along the sparse dimensions 34 | where the components of the dependent variable are sampled. This is only 35 | `valid` when the encoding from the corresponding SparseSampling object is 36 | ``none``. 37 | 38 | * - sparse_grid_vertexes 39 | - String 40 | - A `required` base64 string of a flattened binary array of integer indexes 41 | along the sparse dimensions where the components of the dependent 42 | variable are sampled. This is only `valid` when the encoding from the 43 | corresponding SparseSampling object is ``base64``. 44 | 45 | * - encoding 46 | - String 47 | - A `required` enumeration with the following valid literals. 48 | ``none``, ``base64`` 49 | 50 | * - unsigned_integer_type 51 | - String 52 | - A `required` enumeration with the following valid literals. 53 | ``uint8``, ``uint16``, ``uint32``, ``uint64`` 54 | 55 | * - description 56 | - String 57 | - An `optional` description of the dependent variable. 58 | 59 | * - application 60 | - Generic 61 | - An `optional` generic dictionary object containing application specific 62 | metadata describing the SparseSampling object. 63 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/dimensions/dimension.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _dimension_uml: 3 | 4 | ========= 5 | Dimension 6 | ========= 7 | 8 | A generalized object describing a dimension of a multi-dimensional 9 | grid/space. 10 | 11 | .. only:: html 12 | 13 | Specialized Class 14 | ----------------- 15 | 16 | .. raw:: html 17 | 18 |
19 | 20 | 21 | LinearDimension 22 | 23 | 24 | MonotonicDimension 25 | 26 | 27 | LabeledDimension 28 |
29 | 30 | Attributes 31 | ---------- 32 | 33 | .. cssclass:: table-bordered table-hover centered table-striped 34 | 35 | .. list-table:: 36 | :widths: 25 25 50 37 | :header-rows: 1 38 | 39 | * - Name 40 | - Type 41 | - Description 42 | 43 | * - type 44 | - :ref:`dimObjectSubtype_uml` 45 | - A `required` enumeration literal with a valid dimension subtype. 46 | 47 | * - label 48 | - String 49 | - An `optional` label of the dimension. 50 | 51 | * - description 52 | - String 53 | - An `optional` description of the dimension. 54 | 55 | * - application 56 | - Generic 57 | - An `optional` generic dictionary object containing application specific 58 | metadata describing the dimension. 59 | 60 | .. only:: latex 61 | 62 | Specialized Class 63 | ----------------- 64 | 65 | .. _linearDimension_uml: 66 | 67 | .. include:: linear.rst 68 | 69 | .. _monotonicDimension_uml: 70 | 71 | .. include:: monotonic.rst 72 | 73 | .. _labeledDimension_uml: 74 | 75 | .. include:: labeled.rst 76 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/dimensions/labeled.rst: -------------------------------------------------------------------------------- 1 | 2 | LabeledDimension 3 | ^^^^^^^^^^^^^^^^ 4 | 5 | .. only:: html 6 | 7 | Generalized Class 8 | """"""""""""""""" 9 | 10 | .. raw:: html 11 | 12 | 13 | Dimension 14 | 15 | 16 | Description 17 | """"""""""" 18 | 19 | A labeled dimension is a qualitative dimension where the coordinates along 20 | the dimension are explicitly defined as labels. Let :math:`\mathbf{A}_k` be an 21 | ordered set of unique labels along the :math:`k^{th}` dimension, then the 22 | coordinates, :math:`\mathbf{X}_k`, along a labeled dimension are 23 | 24 | .. math:: 25 | \mathbf{X}_k = \mathbf{A}_k. 26 | 27 | 28 | Attributes 29 | """""""""" 30 | 31 | .. cssclass:: table-bordered table-hover centered table-striped 32 | 33 | .. list-table:: 34 | :widths: 25 25 50 35 | :header-rows: 1 36 | 37 | * - Name 38 | - Type 39 | - Description 40 | 41 | * - labels 42 | - [String, String, ... ] 43 | - A `required` ordered array of labels along the dimension. 44 | 45 | 46 | Example 47 | """"""" 48 | 49 | The following LabeledDimension object, 50 | 51 | .. code:: 52 | 53 | { 54 | "type": "labeled", 55 | "labels": ["Cu", "Fe", "Si", "H", "Li"] 56 | } 57 | 58 | will generate a dimension, where the coordinates :math:`\mathbf{X}_k` are 59 | 60 | .. code:: 61 | 62 | ["Cu", "Fe", "Si", "H", "Li"] 63 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/dimensions/linear.rst: -------------------------------------------------------------------------------- 1 | 2 | LinearDimension 3 | ^^^^^^^^^^^^^^^ 4 | 5 | .. only:: html 6 | 7 | Generalized Class 8 | """"""""""""""""" 9 | 10 | .. raw:: html 11 | 12 | 13 | Dimension 14 | 15 | 16 | Description 17 | """"""""""" 18 | 19 | A LinearDimension is where the coordinates along the dimension follow a linear 20 | relationship with the indexes, :math:`\mathbf{J}_k`, along the dimension. Let 21 | :math:`\Delta x_k` be the `increment`, :math:`N_k \ge 1`, the number of points 22 | (`counts`), :math:`b_k`, the `coordinates offset`, and :math:`o_k`, the 23 | `origin offset` along the :math:`k^{th}` dimension, then the corresponding 24 | coordinates along the dimension, :math:`\mathbf{X}_k`, are given as 25 | 26 | .. math :: 27 | \mathbf{X}_k = \Delta x_k (\mathbf{J}_k - Z_k) + b_k \mathbf{1}, 28 | 29 | and the absolute coordinates as, 30 | 31 | .. math:: 32 | \mathbf{X}_k^\mathrm{abs} = \mathbf{X}_k + o_k \mathbf{1}. 33 | 34 | Here, :math:`\mathbf{1}` is an array of ones, and :math:`\mathbf{J}_k` is the 35 | array of indexes along the :math:`k^\mathrm{th}` dimension given as 36 | 37 | .. math:: 38 | \mathbf{J}_k = [0, 1, 2, 3, ..., N_k-1]. 39 | 40 | The term, :math:`Z_k`, is an integer with a value of :math:`Z_k=0` or 41 | :math:`\frac{T_k}{2}` when the value of `complex_fft` attribute of the 42 | corresponding dimension object is false or true, respectively. 43 | Here, :math:`T_k=N_k` and :math:`N_k-1` for even and odd 44 | value of :math:`N_k`, respectively. 45 | 46 | .. note:: 47 | When the value of the `complex_fft` attribute is true, and :math:`N_k` 48 | is even, the dependent variable value corresponding to the index 49 | :math:`\pm N_k/2` is an alias. 50 | 51 | 52 | Attributes 53 | """""""""" 54 | 55 | .. cssclass:: table-bordered table-hover centered table-striped 56 | 57 | .. list-table:: 58 | :widths: 25 25 50 59 | :header-rows: 1 60 | 61 | * - Name 62 | - Type 63 | - Description 64 | 65 | * - count 66 | - Integer 67 | - A `required` number of points, :math:`N_k`, along the dimension. 68 | 69 | * - increment 70 | - :ref:`sQ_uml` 71 | - A `required` increment, :math:`\Delta x_k`, along the dimension. 72 | 73 | * - coordinates_offset 74 | - :ref:`sQ_uml` 75 | - An `optional` coordinate, :math:`b_k`, corresponding to the zero of the 76 | indexes array, :math:`\bf{J}_k`. The default value is a physical quantity 77 | with zero numerical value. 78 | 79 | * - origin_offset 80 | - :ref:`sQ_uml` 81 | - An `optional` origin offset, :math:`o_k`, along the dimension. The 82 | default value is a physical quantity with zero numerical value. 83 | 84 | * - quantity_name 85 | - String 86 | - An `optional` quantity name associated with the physical quantities 87 | describing the dimension. 88 | 89 | * - period 90 | - :ref:`sQ_uml` 91 | - An `optional` period of the dimension. By default, the dimension is 92 | considered non-periodic. 93 | 94 | * - complex_fft 95 | - Boolean 96 | - An `optional` boolean with default value as False. 97 | If true, the coordinates along the dimension are evaluated as the output 98 | of a complex fast Fourier transform (FFT) routine. See the description. 99 | 100 | * - reciprocal 101 | - ReciprocalDimension 102 | - An `optional` object with attributes required to describe the reciprocal 103 | dimension. 104 | 105 | 106 | Example 107 | """"""" 108 | 109 | The following LinearDimension object, 110 | 111 | .. code:: 112 | 113 | { 114 | "type": "linear", 115 | "count": 10, 116 | "increment": "2 µA", 117 | "coordinates_offset": "0.1 µA" 118 | } 119 | 120 | will generate a dimension, where the coordinates :math:`\mathbf{X}_k` are 121 | 122 | .. code:: 123 | 124 | [ 125 | "0.1 µA", 126 | "2.1 µA", 127 | "4.1 µA", 128 | "6.1 µA", 129 | "8.1 µA", 130 | "10.1 µA", 131 | "12.1 µA", 132 | "14.1 µA", 133 | "16.1 µA", 134 | "18.1 µA" 135 | ] 136 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/dimensions/monotonic.rst: -------------------------------------------------------------------------------- 1 | 2 | MonotonicDimension 3 | ^^^^^^^^^^^^^^^^^^ 4 | 5 | .. only:: html 6 | 7 | Generalized Class 8 | """"""""""""""""" 9 | 10 | .. raw:: html 11 | 12 | 13 | Dimension 14 | 15 | 16 | Description 17 | """"""""""" 18 | 19 | A monotonic dimension is a quantitative dimension where the coordinates along 20 | the dimension are explicitly defined and, unlike a LinearDimension, may not 21 | be derivable from the ordered array of indexes along the dimension. 22 | Let :math:`\mathbf{A}_k` be an ordered set of strictly ascending or descending 23 | physical quantities and, :math:`o_k`, the origin offset along the 24 | :math:`k^{th}` dimension, then the coordinates, :math:`\mathbf{X}_k`, and the 25 | absolute coordinates, :math:`\mathbf{X}_k^\mathrm{abs}`, along a monotonic 26 | dimension follow 27 | 28 | .. math:: 29 | \begin{aligned} 30 | \mathbf{X}_k &= \mathbf{A}_k \text{ and}\\ 31 | \mathbf{X}_k^\mathrm{abs} &= \mathbf{X}_k + o_k \mathbf{1}, 32 | \end{aligned} 33 | 34 | respectively, where :math:`\mathbf{1}` is an array of ones. 35 | 36 | Attributes 37 | """""""""" 38 | 39 | .. cssclass:: table-bordered table-hover centered table-striped 40 | 41 | .. list-table:: 42 | :widths: 25 25 50 43 | :header-rows: 1 44 | 45 | * - Name 46 | - Type 47 | - Description 48 | 49 | * - coordinates 50 | - [:ref:`sQ_uml`, :ref:`sQ_uml`, ... ] 51 | - A `required` array of strictly ascending or descending ScalarQuantity. 52 | 53 | * - origin_offset 54 | - :ref:`sQ_uml` 55 | - An `optional` origin offset, :math:`o_k`, along the dimension. The 56 | default value is a physical quantity with zero numerical value. 57 | 58 | * - quantity_name 59 | - String 60 | - An `optional` quantity name associated with the physical quantities 61 | describing the dimension. 62 | 63 | * - period 64 | - :ref:`sQ_uml` 65 | - An `optional` period of the dimension. By default, the dimension is 66 | considered non-periodic. 67 | 68 | * - reciprocal 69 | - ReciprocalDimension 70 | - An `optional` object with attributes required to describe the reciprocal 71 | dimension. 72 | 73 | 74 | Example 75 | """"""" 76 | 77 | The following MonotonicDimension object, 78 | 79 | .. code:: 80 | 81 | { 82 | "type": "monotonic", 83 | "coordinates": ["1 µs", "10 µs", "100 µs", "1 ms", "10 ms", "100 ms", "1 s", "10 s"] 84 | } 85 | 86 | will generate a dimension, where the coordinates :math:`\mathbf{X}_k` are 87 | 88 | .. code:: 89 | 90 | ["1 µs", "10 µs", "100 µs", "1 ms", "10 ms", "100 ms", "1 s", "10 s"] 91 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/enumeration.rst: -------------------------------------------------------------------------------- 1 | 2 | =========== 3 | Enumeration 4 | =========== 5 | 6 | .. _dimObjectSubtype_uml: 7 | 8 | ---------------- 9 | DimObjectSubtype 10 | ---------------- 11 | 12 | An enumeration with literals as the value of the :ref:`dimension_uml` objects' 13 | `type` attribute. 14 | 15 | .. cssclass:: table-bordered table-hover centered table-striped 16 | 17 | .. list-table:: 18 | :widths: 25 75 19 | :header-rows: 1 20 | 21 | * - Literal 22 | - Description 23 | 24 | * - linear 25 | - Literal specifying an instance of a :ref:`linearDimension_uml` object. 26 | 27 | * - monotonic 28 | - Literal specifying an instance of a :ref:`monotonicDimension_uml` object. 29 | 30 | * - labeled 31 | - Literal specifying an instance of a :ref:`labeledDimension_uml` object. 32 | 33 | 34 | .. _DVObjectSubtype_uml: 35 | 36 | --------------- 37 | DVObjectSubtype 38 | --------------- 39 | 40 | An enumeration with literals as the values of the :ref:`dependent_var_uml` 41 | object' `type` attribute. 42 | 43 | .. cssclass:: table-bordered table-hover centered table-striped 44 | 45 | .. list-table:: 46 | :widths: 25 75 47 | :header-rows: 1 48 | 49 | * - Literal 50 | - Description 51 | 52 | * - internal 53 | - Literal specifying an instance of an :ref:`internal_uml` object. 54 | 55 | * - external 56 | - Literal specifying an instance of an :ref:`external_uml` object. 57 | 58 | .. _numericType_uml: 59 | 60 | ----------- 61 | NumericType 62 | ----------- 63 | 64 | An enumeration with literals as the value of the :ref:`dependent_var_uml` 65 | objects' `numeric_type` attribute. 66 | 67 | .. cssclass:: table-bordered table-hover centered table-striped 68 | 69 | .. list-table:: 70 | :widths: 25 75 71 | :header-rows: 1 72 | 73 | * - Literal 74 | - Description 75 | 76 | * - uint8 77 | - 8-bit unsigned integer 78 | 79 | * - uint16 80 | - 16-bit unsigned integer 81 | 82 | * - uint32 83 | - 32-bit unsigned integer 84 | 85 | * - uint64 86 | - 64-bit unsigned integer 87 | 88 | * - int8 89 | - 8-bit signed integer 90 | 91 | * - int16 92 | - 16-bit signed integer 93 | 94 | * - int32 95 | - 32-bit signed integer 96 | 97 | * - int64 98 | - 64-bit signed integer 99 | 100 | * - float32 101 | - 32-bit floating point number 102 | 103 | * - float64 104 | - 64-bit floating point number 105 | 106 | * - complex64 107 | - two 32-bit floating points numbers 108 | 109 | * - complex128 110 | - two 64-bit floating points numbers 111 | 112 | 113 | .. _quantityType_uml: 114 | 115 | ------------ 116 | QuantityType 117 | ------------ 118 | 119 | An enumeration with literals as the value of the :ref:`dependent_var_uml` 120 | objects' `quantity_type` attribute. The value is used in interpreting the 121 | `p`-components of the dependent variable. 122 | 123 | - **scalar** 124 | A dependent variable with :math:`p=1` component interpret as 125 | a scalar, :math:`\mathcal{S}_i=U_{0,i}`. 126 | 127 | - **vector_n** 128 | A dependent variable with :math:`p=n` components interpret 129 | as vector components, 130 | :math:`\mathcal{V}_i= \left[ U_{0,i}, U_{1,i}, ... U_{n-1,i}\right]`. 131 | 132 | - **matrix_n_m** 133 | A dependent variable with :math:`p=mn` components interpret 134 | as a :math:`n \times m` matrix as follows, 135 | 136 | .. math:: 137 | M_i = \left[ 138 | \begin{array}{cccc} 139 | U_{0,i} & U_{1,i} & ... &U_{(n-1)m,i} \\ 140 | U_{1,i} & U_{m+1,i} & ... &U_{(n-1)m+1,i} \\ 141 | \vdots & \vdots & \vdots & \vdots \\ 142 | U_{m-1,i} & U_{2m-1,i} & ... &U_{nm-1,i} 143 | \end{array} 144 | \right] 145 | 146 | - **symmetric_matrix_n** 147 | A dependent variable with :math:`p=n^2` components 148 | interpret as a matrix symmetric about its leading diagonal as shown below, 149 | 150 | .. math:: 151 | M^{(s)}_i = \left[ 152 | \begin{array}{cccc} 153 | U_{0,i} & U_{1,i} & ... & U_{n-1,i} \\ 154 | U_{1,i} & U_{n,i} & ... &U_{2n-2,i} \\ 155 | \vdots & \vdots & \vdots & \vdots \\ 156 | U_{n-1,i} & U_{2n-2,i} & ... &U_{\frac{n(n+1)}{2}-1,i} 157 | \end{array} 158 | \right] 159 | 160 | - **pixel_n** 161 | A dependent variable with :math:`p=n` components interpret as 162 | image/pixel components, 163 | :math:`\mathcal{P}_i= \left[ U_{0,i}, U_{1,i}, ... U_{n-1,i}\right]`. 164 | 165 | Here, the terms :math:`n` and :math:`m` are intergers. 166 | -------------------------------------------------------------------------------- /docs/CSDmodel_uml/scalarQuantity.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _sQ_uml: 3 | 4 | -------------- 5 | ScalarQuantity 6 | -------------- 7 | 8 | ScalarQuantity is an object composed of a numerical value and any valid SI unit 9 | symbol or any number of accepted non-SI unit symbols. It is serialized in the 10 | JSON file as a string containing a numerical value followed by the unit symbol, 11 | for example, 12 | 13 | - "3.4 m" (SI) 14 | - "2.3 bar" (non-SI) 15 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | PDFBUILDDIR = /tmp 10 | PDF = ../manual.pdf 11 | 12 | # Put it first so that "make" without argument is like "make help". 13 | help: 14 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 15 | 16 | .PHONY: help Makefile 17 | 18 | # Catch-all target: route all unknown targets to Sphinx using the new 19 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 20 | %: Makefile 21 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 22 | 23 | clean: 24 | rm -rf $(BUILDDIR)/* 25 | rm -rf auto_examples/ 26 | rm -rf auto_tutorials/ 27 | -------------------------------------------------------------------------------- /docs/_static/button.css: -------------------------------------------------------------------------------- 1 | .myButton { 2 | background: -webkit-gradient( 3 | linear, 4 | left top, 5 | left bottom, 6 | color-stop(0.05, #79bbff), 7 | color-stop(1, #378de5) 8 | ); 9 | background: -moz-linear-gradient(top, #79bbff 5%, #378de5 100%); 10 | background: -webkit-linear-gradient(top, #79bbff 5%, #378de5 100%); 11 | background: -o-linear-gradient(top, #79bbff 5%, #378de5 100%); 12 | background: -ms-linear-gradient(top, #79bbff 5%, #378de5 100%); 13 | background: linear-gradient(to bottom, #79bbff 5%, #378de5 100%); 14 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#79bbff', endColorstr='#378de5',GradientType=0); 15 | background-color: #79bbff; 16 | -moz-border-radius: 28px; 17 | -webkit-border-radius: 28px; 18 | border-radius: 28px; 19 | border: 1px solid #337bc4; 20 | display: inline-block; 21 | cursor: pointer; 22 | color: #ffffff; 23 | font-family: Arial; 24 | font-size: 12px; 25 | padding: 16px 31px; 26 | text-decoration: none; 27 | text-shadow: 0 1px 0 #528ecc; 28 | } 29 | .myButton:hover { 30 | background: -webkit-gradient( 31 | linear, 32 | left top, 33 | left bottom, 34 | color-stop(0.05, #378de5), 35 | color-stop(1, #79bbff) 36 | ); 37 | background: -moz-linear-gradient(top, #378de5 5%, #79bbff 100%); 38 | background: -webkit-linear-gradient(top, #378de5 5%, #79bbff 100%); 39 | background: -o-linear-gradient(top, #378de5 5%, #79bbff 100%); 40 | background: -ms-linear-gradient(top, #378de5 5%, #79bbff 100%); 41 | background: linear-gradient(to bottom, #378de5 5%, #79bbff 100%); 42 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#378de5', endColorstr='#79bbff',GradientType=0); 43 | background-color: #378de5; 44 | } 45 | .myButton:active { 46 | position: relative; 47 | top: 1px; 48 | } 49 | -------------------------------------------------------------------------------- /docs/_static/csdm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepanshs/csdmpy/434f6ce06cdaa03a73db07495beff1d151f8d824/docs/_static/csdm.png -------------------------------------------------------------------------------- /docs/_static/csdmpy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepanshs/csdmpy/434f6ce06cdaa03a73db07495beff1d151f8d824/docs/_static/csdmpy.png -------------------------------------------------------------------------------- /docs/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | 3 | {# Add the google webfonts needed for the 4 | logo #} {% block extrahead %} 5 | 6 | {% endblock %} {# Silence the bottom relbar. #} {% block relbar2 %}{% endblock 7 | %} 8 | 9 | {%- block footer %} 10 | 39 | 40 | 41 | 48 | {%- endblock %} 49 | -------------------------------------------------------------------------------- /docs/api/CSDM.rst: -------------------------------------------------------------------------------- 1 | .. _csdm_api: 2 | 3 | ---- 4 | CSDM 5 | ---- 6 | 7 | .. currentmodule:: csdmpy 8 | .. autoclass:: CSDM 9 | :show-inheritance: 10 | 11 | .. rubric:: Attributes Summary 12 | .. autosummary:: 13 | :nosignatures: 14 | 15 | ~CSDM.version 16 | ~CSDM.description 17 | ~CSDM.read_only 18 | ~CSDM.tags 19 | ~CSDM.timestamp 20 | ~CSDM.geographic_coordinate 21 | ~CSDM.dimensions 22 | ~CSDM.x 23 | ~CSDM.dependent_variables 24 | ~CSDM.y 25 | ~CSDM.application 26 | ~CSDM.data_structure 27 | ~CSDM.filename 28 | 29 | .. rubric:: Methods summary 30 | .. autosummary:: 31 | :nosignatures: 32 | 33 | ~CSDM.dict 34 | ~CSDM.to_dict 35 | ~CSDM.dumps 36 | ~CSDM.astype 37 | ~CSDM.to_list 38 | ~CSDM.save 39 | ~CSDM.copy 40 | ~CSDM.split 41 | ~CSDM.reshape 42 | ~CSDM.transpose 43 | ~CSDM.fft 44 | ~CSDM.to_positive_inc 45 | 46 | .. rubric:: Numpy compatible attributes summary 47 | .. autosummary:: 48 | :nosignatures: 49 | 50 | ~CSDM.real 51 | ~CSDM.imag 52 | ~CSDM.shape 53 | ~CSDM.size 54 | ~CSDM.T 55 | 56 | .. rubric:: Numpy compatible method summary 57 | .. autosummary:: 58 | :nosignatures: 59 | 60 | ~CSDM.max 61 | ~CSDM.min 62 | ~CSDM.clip 63 | ~CSDM.conj 64 | ~CSDM.round 65 | ~CSDM.sum 66 | ~CSDM.mean 67 | ~CSDM.var 68 | ~CSDM.std 69 | ~CSDM.prod 70 | 71 | .. rubric:: Attributes documentation 72 | 73 | .. autoattribute:: version 74 | .. autoattribute:: description 75 | .. autoattribute:: read_only 76 | .. autoattribute:: tags 77 | .. autoattribute:: timestamp 78 | .. autoattribute:: geographic_coordinate 79 | .. autoattribute:: dimensions 80 | .. autoattribute:: x 81 | .. autoattribute:: dependent_variables 82 | .. autoattribute:: y 83 | .. autoattribute:: application 84 | .. autoattribute:: data_structure 85 | .. autoattribute:: filename 86 | 87 | .. rubric:: Numpy compatible attributes documentation 88 | 89 | .. autoattribute:: real 90 | .. autoattribute:: imag 91 | .. autoattribute:: shape 92 | .. autoattribute:: size 93 | .. autoattribute:: T 94 | 95 | .. rubric:: Methods documentation 96 | 97 | .. automethod:: dict 98 | .. automethod:: to_dict 99 | .. automethod:: dumps 100 | .. automethod:: save 101 | .. automethod:: to_list 102 | .. automethod:: astype 103 | .. automethod:: copy 104 | .. automethod:: split 105 | .. automethod:: transpose 106 | .. automethod:: fft 107 | .. automethod:: reshape 108 | .. automethod:: to_positive_inc 109 | 110 | .. rubric:: Numpy compatible method documentation 111 | 112 | .. automethod:: max 113 | .. automethod:: min 114 | .. automethod:: clip 115 | .. automethod:: conj 116 | .. automethod:: round 117 | .. automethod:: sum 118 | .. automethod:: mean 119 | .. automethod:: var 120 | .. automethod:: std 121 | .. automethod:: prod 122 | -------------------------------------------------------------------------------- /docs/api/DependentVariable.rst: -------------------------------------------------------------------------------- 1 | .. _dv_api: 2 | 3 | ----------------- 4 | DependentVariable 5 | ----------------- 6 | 7 | .. currentmodule:: csdmpy 8 | 9 | .. autoclass:: DependentVariable 10 | :show-inheritance: 11 | 12 | .. rubric:: Attributes Summary 13 | 14 | .. autosummary:: 15 | :nosignatures: 16 | 17 | ~DependentVariable.type 18 | ~DependentVariable.description 19 | ~DependentVariable.application 20 | ~DependentVariable.name 21 | ~DependentVariable.unit 22 | ~DependentVariable.quantity_name 23 | ~DependentVariable.encoding 24 | ~DependentVariable.numeric_type 25 | ~DependentVariable.quantity_type 26 | ~DependentVariable.component_labels 27 | ~DependentVariable.components 28 | ~DependentVariable.components_url 29 | ~DependentVariable.axis_label 30 | ~DependentVariable.data_structure 31 | 32 | .. rubric:: Methods Summary 33 | 34 | .. autosummary:: 35 | :nosignatures: 36 | 37 | ~DependentVariable.to 38 | ~DependentVariable.dict 39 | ~DependentVariable.to_dict 40 | ~DependentVariable.copy 41 | 42 | 43 | .. rubric:: Attributes Documentation 44 | .. autoattribute:: type 45 | .. autoattribute:: description 46 | .. autoattribute:: application 47 | .. autoattribute:: name 48 | .. autoattribute:: unit 49 | .. autoattribute:: quantity_name 50 | .. autoattribute:: encoding 51 | .. autoattribute:: numeric_type 52 | .. autoattribute:: quantity_type 53 | .. autoattribute:: component_labels 54 | .. autoattribute:: components 55 | .. autoattribute:: components_url 56 | .. autoattribute:: axis_label 57 | .. autoattribute:: data_structure 58 | 59 | 60 | .. rubric:: Method Documentation 61 | .. automethod:: to 62 | .. automethod:: dict 63 | .. automethod:: to_dict 64 | .. automethod:: copy 65 | -------------------------------------------------------------------------------- /docs/api/Dimensions.rst: -------------------------------------------------------------------------------- 1 | .. _dim_api: 2 | 3 | --------- 4 | Dimension 5 | --------- 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | :caption: Dimension subtypes 10 | 11 | dimension/linear 12 | dimension/monotonic 13 | dimension/labeled 14 | 15 | 16 | .. currentmodule:: csdmpy 17 | 18 | .. autoclass:: Dimension 19 | :show-inheritance: 20 | 21 | .. rubric:: Attributes Summary 22 | 23 | .. autosummary:: 24 | :nosignatures: 25 | 26 | ~Dimension.type 27 | ~Dimension.description 28 | ~Dimension.application 29 | ~Dimension.coordinates 30 | ~Dimension.coords 31 | ~Dimension.absolute_coordinates 32 | ~Dimension.count 33 | ~Dimension.increment 34 | ~Dimension.coordinates_offset 35 | ~Dimension.origin_offset 36 | ~Dimension.complex_fft 37 | ~Dimension.quantity_name 38 | ~Dimension.label 39 | ~Dimension.labels 40 | ~Dimension.period 41 | ~Dimension.axis_label 42 | ~Dimension.data_structure 43 | 44 | .. rubric:: Methods Summary 45 | 46 | .. autosummary:: 47 | :nosignatures: 48 | 49 | ~Dimension.to 50 | ~Dimension.dict 51 | ~Dimension.to_dict 52 | ~Dimension.is_quantitative 53 | ~Dimension.copy 54 | ~Dimension.reciprocal_coordinates 55 | ~Dimension.reciprocal_increment 56 | 57 | 58 | .. rubric:: Attributes Documentation 59 | 60 | .. autoattribute:: type 61 | .. autoattribute:: description 62 | .. autoattribute:: application 63 | .. autoattribute:: coordinates 64 | .. autoattribute:: coords 65 | .. autoattribute:: absolute_coordinates 66 | .. autoattribute:: count 67 | .. autoattribute:: increment 68 | .. autoattribute:: coordinates_offset 69 | .. autoattribute:: origin_offset 70 | .. autoattribute:: complex_fft 71 | .. autoattribute:: quantity_name 72 | .. autoattribute:: label 73 | .. autoattribute:: labels 74 | .. autoattribute:: period 75 | .. autoattribute:: axis_label 76 | .. autoattribute:: data_structure 77 | 78 | 79 | .. rubric:: Method Documentation 80 | 81 | .. automethod:: to 82 | .. automethod:: dict 83 | .. automethod:: to_dict 84 | .. automethod:: is_quantitative 85 | .. automethod:: copy 86 | .. automethod:: reciprocal_coordinates 87 | .. automethod:: reciprocal_increment 88 | -------------------------------------------------------------------------------- /docs/api/csdmpy.rst: -------------------------------------------------------------------------------- 1 | 2 | 3 | ------ 4 | csdmpy 5 | ------ 6 | 7 | The `csdmpy` is a python package for importing and exporting files serialized 8 | with the core scientific dataset model file-format. The package supports a 9 | :math:`p`-component dependent variable, 10 | :math:`\mathbf{U} \equiv \{\mathbf{U}_{0}, \ldots,\mathbf{U}_{q}, 11 | \ldots,\mathbf{U}_{p-1} \}`, which is discretely sampled at :math:`M` unique 12 | points in a :math:`d`-dimensional space 13 | :math:`(\mathbf{X}_0, \ldots \mathbf{X}_k, \ldots \mathbf{X}_{d-1})`. Besides, 14 | the package also supports multiple dependent variables, 15 | :math:`\mathbf{U}_i`, sharing the same :math:`d`-dimensional space. 16 | 17 | Here, every dataset is an instance of the :ref:`csdm_api` class, which holds a 18 | list of dimensions and dependent variables. Every dimension, 19 | :math:`\mathbf{X}_k`, is an instance of the :ref:`dim_api` class, while every 20 | dependent variable, :math:`\mathbf{U}_i`, is an instance of the 21 | :ref:`dv_api` class. 22 | 23 | .. A UML class diagram of the `csdmpy` module is shown below. 24 | 25 | 26 | Methods 27 | ^^^^^^^ 28 | 29 | .. currentmodule:: csdmpy 30 | 31 | .. rubric:: Methods Summary 32 | 33 | .. autosummary:: 34 | :nosignatures: 35 | 36 | ~parse_dict 37 | ~load 38 | ~loads 39 | ~new 40 | ~as_dimension 41 | ~as_dependent_variable 42 | ~as_csdm 43 | ~plot 44 | ~join 45 | 46 | .. rubric:: Method Documentation 47 | 48 | .. autofunction:: parse_dict 49 | .. autofunction:: load 50 | .. autofunction:: loads 51 | .. autofunction:: new 52 | .. autofunction:: as_csdm 53 | .. autofunction:: as_dimension 54 | .. autofunction:: as_dependent_variable 55 | .. autofunction:: plot 56 | .. autofunction:: join 57 | -------------------------------------------------------------------------------- /docs/api/dimension/labeled.rst: -------------------------------------------------------------------------------- 1 | 2 | ---------------- 3 | LabeledDimension 4 | ---------------- 5 | 6 | .. currentmodule:: csdmpy 7 | 8 | .. autoclass:: LabeledDimension 9 | :show-inheritance: 10 | :members: 11 | -------------------------------------------------------------------------------- /docs/api/dimension/linear.rst: -------------------------------------------------------------------------------- 1 | 2 | --------------- 3 | LinearDimension 4 | --------------- 5 | 6 | .. currentmodule:: csdmpy 7 | 8 | .. autoclass:: LinearDimension 9 | :show-inheritance: 10 | :members: 11 | -------------------------------------------------------------------------------- /docs/api/dimension/monotonic.rst: -------------------------------------------------------------------------------- 1 | 2 | ------------------ 3 | MonotonicDimension 4 | ------------------ 5 | 6 | .. currentmodule:: csdmpy 7 | 8 | .. autoclass:: MonotonicDimension 9 | :show-inheritance: 10 | :members: 11 | -------------------------------------------------------------------------------- /docs/api/numpy_wrappers.rst: -------------------------------------------------------------------------------- 1 | .. _wrapper_api: 2 | 3 | Numpy methods 4 | ============= 5 | 6 | 7 | .. toctree:: 8 | 9 | wrappers/element_wise_operation 10 | wrappers/apodization 11 | -------------------------------------------------------------------------------- /docs/api/plotting_function.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _plot_api: 3 | 4 | -------- 5 | CSDMAxes 6 | -------- 7 | 8 | 9 | .. currentmodule:: csdmpy.helper_functions 10 | 11 | .. autoclass:: CSDMAxes 12 | :show-inheritance: 13 | 14 | .. rubric:: Methods Summary 15 | 16 | .. autosummary:: 17 | :nosignatures: 18 | 19 | ~CSDMAxes.plot 20 | ~CSDMAxes.scatter 21 | ~CSDMAxes.imshow 22 | ~CSDMAxes.contour 23 | ~CSDMAxes.contourf 24 | 25 | .. rubric:: Method Documentation 26 | 27 | .. automethod:: plot 28 | .. automethod:: scatter 29 | .. automethod:: imshow 30 | .. automethod:: contour 31 | .. automethod:: contourf 32 | -------------------------------------------------------------------------------- /docs/api/statistics.rst: -------------------------------------------------------------------------------- 1 | .. _csdmpy_statistics: 2 | 3 | Statistics 4 | ^^^^^^^^^^ 5 | 6 | .. currentmodule:: csdmpy.statistics 7 | 8 | .. rubric:: Methods Summary 9 | 10 | .. autosummary:: 11 | :nosignatures: 12 | 13 | ~integral 14 | ~mean 15 | ~var 16 | ~std 17 | 18 | .. rubric:: Method Documentation 19 | 20 | .. autofunction:: integral 21 | .. autofunction:: mean 22 | .. autofunction:: var 23 | .. autofunction:: std 24 | -------------------------------------------------------------------------------- /docs/api/wrappers/apodization.rst: -------------------------------------------------------------------------------- 1 | Dimension specific Apodization methods 2 | -------------------------------------- 3 | 4 | The following methods of form 5 | 6 | .. math:: 7 | y = f(a x), 8 | 9 | where :math:`a` is the function argument, and :math:`x` are the coordinates 10 | along the dimension, apodize the components of the dependent variables along 11 | the respective dimensions. The dimensionality of :math:`a` must be the 12 | reciprocal of that of :math:`x`. 13 | The resulting CSDM object has the same number of dimensions as the original 14 | object. 15 | 16 | .. currentmodule:: csdmpy.apodize 17 | 18 | .. rubric:: Method Summary 19 | .. autosummary:: 20 | ~sin 21 | ~cos 22 | ~tan 23 | ~arcsin 24 | ~arccos 25 | ~arctan 26 | ~exp 27 | 28 | .. rubric:: Method Documentation 29 | .. autofunction:: sin 30 | .. autofunction:: cos 31 | .. autofunction:: tan 32 | .. autofunction:: arcsin 33 | .. autofunction:: arccos 34 | .. autofunction:: arctan 35 | .. autofunction:: exp 36 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | Changelog 3 | ========= 4 | 5 | .. include:: ../CHANGELOG 6 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Installation 3 | ============ 4 | 5 | Installing ``csdmpy`` 6 | --------------------- 7 | 8 | On Local machine (Using pip) 9 | '''''''''''''''''''''''''''' 10 | 11 | PIP is a package manager for Python packages and is included with python version 3.4 12 | and higher. PIP is the easiest way to install python packages. 13 | 14 | .. code-block:: bash 15 | 16 | $ pip install csdmpy 17 | 18 | If you get a ``PermissionError``, it usually means that you do not have the required 19 | administrative access to install new packages to your Python installation. In this 20 | case, you may consider adding the ``--user`` option, at the end of the statement, to 21 | install the package into your home directory. You can read more about how to do this in 22 | the `pip documentation `_. 23 | 24 | .. code-block:: bash 25 | 26 | $ pip install csdmpy --user 27 | 28 | 29 | Upgrading to a newer version 30 | """""""""""""""""""""""""""" 31 | 32 | To upgrade, type the following in the terminal/Prompt 33 | 34 | .. code-block:: bash 35 | 36 | $ pip install csdmpy -U 37 | 38 | On Google Colab Notebook 39 | '''''''''''''''''''''''' 40 | 41 | Colaboratory is a Google research project. It is a Jupyter notebook environment that 42 | runs entirely in the cloud. Launch a new notebook on 43 | `Colab `_. To install the package, type 44 | 45 | .. code-block:: shell 46 | 47 | !pip install csdmpy 48 | 49 | in the first cell, and execute. All done! You may now start using the library. 50 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=../../csdmpy-doc 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/plotting_with_pyplot/one_D_plots.rst: -------------------------------------------------------------------------------- 1 | 2 | 1D CSDM objects with ``plot()|scatter()`` 3 | ----------------------------------------- 4 | 5 | 1D{1} datasets 6 | '''''''''''''' 7 | 8 | .. plot:: ../pyplot/oneD_plot.py 9 | :include-source: 10 | 11 | 12 | 1D{1, 1, ...} datasets 13 | '''''''''''''''''''''' 14 | 15 | Plotting on the same Axes 16 | """"""""""""""""""""""""" 17 | 18 | When multiple single-component dependent variables are present within the CSDM object, 19 | the data from all dependent-variables is plotted on the same axes. The name of each 20 | dependent variable is displayed within the legend. 21 | 22 | Plotting on separate Axes 23 | """"""""""""""""""""""""" 24 | 25 | To plot the data from individual dependent variables onto separate axes, use the 26 | :meth:`~csdmpy.CSDM.split` method to first split the CSDM object with `n` dependent 27 | variables into `n` CSDM objects with single dependent variables, and then plot them 28 | separately. 29 | 30 | .. plot:: ../pyplot/oneD111_plot.py 31 | :include-source: 32 | -------------------------------------------------------------------------------- /docs/plotting_with_pyplot/two_D_plots.rst: -------------------------------------------------------------------------------- 1 | 2 | 2D CSDM objects with ``imshow()|contour()|contourf()`` 3 | ------------------------------------------------------ 4 | 5 | 2D{1} datasets 6 | '''''''''''''' 7 | 8 | .. plot:: ../pyplot/twoD_plot.py 9 | :include-source: 10 | 11 | 12 | 2D{1, 1, ..} datasets 13 | ''''''''''''''''''''' 14 | 15 | Plotting on the same Axes 16 | """"""""""""""""""""""""" 17 | 18 | When multiple single-component dependent variables are present within the CSDM object, 19 | the data from all dependent-variables is plotted on the same axes. The name of each 20 | dependent variable is displayed along the color bar. 21 | 22 | .. plot:: ../pyplot/twoD111_plot.py 23 | :include-source: 24 | 25 | Plotting on separate Axes 26 | """"""""""""""""""""""""" 27 | 28 | To plot the data from individual dependent variables onto separate axes, use the 29 | :meth:`~csdmpy.CSDM.split` method to first split the CSDM object with `n` dependent 30 | variables into `n` CSDM objects with single dependent variables, and then plot them 31 | separately. 32 | -------------------------------------------------------------------------------- /docs/referenceAPI.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | API-Reference 3 | ============= 4 | 5 | .. toctree:: 6 | 7 | api/csdmpy 8 | api/CSDM 9 | api/Dimensions 10 | api/DependentVariable 11 | api/statistics 12 | api/plotting_function 13 | api/numpy_wrappers 14 | 15 | 16 | .. api/Archive/DimensionWithLinearSpacing 17 | .. api/Archive/DimensionWithArbitrarySpacing 18 | .. api/Archive/DimensionWithLabels 19 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy>=1.20 2 | scipy>=1.10 3 | matplotlib>=3.3.3 4 | astropy>=5.1 5 | numexpr>=2.10.0 6 | 7 | setuptools>=27.3 8 | requests>=2.21.0 9 | 10 | # Building Docs requirements 11 | sphinxjp.themes.basicstrap 12 | sphinx<6.0 13 | sphinx-gallery>0.6.2 14 | pillow>=7.1.2 15 | breathe>=4.34.0 16 | sphinx_copybutton>=0.3.0 17 | sphinx_tabs>3.0 18 | recommonmark 19 | sphinx-version-warning 20 | -------------------------------------------------------------------------------- /docs/startFromScratch/A fun example.rst: -------------------------------------------------------------------------------- 1 | 2 | ------------------- 3 | An emoji 😁 example 4 | ------------------- 5 | 6 | Let's make use of what we learned so far and create a simple 1D{1} dataset. 7 | To make it interesting, let's create an emoji dataset. 8 | 9 | Start by importing the `csdmpy` package. 10 | 11 | .. doctest:: 12 | 13 | >>> import csdmpy as cp 14 | 15 | Create a labeled dimension. Here, we make use of python dictionary. 16 | 17 | .. doctest:: 18 | 19 | >>> x = dict(type="labeled", labels=["🍈", "🍉", "🍋", "🍌", "🥑", "🍍"]) 20 | 21 | The above python dictionary contains two keys. The `type` key identifies the 22 | dimension as a labeled dimension while the `labels` key holds an 23 | array of labels. In this example, the labels are emojis. Add this dictionary 24 | to the list of dimensions. 25 | 26 | Next, create a dependent variable. Similarly, set up a python dictionary corresponding 27 | to the dependent variable object. 28 | 29 | .. doctest:: 30 | 31 | >>> y = dict( 32 | ... type="internal", 33 | ... numeric_type="float32", 34 | ... quantity_type="scalar", 35 | ... components=[[0.5, 0.25, 1, 2, 1, 0.25]], 36 | ... ) 37 | 38 | Here, the python dictionary contains `type`, `numeric_type`, and `components` 39 | key. The value of the `components` key holds an array of data values 40 | corresponding to the labels from the labeled dimension. 41 | 42 | Create a csdm object from the dimensions and dependent variables and we have a 😂 dataset... 43 | 44 | .. doctest:: 45 | 46 | >>> fun_data = cp.CSDM( 47 | ... dimensions=[x], dependent_variables=[y], description="An emoji dataset" 48 | ... ) 49 | >>> print(fun_data.data_structure) 50 | { 51 | "csdm": { 52 | "version": "1.0", 53 | "description": "An emoji dataset", 54 | "dimensions": [ 55 | { 56 | "type": "labeled", 57 | "labels": [ 58 | "🍈", 59 | "🍉", 60 | "🍋", 61 | "🍌", 62 | "🥑", 63 | "🍍" 64 | ] 65 | } 66 | ], 67 | "dependent_variables": [ 68 | { 69 | "type": "internal", 70 | "numeric_type": "float32", 71 | "quantity_type": "scalar", 72 | "components": [ 73 | [ 74 | "0.5, 0.25, ..., 1.0, 0.25" 75 | ] 76 | ] 77 | } 78 | ] 79 | } 80 | } 81 | 82 | To serialize this file, use the :meth:`~csdmpy.CSDM.save` method of the 83 | `fun_data` instance as 84 | 85 | .. doctest:: 86 | 87 | >>> fun_data.dependent_variables[0].encoding = "base64" 88 | >>> fun_data.save("my_file.csdf") 89 | 90 | 91 | In the above code, the components from the 92 | :attr:`~csdmpy.CSDM.dependent_variables` attribute at index zero, are 93 | encoded as `base64` strings before serializing to the `my_file.csdf` file. 94 | 95 | You may also save the components as a binary file, in which case, the file is 96 | serialized with a `.csdfe` file extension. 97 | 98 | .. doctest:: 99 | 100 | >>> fun_data.dependent_variables[0].encoding = "raw" 101 | >>> fun_data.save("my_file_raw.csdfe") 102 | 103 | .. testcleanup:: 104 | 105 | import os 106 | 107 | os.remove("my_file.csdf") 108 | os.remove("my_file_raw.csdfe") 109 | os.remove("my_file_raw_0.dat") 110 | -------------------------------------------------------------------------------- /docs/startFromScratch/add_dependent_variable_object.rst: -------------------------------------------------------------------------------- 1 | .. _adding_dv: 2 | 3 | ----------------------------------------------- 4 | Adding DependentVariable objects to CSDM object 5 | ----------------------------------------------- 6 | 7 | There are two subtypes of DependentVariable class: 8 | 9 | - **InternalDependentVariable**: 10 | We refer to an instance of the DependentVariable as *internal* when the 11 | components of the dependent variable are listed along with the other 12 | metadata specifying the dependent variable. 13 | - **ExternalDependentVariable**: 14 | We refer to an instance of the DependentVariable as *external* when the 15 | components of the dependent variable are stored in an external file as 16 | binary data either locally or at a remote server. 17 | 18 | 19 | **Using an instance of the DependentVariable class** 20 | 21 | Please read the topic :ref:`generate_dependent_variable_objects` for details 22 | on how to generate an instance of the DependentVariable class. Once created, 23 | use the dependent variables to generate a CSDM object. 24 | 25 | .. doctest:: 26 | 27 | >>> dv = cp.as_dependent_variable(np.arange(10)) 28 | >>> new_data = cp.CSDM(dependent_variables=[dv]) 29 | >>> print(new_data) 30 | CSDM( 31 | DependentVariable( 32 | [[0 1 2 3 4 5 6 7 8 9]], quantity_type=scalar, numeric_type=int64) 33 | ) 34 | 35 | 36 | **Using Python's dictionary objects** 37 | 38 | When using python dictionaries, the key-value pairs of the dictionary must 39 | be a valid collection for the given DependentVariable subtype. For example, 40 | 41 | .. doctest:: 42 | 43 | >>> dv0 = { 44 | ... "type": "internal", 45 | ... "quantity_type": "scalar", 46 | ... "description": "This is an internal scalar dependent variable", 47 | ... "unit": "cm", 48 | ... "components": np.arange(50), 49 | ... } 50 | >>> dv1 = { 51 | ... "type": "internal", 52 | ... "quantity_type": "vector_2", 53 | ... "description": "This is an internal vector dependent variable", 54 | ... "unit": "cm", 55 | ... "components": np.arange(100), 56 | ... } 57 | >>> new_data = cp.CSDM(dependent_variables=[dv0, dv1]) 58 | >>> print(new_data) 59 | CSDM( 60 | DependentVariable( 61 | [[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 62 | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 63 | 48 49]] cm, quantity_type=scalar, numeric_type=int64), 64 | DependentVariable( 65 | [[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 66 | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 67 | 48 49] 68 | [50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 69 | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 70 | 98 99]] cm, quantity_type=vector_2, numeric_type=int64) 71 | ) 72 | -------------------------------------------------------------------------------- /docs/startFromScratch/add_dimension_object.rst: -------------------------------------------------------------------------------- 1 | .. _how_to_add_dimension: 2 | 3 | --------------------------------------- 4 | Adding Dimension objects to CSDM object 5 | --------------------------------------- 6 | 7 | There are three subtypes of Dimension objects, 8 | 9 | - LinearDimension 10 | - MonotonicDimension 11 | - LabeledDimension 12 | 13 | **Using an instance of the Dimension class** 14 | 15 | Please read the topic :ref:`generate_dimension_objects` for details on how to 16 | generate an instance of the Dimension class. Once created, use the dimensions 17 | to generate a CSDM object. 18 | 19 | 20 | .. doctest:: 21 | 22 | >>> linear_dim = cp.LinearDimension(count=10, increment="0.1 C/V") 23 | >>> new_data = cp.CSDM(dimensions=[linear_dim]) 24 | >>> print(new_data) 25 | CSDM( 26 | LinearDimension([0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9] C / V) 27 | ) 28 | 29 | **Using Python's dictionary objects** 30 | 31 | When using python dictionaries, the key-value pairs of the dictionary must 32 | be a valid collection for the given Dimension subtype. For example, 33 | 34 | .. doctest:: 35 | 36 | >>> # dictionary representation of a linear dimension. 37 | >>> d0 = { 38 | ... "type": "linear", 39 | ... "description": "This is a linear dimension", 40 | ... "count": 5, 41 | ... "increment": "0.1 rad", 42 | ... } 43 | >>> # dictionary representation of a monotonic dimension. 44 | >>> d1 = { 45 | ... "type": "monotonic", 46 | ... "description": "This is a monotonic dimension", 47 | ... "coordinates": ["1 m/s", "2 cm/s", "4 mm/s"], 48 | ... } 49 | >>> # dictionary representation of a labeled dimension. 50 | >>> d2 = { 51 | ... "type": "labeled", 52 | ... "description": "This is a labeled dimension", 53 | ... "labels": ["Cu", "Ag", "Au"], 54 | ... } 55 | >>> # add the dictionaries to the CSDM object. 56 | >>> new_data = cp.CSDM(dimensions=[d0, d1, d2]) 57 | >>> print(new_data) 58 | CSDM( 59 | LinearDimension([0. 0.1 0.2 0.3 0.4] rad), 60 | MonotonicDimension([1. 0.02 0.004] m / s), 61 | LabeledDimension(['Cu' 'Ag' 'Au']) 62 | ) 63 | -------------------------------------------------------------------------------- /docs/startFromScratch/dimension/generate/dimension_objects.rst: -------------------------------------------------------------------------------- 1 | .. _generate_dimension_objects: 2 | 3 | ============================ 4 | Generating Dimension objects 5 | ============================ 6 | 7 | 8 | .. include:: linear.rst 9 | .. include:: monotonic.rst 10 | .. include:: labeled.rst 11 | -------------------------------------------------------------------------------- /docs/startFromScratch/dimension/generate/labeled.rst: -------------------------------------------------------------------------------- 1 | ---------------- 2 | LabeledDimension 3 | ---------------- 4 | 5 | A LabeledDimension is one where the coordinates along the dimension are 6 | string labels. You can similarly generate a labeled dimension. 7 | 8 | **Using the** :class:`~csdmpy.Dimension` **class.** 9 | 10 | .. doctest:: 11 | 12 | >>> import csdmpy as cp 13 | >>> x = cp.Dimension(type="labeled", labels=["The", "great", "circle"]) 14 | >>> print(x) 15 | LabeledDimension(['The' 'great' 'circle']) 16 | 17 | **Using the** :class:`~csdmpy.LabeledDimension` **class.** 18 | 19 | .. doctest:: 20 | 21 | >>> x = cp.LabeledDimension(labels=["The", "great", "circle"]) 22 | >>> print(x) 23 | LabeledDimension(['The' 'great' 'circle']) 24 | 25 | **From numpy arrays or python list.** 26 | 27 | Use the :meth:`~csdmpy.as_dimension` method to convert a numpy array as a 28 | Dimension object. 29 | 30 | .. doctest:: 31 | 32 | >>> array = ["The", "great", "circle"] 33 | >>> x = cp.as_dimension(array) 34 | >>> print(x) 35 | LabeledDimension(['The' 'great' 'circle']) 36 | -------------------------------------------------------------------------------- /docs/startFromScratch/dimension/generate/linear.rst: -------------------------------------------------------------------------------- 1 | --------------- 2 | LinearDimension 3 | --------------- 4 | 5 | A LinearDimension is where the coordinates are regularly spaced along the 6 | dimension. This type of dimension is frequently encountered in many scientific 7 | datasets. There are several ways to generate LinearDimension. 8 | 9 | **Using the** :class:`~csdmpy.Dimension` **class.** 10 | 11 | .. doctest:: 12 | 13 | >>> import csdmpy as cp 14 | >>> x = cp.Dimension( 15 | ... type="linear", 16 | ... count=10, 17 | ... increment="0.1 s", 18 | ... label="time", 19 | ... description="A temporal dimension.", 20 | ... ) 21 | >>> print(x) 22 | LinearDimension([0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9] s) 23 | 24 | **Using the** :class:`~csdmpy.LinearDimension` **class.** 25 | 26 | .. doctest:: 27 | 28 | >>> import csdmpy as cp 29 | >>> x1 = cp.LinearDimension( 30 | ... count=10, increment="0.1 s", label="time", description="A temporal dimension." 31 | ... ) 32 | >>> print(x1) 33 | LinearDimension([0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9] s) 34 | 35 | **Using NumPy array** 36 | 37 | You may also create a LinearDimesion object from a one-dimensional NumPy array 38 | using the :meth:`~csdmpy.as_dimension` method. 39 | 40 | .. doctest:: 41 | 42 | >>> import numpy as np 43 | >>> array = np.arange(10) * 0.1 44 | >>> x2 = cp.as_dimension(array) 45 | >>> print(x2) 46 | LinearDimension([0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]) 47 | 48 | Note, the Dimension object ``x2`` is dimensionless. You can create a physical 49 | dimension by either providing an appropriate unit as the argument to the 50 | :meth:`~csdmpy.as_dimension` method, 51 | 52 | .. doctest:: 53 | 54 | >>> x3 = cp.as_dimension(array, unit="s") 55 | >>> print(x3) 56 | LinearDimension([0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9] s) 57 | 58 | or appropriately multiplying the dimension object ``x2`` with a 59 | :class:`~csdmpy.ScalarQuantity`. 60 | 61 | .. doctest:: 62 | 63 | >>> x2 *= cp.ScalarQuantity("s") 64 | >>> print(x2) 65 | LinearDimension([0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9] s) 66 | 67 | The coordinates of the ``x2`` LinearDimension object are 68 | 69 | .. doctest:: 70 | 71 | >>> x2.coordinates 72 | 73 | 74 | where ``x2.coordinates`` is a `Quantity `_ 75 | array. The value and the unit of the quantity instance are 76 | 77 | .. doctest:: 78 | 79 | >>> # To access the numpy array 80 | >>> numpy_array = x.coordinates.value 81 | >>> print("numpy array =", numpy_array) 82 | numpy array = [0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9] 83 | 84 | >>> # To access the astropy.unit 85 | >>> unit = x.coordinates.unit 86 | >>> print("unit =", unit) 87 | unit = s 88 | 89 | respectively. 90 | 91 | .. Note:: When generating LinearDimension objects from NumPy array, the NumPy 92 | array must be one-dimensional and regularly spaced. 93 | 94 | .. doctest:: 95 | 96 | >>> cp.as_dimension(np.arange(20).reshape(2, 10)) # doctest: +SKIP 97 | ValueError: Cannot convert a 2 dimensional array to a Dimension object. 98 | -------------------------------------------------------------------------------- /docs/startFromScratch/dimension/generate/monotonic.rst: -------------------------------------------------------------------------------- 1 | ------------------ 2 | MonotonicDimension 3 | ------------------ 4 | 5 | A MonotonicDimension is one where the coordinates along the dimension are 6 | sampled monotonically, that is, either strictly increasing or decreasing 7 | coordinates. Like the LinearDimension, there are several ways to generate 8 | a MonotonicDimension. 9 | 10 | **Using the** :class:`~csdmpy.Dimension` **class.** 11 | 12 | .. doctest:: 13 | 14 | >>> import csdmpy as cp 15 | >>> x = cp.Dimension( 16 | ... type="monotonic", 17 | ... coordinates=[ 18 | ... "10ns", 19 | ... "100ns", 20 | ... "1µs", 21 | ... "10µs", 22 | ... "100µs", 23 | ... "1ms", 24 | ... "10ms", 25 | ... "100ms", 26 | ... "1s", 27 | ... "10s", 28 | ... ], 29 | ... ) 30 | >>> print(x) 31 | MonotonicDimension([1.e+01 1.e+02 1.e+03 1.e+04 1.e+05 1.e+06 1.e+07 1.e+08 1.e+09 1.e+10] ns) 32 | 33 | **Using the** :class:`~csdmpy.MonotonicDimension` **class.** 34 | 35 | .. doctest:: 36 | 37 | >>> import numpy as np 38 | >>> array = np.asarray( 39 | ... [ 40 | ... -0.28758166, 41 | ... -0.22712233, 42 | ... -0.19913859, 43 | ... -0.17235106, 44 | ... -0.1701172, 45 | ... -0.10372635, 46 | ... -0.01817061, 47 | ... 0.05936719, 48 | ... 0.18141424, 49 | ... 0.34758913, 50 | ... ] 51 | ... ) 52 | >>> x = cp.MonotonicDimension(coordinates=array) * cp.ScalarQuantity("cm") 53 | >>> print(x) 54 | MonotonicDimension([-0.28758166 -0.22712233 -0.19913859 -0.17235106 -0.1701172 -0.10372635 55 | -0.01817061 0.05936719 0.18141424 0.34758913] cm) 56 | 57 | In the above example, we generate a dimensionless MonotonicDimension from 58 | the NumPy array and then scale its dimensionality by multiplying the object with an 59 | appropriate :class:`~csdmpy.ScalarQuantity`. 60 | 61 | **From numpy arrays.** 62 | 63 | Use the :meth:`~csdmpy.as_dimension` method to convert a numpy array as a 64 | Dimension object. 65 | 66 | .. doctest:: 67 | 68 | >>> numpy_array = 10 ** (np.arange(10) / 10) 69 | >>> x_dim = cp.as_dimension(numpy_array, unit="A") 70 | >>> print(x_dim) 71 | MonotonicDimension([1. 1.25892541 1.58489319 1.99526231 2.51188643 3.16227766 72 | 3.98107171 5.01187234 6.30957344 7.94328235] A) 73 | 74 | 75 | When generating MonotonicDimension object using the Numpy array, the array 76 | must be monotonic, that is, either strictly increasing or decreasing. 77 | An exception will be raised otherwise. 78 | 79 | .. doctest:: 80 | 81 | >>> numpy_array = np.random.rand(10) 82 | >>> x_dim = cp.as_dimension(numpy_array) # doctest: +SKIP 83 | Exception: Invalid array for Dimension object. 84 | -------------------------------------------------------------------------------- /docs/startFromScratch/dimension/interact/dimension_objects.rst: -------------------------------------------------------------------------------- 1 | 2 | ================================== 3 | Interacting with Dimension objects 4 | ================================== 5 | 6 | .. include:: linear.rst 7 | .. include:: monotonic.rst 8 | -------------------------------------------------------------------------------- /docs/startFromScratch/interacting_with_csdmpy_objects.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | Interacting with csdmpy objects 3 | =============================== 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | dimension/interact/dimension_objects 9 | interacting_with_csdm 10 | -------------------------------------------------------------------------------- /docs/startFromScratch/save_dataset.rst: -------------------------------------------------------------------------------- 1 | 2 | ------------------------------- 3 | Serializing CSDM object to file 4 | ------------------------------- 5 | 6 | An instance of a :ref:`csdm_api` object is serialized as a csdf/csdfe 7 | JSON-format file with the :meth:`~csdmpy.CSDM.save` method. 8 | When serializing the dependent-variable from the CSDM object to the data-file, 9 | the `csdmpy` module uses the value of the dependent variable's 10 | :attr:`~csdmpy.DependentVariable.encoding` attribute to 11 | determine the encoding type of the serialized data. There are three encoding 12 | types for the dependent variables: 13 | 14 | - ``none`` 15 | - ``base64`` 16 | - ``raw`` 17 | 18 | .. note:: By default, all instances of 19 | :attr:`~csdmpy.DependentVariable` from a 20 | :attr:`~csdmpy.CSDM` object are serialized as 21 | base64 strings. 22 | 23 | For the following examples, consider ``data`` as an instance of the 24 | :attr:`~csdmpy.CSDM` class. 25 | 26 | To serialize a dependent variable with a given encoding type, set the value 27 | of it's encoding attribute to the respective encoding. For example, 28 | 29 | **As ``none`` encoding** 30 | 31 | .. code:: 32 | 33 | >>> data.dependent_variables[0].encoding = "none" 34 | >>> data.save('my_file.csdf') 35 | 36 | The above code will serialize the dependent variable at index zero to a JSON 37 | file, `my_file.csdf`, where each component of the dependent variable is 38 | serialized as an array of JSON number. 39 | 40 | **As ``base64`` encoding** 41 | 42 | >>> data.dependent_variables[0].encoding = "base64" 43 | >>> data.save('my_file.csdf') 44 | 45 | The above code will serialize the dependent variable at index zero to a JSON 46 | file, `my_file.csdf`, where each component of the dependent variable is 47 | serialized as a base64 string. 48 | 49 | **As ``raw`` encoding** 50 | 51 | >>> data.dependent_variables[0].encoding = "raw" 52 | >>> data.save('my_file.csdfe') 53 | 54 | The above code will serialize the metadata from the dependent variable at index 55 | zero to a 56 | JSON file, `my_file.csdfe`, which includes a link to an external file where the 57 | components of the respective dependent variable are serialized as a binary 58 | array. The binary file is named, `my_file_0.dat`, where `my_file` is the 59 | filename from the argument of the save method, and `0` is the index number of 60 | the dependent variable from the CSDM object. 61 | 62 | **Multiple encoding types** 63 | 64 | In the case of multiple dependent-variables, you may choose to serialize 65 | each dependent variables with a different encoding, for example, 66 | 67 | .. code:: 68 | 69 | >>> my_data.dependent_variables[0].encoding = "raw" 70 | >>> my_data.dependent_variables[1].encoding = "base64" 71 | >>> my_data.dependent_variables[2].encoding = "none" 72 | >>> my_data.dependent_variables[3].encoding = "base64" 73 | >>> my_data.save('my_file.csdfe') 74 | 75 | In the above example, ``my_data`` is a CSDM object containing four 76 | :attr:`~csdmpy.DependentVariable` objects. Here, we 77 | serialize the dependent variable at index two with ``none``, 78 | the dependent variables at index one and three with ``bae64``, 79 | and the dependent variables at index zero with ``raw`` encoding, respectively. 80 | 81 | .. note:: Because an instance of the dependent variable, that is, the index 82 | zero in the above example, is set to be serialized with an external 83 | subtype, the corresponding file should be saved with a .csdfe extension. 84 | 85 | .. testcleanup:: 86 | 87 | import os 88 | 89 | os.remove("my_file.csdf") 90 | os.remove("my_file.csdfe") 91 | os.remove("my_file_0.dat") 92 | -------------------------------------------------------------------------------- /docs/startFromScratch/start.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | Using csdmpy objects 3 | ==================== 4 | 5 | The `csdmpy` module is not just designed for deserializing and serializing 6 | the `.csdf` or `.csdfe` files. It can also be used to create new datasets, 7 | a feature that is most useful when converting datasets to CSDM compliant 8 | files. 9 | 10 | .. toctree:: 11 | :maxdepth: 3 12 | 13 | dimension/generate/dimension_objects 14 | generating_dependent_variable_object 15 | generating_csdm_object 16 | add_dimension_object 17 | add_dependent_variable_object 18 | -------------------------------------------------------------------------------- /docs/using_csdm_with_pyplot.rst: -------------------------------------------------------------------------------- 1 | 2 | ==================================== 3 | Plotting CSDM object with matplotlib 4 | ==================================== 5 | 6 | As you may have noticed by now, a CSDM object holds basic metadata such as the label, 7 | unit, and physical quantity of the dimensions and dependent-variables, which is enough 8 | to visualize the CSDM datasets on proper coordinate axes. In the following section, we 9 | illustrate how you may use the CSDM object with the matplotlib plotting library. 10 | 11 | When plotting CSDM objects with matplotlib, we make use of the CSDM object's metadata 12 | to produce a `matplotlib Axes `_ object with 13 | basic formattings, such as the coordinate axes label, dependent variable labels, and 14 | legends. You may still additionally customize your figures. Please refer to the 15 | `matplotlib documentation `_ for further details. 16 | 17 | To enable plotting CSDM objects with matplotlib, add a ``projection="csdm"`` to the 18 | matplotlib's Axes instance, as follows, 19 | 20 | .. code-block:: python 21 | 22 | ax = plt.subplot(projection="csdm") 23 | # now add the matplotlib plotting functions to this axes. 24 | # ax.plot(csdm_object) or 25 | # ax.imshow(csdm_object) ... etc 26 | 27 | See the following examples. 28 | 29 | .. toctree:: 30 | :maxdepth: 2 31 | 32 | plotting_with_pyplot/one_D_plots 33 | plotting_with_pyplot/two_D_plots 34 | -------------------------------------------------------------------------------- /examples/1D_1_examples/README.rst: -------------------------------------------------------------------------------- 1 | Scalar, 1D{1} datasets 2 | ====================== 3 | 4 | The 1D{1} datasets are one dimensional, :math:`d=1`, with one single-component, 5 | :math:`p=1`, dependent variable. These datasets are the most common, and we, 6 | therefore, provide a few examples from various fields of science. 7 | -------------------------------------------------------------------------------- /examples/1D_1_examples/plot_0_gmsl.py: -------------------------------------------------------------------------------- 1 | """ 2 | Global Mean Sea Level rise dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following dataset is the Global Mean Sea Level (GMSL) rise from the late 7 | # 19th to the Early 21st Century [#f0]_. The 8 | # `original dataset `_ was 9 | # downloaded as a CSV file and subsequently converted to the CSD model format. 10 | # 11 | # Let's import this file. 12 | import csdmpy as cp 13 | 14 | filename = "https://www.ssnmr.org/sites/default/files/CSDM/gmsl/GMSL.csdf" 15 | sea_level = cp.load(filename) 16 | 17 | # %% 18 | # The variable `filename` is a string with the address to the `.csdf` file. 19 | # The :meth:`~csdmpy.load` method of the `csdmpy` module reads the 20 | # file and returns an instance of the :ref:`csdm_api` class, in 21 | # this case, as a variable ``sea_level``. For a quick preview of the data 22 | # structure, use the :attr:`~csdmpy.CSDM.data_structure` attribute of this 23 | # instance. 24 | 25 | print(sea_level.data_structure) 26 | 27 | # %% 28 | # .. warning:: 29 | # The serialized string from the :attr:`~csdmpy.CSDM.data_structure` 30 | # attribute is not the same as the JSON serialization on the file. 31 | # This attribute is only intended for a quick preview of the data 32 | # structure and avoids displaying large datasets. Do not use 33 | # the value of this attribute to save the data to the file. Instead, use the 34 | # :meth:`~csdmpy.CSDM.save` method of the :ref:`CSDM ` 35 | # class. 36 | 37 | # %% 38 | # The tuple of the dimensions and dependent variables, from this example, are 39 | 40 | x = sea_level.dimensions 41 | y = sea_level.dependent_variables 42 | 43 | # %% 44 | # respectively. The coordinates along the dimension and the 45 | # component of the dependent variable are 46 | print(x[0].coordinates) 47 | 48 | # %% 49 | # and 50 | print(y[0].components[0]) 51 | 52 | # %% 53 | # respectively. 54 | 55 | # %% 56 | # **Plotting the data** 57 | # 58 | # .. note:: 59 | # The following code is only for illustrative purposes. The users may use 60 | # any plotting library to visualize their datasets. 61 | import matplotlib.pyplot as plt 62 | 63 | plt.figure(figsize=(5, 3.5)) 64 | ax = plt.subplot(projection="csdm") 65 | 66 | # csdmpy is compatible with matplotlib function. Use the csdm object as the argument 67 | # of the matplotlib function. 68 | ax.plot(sea_level) 69 | plt.tight_layout() 70 | plt.show() 71 | 72 | # %% 73 | # The following is a quick description of the above code. Within the code, we 74 | # make use of the csdm instance's attributes in addition to the matplotlib 75 | # functions. The first line is an import call for the matplotlib functions. 76 | # The following line generates a plot of the coordinates along the 77 | # dimension verse the component of the dependent variable. 78 | # The next line sets the x-range. For labeling the axes, 79 | # use the :attr:`~csdmpy.Dimension.axis_label` attribute 80 | # of both dimension and dependent variable instances. For the figure title, 81 | # use the :attr:`~csdmpy.DependentVariable.name` attribute 82 | # of the dependent variable instance. The next statement adds the grid lines. 83 | # For additional information, refer to `Matplotlib `_ 84 | # documentation. 85 | 86 | # %% 87 | # .. seealso:: 88 | # :ref:`getting_started` 89 | # 90 | 91 | # %% 92 | # .. rubric:: Citation 93 | # 94 | # .. [#f0] Church JA, White NJ. Sea-Level Rise from the Late 19th to the Early 21st 95 | # Century. Surveys in Geophysics. 2011;32:585–602. DOI:10.1007/s10712-011-9119-1. 96 | -------------------------------------------------------------------------------- /examples/1D_1_examples/plot_2_EPR.py: -------------------------------------------------------------------------------- 1 | """ 2 | Electron Paramagnetic Resonance (EPR) dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following is a simulation of the 7 | # `EPR dataset `_, 8 | # originally obtained as a JCAMP-DX file, and subsequently converted to the 9 | # CSD model file-format. The data structure of this dataset follows, 10 | import matplotlib.pyplot as plt 11 | 12 | import csdmpy as cp 13 | 14 | domain = "https://www.ssnmr.org/sites/default/files/CSDM" 15 | filename = f"{domain}/EPR/AmanitaMuscaria_base64.csdf" 16 | EPR_data = cp.load(filename) 17 | print(EPR_data.data_structure) 18 | 19 | # %% 20 | # and the corresponding plot. 21 | plt.figure(figsize=(5, 3.5)) 22 | ax = plt.subplot(projection="csdm") 23 | ax.plot(EPR_data) 24 | plt.tight_layout() 25 | plt.show() 26 | -------------------------------------------------------------------------------- /examples/1D_1_examples/plot_3_GS.py: -------------------------------------------------------------------------------- 1 | """ 2 | Gas Chromatography dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following 7 | # `Gas Chromatography dataset `_ 8 | # was obtained as a JCAMP-DX file, and subsequently converted to the CSD model 9 | # file-format. The data structure of the gas chromatography dataset follows, 10 | import matplotlib.pyplot as plt 11 | 12 | import csdmpy as cp 13 | 14 | filename = "https://www.ssnmr.org/sites/default/files/CSDM/GC/cinnamon_base64.csdf" 15 | GCData = cp.load(filename) 16 | print(GCData.data_structure) 17 | 18 | # %% 19 | # and the corresponding plot 20 | plt.figure(figsize=(5, 3.5)) 21 | ax = plt.subplot(projection="csdm") 22 | ax.plot(GCData) 23 | plt.tight_layout() 24 | plt.show() 25 | -------------------------------------------------------------------------------- /examples/1D_1_examples/plot_4_FTIR.py: -------------------------------------------------------------------------------- 1 | """ 2 | Fourier Transform Infrared Spectroscopy (FTIR) dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following 7 | # `FTIR dataset `_, 8 | # was obtained as a JCAMP-DX file, and subsequently converted to the CSD model 9 | # file-format. The data structure of the FTIR dataset follows, 10 | import matplotlib.pyplot as plt 11 | 12 | import csdmpy as cp 13 | 14 | filename = "https://www.ssnmr.org/sites/default/files/CSDM/ir/caffeine_base64.csdf" 15 | FTIR_data = cp.load(filename) 16 | print(FTIR_data.data_structure) 17 | 18 | # %% 19 | # and the corresponding plot. 20 | plt.figure(figsize=(5, 3.5)) 21 | ax = plt.subplot(projection="csdm") 22 | ax.plot(FTIR_data) 23 | ax.invert_xaxis() 24 | plt.tight_layout() 25 | plt.show() 26 | 27 | # %% 28 | # Because, FTIR spectrum is conventionally displayed on a reverse axis, an 29 | # optional `reverse_axis` argument is provided to the :meth:`~csdmpy.plot` method. 30 | # Its value is an order list of boolean, corresponding to the order of the 31 | # dimensions. 32 | -------------------------------------------------------------------------------- /examples/1D_1_examples/plot_5_UV-vis.py: -------------------------------------------------------------------------------- 1 | """ 2 | Ultraviolet–visible (UV-vis) dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following 7 | # `UV-vis dataset `_ 8 | # was obtained as a JCAMP-DX file, and subsequently converted to the CSD model 9 | # file-format. The data structure of the UV-vis dataset follows, 10 | import matplotlib.pyplot as plt 11 | 12 | import csdmpy as cp 13 | 14 | domain = "https://www.ssnmr.org/sites/default/files/CSDM" 15 | filename = f"{domain}/UV-vis/benzeneVapour_base64.csdf" 16 | UV_data = cp.load(filename) 17 | print(UV_data.data_structure) 18 | 19 | # %% 20 | # and the corresponding plot 21 | plt.figure(figsize=(5, 3.5)) 22 | ax = plt.subplot(projection="csdm") 23 | ax.plot(UV_data) 24 | plt.tight_layout() 25 | plt.show() 26 | -------------------------------------------------------------------------------- /examples/1D_1_examples/plot_6_Mass.py: -------------------------------------------------------------------------------- 1 | """ 2 | Mass spectrometry (sparse) dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following mass spectrometry data of acetone is an example of a sparse dataset. 7 | # Here, the CSDM data file holds a sparse dependent variable. Upon import, the 8 | # components of the dependent variable sparsely populates the coordinate grid. The 9 | # remaining unpopulated coordinates are assigned a zero value. 10 | import matplotlib.pyplot as plt 11 | 12 | import csdmpy as cp 13 | 14 | filename = "https://www.ssnmr.org/sites/default/files/CSDM/MassSpec/acetone.csdf" 15 | mass_spec = cp.load(filename) 16 | print(mass_spec.data_structure) 17 | 18 | # %% 19 | # Here, the coordinates along the dimension are 20 | print(mass_spec.dimensions[0].coordinates) 21 | 22 | # %% 23 | # and the corresponding components of the dependent variable, 24 | print(mass_spec.dependent_variables[0].components[0]) 25 | 26 | # %% 27 | # Note, only eight values were listed in the dependent variable's `components` 28 | # attribute in the `.csdf` file. The remaining component values were set to zero. 29 | plt.figure(figsize=(5, 3.5)) 30 | ax = plt.subplot(projection="csdm") 31 | ax.plot(mass_spec) 32 | plt.tight_layout() 33 | plt.show() 34 | -------------------------------------------------------------------------------- /examples/2D_1_examples/README.rst: -------------------------------------------------------------------------------- 1 | Scalar, 2D{1} datasets 2 | ====================== 3 | 4 | The 2D{1} datasets are two dimensional, :math:`d=2`, with one 5 | single-component dependent variable, :math:`p=1`. Following are some 6 | 2D{1} example datasets from various scientific fields expressed in CSDM 7 | format. 8 | -------------------------------------------------------------------------------- /examples/2D_1_examples/plot_0_astronomy.py: -------------------------------------------------------------------------------- 1 | """ 2 | Astronomy dataset 3 | ^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following dataset is a new observation of the Bubble Nebula 7 | # acquired by `The Hubble Heritage Team 8 | # `_, 9 | # in February 2016. The original dataset was obtained in the FITS format 10 | # and subsequently converted to the CSD model file-format. For the convenience of 11 | # illustration, we have downsampled the original dataset. 12 | # 13 | # Let's load the `.csdfe` file and look at its data structure. 14 | import matplotlib.pyplot as plt 15 | 16 | import csdmpy as cp 17 | 18 | domain = "https://www.ssnmr.org/sites/default/files/CSDM" 19 | filename = f"{domain}/BubbleNebula/Bubble_nebula.csdf" 20 | bubble_nebula = cp.load(filename) 21 | print(bubble_nebula.data_structure) 22 | 23 | # %% 24 | # Here, the variable ``bubble_nebula`` is an instance of the :ref:`csdm_api` 25 | # class. From the data structure, one finds two dimensions, labeled as 26 | # *Right Ascension* and *Declination*, and one single-component dependent 27 | # variable named *Bubble Nebula, 656nm*. 28 | 29 | # %% 30 | # Let's get the tuple of the dimension and dependent variable instances from 31 | # the ``bubble_nebula`` instance following, 32 | x = bubble_nebula.dimensions 33 | y = bubble_nebula.dependent_variables 34 | 35 | # %% 36 | # There are two dimension instances in ``x``. Let's look 37 | # at the coordinates along each dimension, using the 38 | # :attr:`~csdmpy.Dimension.coordinates` attribute of the 39 | # respective instances. 40 | 41 | # %% 42 | print(x[0].coordinates[:10]) 43 | 44 | # %% 45 | print(x[1].coordinates[:10]) 46 | 47 | # %% 48 | # Here, we only print the first ten coordinates along the respective dimensions. 49 | 50 | # %% 51 | # The component of the dependent variable is accessed through the 52 | # :attr:`~csdmpy.DependentVariable.components` attribute. 53 | y00 = y[0].components[0] 54 | 55 | # %% 56 | # **Visualize the dataset** 57 | from matplotlib.colors import LogNorm 58 | 59 | plt.figure(figsize=(6, 4.5)) 60 | ax = plt.subplot(projection="csdm") 61 | ax.imshow(bubble_nebula, norm=LogNorm(vmin=7.5e-3, clip=True), aspect="auto") 62 | plt.tight_layout() 63 | plt.show() 64 | -------------------------------------------------------------------------------- /examples/2D_1_examples/plot_2_TEM.py: -------------------------------------------------------------------------------- 1 | """ 2 | Transmission Electron Microscopy (TEM) dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following `TEM dataset `_ is 7 | # a section of an early larval brain of *Drosophila melanogaster* used in the 8 | # analysis of neuronal microcircuitry. The dataset was obtained 9 | # from the `TrakEM2 tutorial `_ and 10 | # subsequently converted to the CSD model file-format. 11 | # 12 | # Let's import the CSD model data-file and look at its data structure. 13 | import matplotlib.pyplot as plt 14 | 15 | import csdmpy as cp 16 | 17 | filename = "https://www.ssnmr.org/sites/default/files/CSDM/TEM/TEM.csdf" 18 | TEM = cp.load(filename) 19 | print(TEM.data_structure) 20 | 21 | # %% 22 | # This dataset consists of two linear dimensions and one single-component 23 | # dependent variable. The tuple of the dimension and the dependent variable 24 | # instances from this example are 25 | x = TEM.dimensions 26 | y = TEM.dependent_variables 27 | 28 | # %% 29 | # and the respective coordinates (viewed only for the first ten coordinates), 30 | print(x[0].coordinates[:10]) 31 | 32 | # %% 33 | print(x[1].coordinates[:10]) 34 | 35 | # %% 36 | # For convenience, let's convert the coordinates from `nm` to `µm` using the 37 | # :meth:`~csdmpy.Dimension.to` method of the respective :ref:`dim_api` instance, 38 | x[0].to("µm") 39 | x[1].to("µm") 40 | 41 | # %% 42 | # and plot the data. 43 | plt.figure(figsize=(5, 3.5)) 44 | ax = plt.subplot(projection="csdm") 45 | cb = ax.imshow(TEM, aspect="auto") 46 | plt.colorbar(cb, ax=ax) 47 | plt.tight_layout() 48 | plt.show() 49 | -------------------------------------------------------------------------------- /examples/2D_1_examples/plot_3_labeled.py: -------------------------------------------------------------------------------- 1 | """ 2 | Labeled Dataset 3 | ^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The CSD model also supports labeled dimensions. In the following example, we 7 | # present a mixed `linear` and `labeled` two-dimensional dataset representing 8 | # the population of the country as a function of time. The dataset is obtained from 9 | # `The World Bank `_. 10 | # 11 | # Import the `csdmpy` model and load the dataset. 12 | import csdmpy as cp 13 | 14 | filename = "https://www.ssnmr.org/sites/default/files/CSDM/labeled/population.csdf" 15 | labeled_data = cp.load(filename) 16 | 17 | # %% 18 | # The tuple of dimension and dependent variable objects from ``labeled_data`` instance 19 | # are 20 | x = labeled_data.dimensions 21 | y = labeled_data.dependent_variables 22 | 23 | # %% 24 | # Since one of the dimensions is a `labeled` dimension, let's make use of the 25 | # :attr:`~csdmpy.Dimension.type` attribute of the dimension instances 26 | # to find out which dimension is `labeled`. 27 | print(x[0].type) 28 | 29 | # %% 30 | print(x[1].type) 31 | 32 | # %% 33 | # Here, the second dimension is the `labeled` dimension with [#f1]_ 34 | print(x[1].count) 35 | 36 | # %% 37 | # labels, where the first five labels are 38 | print(x[1].labels[:5]) 39 | 40 | # %% 41 | # .. note:: 42 | # For labeled dimensions, the :attr:`~csdmpy.Dimension.coordinates` 43 | # attribute is an alias of the :attr:`~csdmpy.Dimension.labels` 44 | # attribute. 45 | print(x[1].coordinates[:5]) 46 | 47 | # %% 48 | # The coordinates along the first dimension, viewed up to the first ten 49 | # points, are 50 | print(x[0].coordinates[:10]) 51 | 52 | # %% 53 | # **Plotting the dataset** 54 | # 55 | # You may plot this dataset however you like. Here, we use a bar graph to 56 | # represent the population of countries in the year 2017. The data 57 | # corresponding to this year is a cross-section of the dependent variable 58 | # at index 57 along the ``x[0]`` dimension. 59 | print(x[0].coordinates[57]) 60 | 61 | # %% 62 | # To keep the plot simple, we only plot the first 20 country labels along 63 | # the ``x[1]`` dimension. 64 | import matplotlib.pyplot as plt 65 | import numpy as np 66 | 67 | x_data = x[1].coordinates[:20] 68 | x_pos = np.arange(20) 69 | y_data = y[0].components[0][:20, 57] 70 | 71 | plt.bar(x_data, y_data, align="center", alpha=0.5) 72 | plt.xticks(x_pos, x_data, rotation=90) 73 | plt.ylabel(y[0].axis_label[0]) 74 | plt.yscale("log") 75 | plt.title(y[0].name) 76 | plt.tight_layout() 77 | plt.show() 78 | 79 | # %% 80 | # .. rubric:: Footnotes 81 | # 82 | # .. [#f1] In the CSD model, the attribute count is only valid for the 83 | # :ref:`linearDimension_uml`. In `csdmpy`, however, the 84 | # :attr:`~csdmpy.Dimension.count` attribute is valid for all 85 | # dimension objects and returns an integer with the number of grid 86 | # points along the dimension. 87 | -------------------------------------------------------------------------------- /examples/README.rst: -------------------------------------------------------------------------------- 1 | 2 | =============== 3 | Example Gallery 4 | =============== 5 | 6 | In this section, we present illustrative examples for importing files 7 | serialized with the CSD model, using the `csdmpy` package. 8 | Because the CSD model allows multi-dimensional datasets with multiple dependent 9 | variables, we use a shorthand notation of :math:`d\mathrm{D}\{p\}` to 10 | indicate that a dataset has a :math:`p`-component dependent variable defined 11 | on a :math:`d`-dimensional coordinate grid. 12 | In the case of `correlated datasets`, the number of components in each 13 | dependent variable is given as a list within the curly braces, `i.e.`, 14 | :math:`d\mathrm{D}\{p_0, p_1, p_2, ...\}`. 15 | -------------------------------------------------------------------------------- /examples/correlated_examples/README.rst: -------------------------------------------------------------------------------- 1 | Correlated datasets 2 | =================== 3 | 4 | The Core Scientific Dataset Model (CSDM) supports multiple dependent 5 | variables that share the same `d`-dimensional coordinate grid, where 6 | :math:`d>=0`. 7 | We call the dependent variables from these datasets as `correlated datasets`. 8 | Following are a few examples of the correlated dataset. 9 | -------------------------------------------------------------------------------- /examples/correlated_examples/plot_0_0D11_dataset.py: -------------------------------------------------------------------------------- 1 | """ 2 | Scatter, 0D{1,1} dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # We start with a 0D{1,1} correlated dataset, that is, a dataset 7 | # without a coordinate grid. A 0D{1,1} dataset has no dimensions, d = 0, and 8 | # two single-component dependent variables. 9 | # In the following example [#f3]_, the two `correlated` dependent variables are 10 | # the :math:`^{29}\text{Si}` - :math:`^{29}\text{Si}` nuclear spin couplings, 11 | # :math:`^2J`, across a Si-O-Si linkage, and the `s`-character product on the 12 | # O and two Si along the Si-O bond across the Si-O-Si linkage. 13 | # 14 | # Let's import the dataset. 15 | import csdmpy as cp 16 | 17 | domain = "https://www.ssnmr.org/sites/default/files/CSDM" 18 | filename = f"{domain}/correlatedDataset/0D_dataset/J_vs_s.csdf" 19 | zero_d_dataset = cp.load(filename) 20 | 21 | # %% 22 | # Since the dataset has no dimensions, the value of the 23 | # :attr:`~csdmpy.CSDM.dimensions` attribute of the :attr:`~csdmpy.CSDM` 24 | # class is an empty tuple, 25 | print(zero_d_dataset.dimensions) 26 | 27 | # %% 28 | # The :attr:`~csdmpy.CSDM.dependent_variables` attribute, however, holds 29 | # two dependent-variable objects. The data structure from the two dependent 30 | # variables is 31 | print(zero_d_dataset.dependent_variables[0].data_structure) 32 | 33 | # %% 34 | # and 35 | print(zero_d_dataset.dependent_variables[1].data_structure) 36 | 37 | # %% 38 | # respectively. 39 | 40 | # %% 41 | # **Visualizing the dataset** 42 | # 43 | # The correlation plot of the dependent-variables from the dataset is 44 | # shown below. 45 | import matplotlib.pyplot as plt 46 | 47 | y0 = zero_d_dataset.dependent_variables[0] 48 | y1 = zero_d_dataset.dependent_variables[1] 49 | 50 | plt.scatter(y1.components[0], y0.components[0], s=2, c="k") 51 | plt.xlabel(y1.axis_label[0]) 52 | plt.ylabel(y0.axis_label[0]) 53 | plt.tight_layout() 54 | plt.show() 55 | 56 | # %% 57 | # .. rubric:: Citation 58 | # 59 | # .. [#f3] Srivastava DJ, Florian P, Baltisberger JH, Grandinetti PJ. Correlating 60 | # geminal couplings to structure in framework silicates. Phys Chem Chem Phys. 61 | # 2018;20:562–571. DOI:10.1039/C7CP06486A 62 | -------------------------------------------------------------------------------- /examples/pixel/README.rst: -------------------------------------------------------------------------------- 1 | Pixel datasets 2 | ============== 3 | -------------------------------------------------------------------------------- /examples/pixel/plot_0_image.py: -------------------------------------------------------------------------------- 1 | """ 2 | Image, 2D{3} datasets 3 | ^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The 2D{3} dataset is two dimensional, :math:`d=2`, with 7 | # a single three-component dependent variable, :math:`p=3`. 8 | # A common example from this subset is perhaps the RGB image dataset. 9 | # An RGB image dataset has two spatial dimensions and one dependent 10 | # variable with three components corresponding to the red, green, and blue color 11 | # intensities. 12 | # 13 | # The following is an example of an RGB image dataset. 14 | import csdmpy as cp 15 | 16 | filename = "https://www.ssnmr.org/sites/default/files/CSDM/image/raccoon_image.csdf" 17 | ImageData = cp.load(filename) 18 | print(ImageData.data_structure) 19 | 20 | # %% 21 | # The tuple of the dimension and dependent variable instances from 22 | # ``ImageData`` instance are 23 | x = ImageData.dimensions 24 | y = ImageData.dependent_variables 25 | 26 | # %% 27 | # respectively. There are two dimensions, and the coordinates along each 28 | # dimension are 29 | print("x0 =", x[0].coordinates[:10]) 30 | 31 | # %% 32 | print("x1 =", x[1].coordinates[:10]) 33 | 34 | # %% 35 | # respectively, where only first ten coordinates along each dimension is displayed. 36 | 37 | # %% 38 | # The dependent variable is the image data, as also seen from the 39 | # :attr:`~csdmpy.DependentVariable.quantity_type` attribute 40 | # of the corresponding :ref:`dv_api` instance. 41 | 42 | print(y[0].quantity_type) 43 | 44 | # %% 45 | # From the value `pixel_3`, `pixel` indicates a pixel data, while `3` 46 | # indicates the number of pixel components. 47 | 48 | # %% 49 | # As usual, the components of the dependent variable are accessed through 50 | # the :attr:`~csdmpy.DependentVariable.components` attribute. 51 | # To access the individual components, use the appropriate array indexing. 52 | # For example, 53 | 54 | print(y[0].components[0]) 55 | 56 | # %% 57 | # will return an array with the first component of all data values. In this case, 58 | # the components correspond to the red color intensity, also indicated by the 59 | # corresponding component label. The label corresponding to 60 | # the component array is accessed through the 61 | # :attr:`~csdmpy.DependentVariable.component_labels` 62 | # attribute with appropriate indexing, that is 63 | print(y[0].component_labels[0]) 64 | 65 | # %% 66 | # To avoid displaying larger output, as an example, we print the shape of 67 | # each component array (using Numpy array's `shape` attribute) for the three 68 | # components along with their respective labels. 69 | 70 | # %% 71 | print(y[0].component_labels[0], y[0].components[0].shape) 72 | 73 | # %% 74 | print(y[0].component_labels[1], y[0].components[1].shape) 75 | 76 | # %% 77 | print(y[0].component_labels[2], y[0].components[2].shape) 78 | 79 | # %% 80 | # The shape (768, 1024) corresponds to the number of points from the each 81 | # dimension instances. 82 | 83 | # %% 84 | # .. note:: 85 | # In this example, since there is only one dependent variable, the index 86 | # of `y` is set to zero, which is ``y[0]``. The indices for the 87 | # :attr:`~csdmpy.DependentVariable.components` and the 88 | # :attr:`~csdmpy.DependentVariable.component_labels`, 89 | # on the other hand, spans through the number of components. 90 | 91 | # %% 92 | # Now, to visualize the dataset as an RGB image, 93 | import matplotlib.pyplot as plt 94 | 95 | img_float = ImageData.astype(float) 96 | img_float /= 256.0 # convert int8 values to [0, 1] range for image plot 97 | ax = plt.subplot(projection="csdm") 98 | ax.imshow(img_float, origin="upper") 99 | plt.tight_layout() 100 | 101 | plt.show() 102 | -------------------------------------------------------------------------------- /examples/sparse/README.rst: -------------------------------------------------------------------------------- 1 | Sparse datasets 2 | =============== 3 | -------------------------------------------------------------------------------- /examples/sparse/plot_0_1D_sparse.py: -------------------------------------------------------------------------------- 1 | """ 2 | Sparse along one dimension, 2D{1,1} dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following is an example [#f2]_ of a 2D{1,1} sparse dataset with two-dimensions, 7 | # :math:`d=2`, and two, :math:`p=2`, sparse single-component dependent-variables, 8 | # where the component is sparsely sampled along one dimension. The following is an 9 | # example of a hypercomplex acquisition of the NMR dataset. 10 | # 11 | # Let's import the CSD model data-file. 12 | import csdmpy as cp 13 | 14 | filename = "https://www.ssnmr.org/sites/default/files/CSDM/sparse/iglu_1d.csdf" 15 | sparse_1d = cp.load(filename) 16 | 17 | # %% 18 | # There are two linear dimensions and two single-component sparse dependent variables. 19 | # The tuple of the dimension and the dependent variable instances are 20 | x = sparse_1d.dimensions 21 | y = sparse_1d.dependent_variables 22 | 23 | # %% 24 | # The coordinates, viewed only for the first ten coordinates, are 25 | print(x[0].coordinates[:10]) 26 | 27 | # %% 28 | print(x[1].coordinates[:10]) 29 | 30 | # %% 31 | # Converting the coordinates to `ms`. 32 | x[0].to("ms") 33 | x[1].to("ms") 34 | 35 | # %% 36 | # **Visualizing the dataset** 37 | import matplotlib.pyplot as plt 38 | 39 | # split the CSDM object with two dependent variables into two CSDM objects with single 40 | # dependent variables. 41 | 42 | cos, sin = sparse_1d.split() 43 | 44 | # cosine data 45 | plt.figure(figsize=(5, 3.5)) 46 | ax = plt.subplot(projection="csdm") 47 | cb = ax.contourf(cos.real) 48 | plt.colorbar(cb, ax=ax) 49 | plt.tight_layout() 50 | plt.show() 51 | 52 | # %% 53 | 54 | # sine data 55 | plt.figure(figsize=(5, 3.5)) 56 | ax = plt.subplot(projection="csdm") 57 | cb = ax.contourf(sin.real) 58 | plt.colorbar(cb, ax=ax) 59 | plt.tight_layout() 60 | plt.show() 61 | 62 | # %% 63 | # .. rubric:: Citation 64 | # 65 | # .. [#f2] Balsgart NM, Vosegaard T., Fast Forward Maximum entropy reconstruction 66 | # of sparsely sampled data., J Magn Reson. 2012, 223, 164-169. 67 | # doi: 10.1016/j.jmr.2012.07.002 68 | -------------------------------------------------------------------------------- /examples/sparse/plot_1_2D_sparse.py: -------------------------------------------------------------------------------- 1 | """ 2 | Sparse along two dimensions, 2D{1,1} dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following is an example [#f2]_ of a 2D{1,1} sparse dataset with two-dimensions, 7 | # :math:`d=2`, and two, :math:`p=2`, sparse single-component dependent-variables, 8 | # where the component is sparsely sampled along two dimensions. The following is an 9 | # example of a hypercomplex acquisition of the NMR dataset. 10 | # 11 | # Let's import the CSD model data-file and look at its data structure. 12 | import csdmpy as cp 13 | 14 | filename = "https://www.ssnmr.org/sites/default/files/CSDM/sparse/iglu_2d.csdf" 15 | sparse_2d = cp.load(filename) 16 | 17 | # %% 18 | # There are two linear dimensions and two single-component sparse dependent variables. 19 | # The tuple of the dimension and the dependent variable instances are 20 | x = sparse_2d.dimensions 21 | y = sparse_2d.dependent_variables 22 | 23 | # %% 24 | # The coordinates, viewed only for the first ten coordinates, are 25 | print(x[0].coordinates[:10]) 26 | 27 | # %% 28 | print(x[1].coordinates[:10]) 29 | 30 | # %% 31 | # Converting the coordinates to `ms`. 32 | x[0].to("ms") 33 | x[1].to("ms") 34 | 35 | # %% 36 | # **Visualize the dataset** 37 | import matplotlib.pyplot as plt 38 | 39 | # split the CSDM object with two dependent variables into two CSDM objects with single 40 | # dependent variables. 41 | 42 | cos, sin = sparse_2d.split() 43 | 44 | # cosine data 45 | plt.figure(figsize=(5, 3.5)) 46 | ax = plt.subplot(projection="csdm") 47 | cb = ax.contourf(cos.real) 48 | plt.colorbar(cb, ax=ax) 49 | plt.tight_layout() 50 | plt.show() 51 | 52 | # %% 53 | 54 | # sine data 55 | plt.figure(figsize=(5, 3.5)) 56 | ax = plt.subplot(projection="csdm") 57 | cb = ax.contourf(sin.real) 58 | plt.colorbar(cb, ax=ax) 59 | plt.tight_layout() 60 | plt.show() 61 | 62 | # %% 63 | # .. rubric:: Citation 64 | # 65 | # .. [#f2] Balsgart NM, Vosegaard T., Fast Forward Maximum entropy reconstruction 66 | # of sparsely sampled data., J Magn Reson. 2012, 223, 164-169. 67 | # doi: 10.1016/j.jmr.2012.07.002 68 | -------------------------------------------------------------------------------- /examples/tensor/README.rst: -------------------------------------------------------------------------------- 1 | 2 | Tensor datasets 3 | =============== 4 | -------------------------------------------------------------------------------- /examples/tensor/plot_0_3D_diff_tensor_mri.py: -------------------------------------------------------------------------------- 1 | """ 2 | Diffusion tensor MRI, 3D{6} dataset 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The following is an example of a 3D{6} diffusion tensor MRI dataset with three 7 | # spatial dimensions, :math:`d=3`, and one, :math:`p=1`, dependent-variable 8 | # with six components. For illustration, we have reduced the size of the dataset. 9 | # The complete diffusion tensor MRI dataset, in the CSDM format, is available 10 | # `online `_. 11 | # The original dataset [#f1]_ is also available. 12 | # 13 | # Let's import the CSDM data-file and look at its data structure. 14 | import csdmpy as cp 15 | 16 | domain = "https://www.ssnmr.org/sites/default/files/CSDM" 17 | filename = f"{domain}/tensor/human_brain/brain_MRI_reduced_example.csdf" 18 | diff_mri = cp.load(filename) 19 | 20 | # %% 21 | # There are three linear dimensions in this dataset, corresponding to the x, y, and z 22 | # spatial dimensions, 23 | x = diff_mri.dimensions 24 | print(x[0].label, x[1].label, x[2].label) 25 | 26 | # %% 27 | # and one six-component dependent variables holding the diffusion tensor components. 28 | # Because the diffusion tensor is a symmetric second-rank tensor, we only need six 29 | # tensor components. The components of the tensor are ordered as 30 | y = diff_mri.dependent_variables 31 | print(y[0].component_labels) 32 | 33 | # %% 34 | # The symmetric matrix information is also found with the 35 | # :attr:`~csdmpy.DependentVariable.quantity_type` attribute, 36 | print(y[0].quantity_type) 37 | 38 | # %% 39 | # which implies a 3x3 symmetric matrix. 40 | 41 | # %% 42 | # **Visualize the dataset** 43 | # 44 | # In the following, we visualize the isotropic diffusion coefficient, that is, the 45 | # average of the :math:`d_{xx}`, :math:`d_{yy}`, and :math:`d_{zz}` tensor components. 46 | # Since it's a three-dimensional dataset, we'll visualize the projections onto the 47 | # three dimensions. 48 | 49 | # the isotropic diffusion coefficient. 50 | # component at index 0 = dxx 51 | # component at index 3 = dyy 52 | # component at index 5 = dzz 53 | isotropic_diffusion = (y[0].components[0] + y[0].components[3] + y[0].components[5]) / 3 54 | 55 | # %% 56 | # In the following, we use certain features of the csdmpy module. 57 | # Please refer to :ref:`generating_csdm_objects` for further details. 58 | 59 | # Create a new csdm object from the isotropic diffusion coefficient array. 60 | new_csdm = cp.as_csdm(isotropic_diffusion, quantity_type="scalar") 61 | 62 | # Add the dimensions from `diff_mri` object to the `new_csdm` object. 63 | for i, dim in enumerate(x): 64 | new_csdm.dimensions[i] = dim 65 | 66 | # %% 67 | # Now, we can plot the projections of the isotropic diffusion coefficients along 68 | # the respective dimensions as 69 | import matplotlib.pyplot as plt 70 | 71 | # projection along the x-axis. 72 | plt.figure(figsize=(5, 4)) 73 | ax = plt.subplot(projection="csdm") 74 | cb = ax.imshow(new_csdm.sum(axis=0), cmap="gray_r", origin="upper", aspect="auto") 75 | plt.colorbar(cb, ax=ax) 76 | plt.tight_layout() 77 | plt.show() 78 | 79 | # %% 80 | 81 | # projection along the y-axis. 82 | plt.figure(figsize=(5, 4)) 83 | ax = plt.subplot(projection="csdm") 84 | cb = ax.imshow(new_csdm.sum(axis=1), cmap="gray_r", origin="upper", aspect="auto") 85 | plt.colorbar(cb, ax=ax) 86 | plt.tight_layout() 87 | plt.show() 88 | 89 | # %% 90 | 91 | # projection along the z-axis. 92 | plt.figure(figsize=(5, 4)) 93 | ax = plt.subplot(projection="csdm") 94 | cb = ax.imshow(new_csdm.sum(axis=2), cmap="gray_r", origin="upper", aspect="auto") 95 | plt.colorbar(cb, ax=ax) 96 | plt.tight_layout() 97 | plt.show() 98 | 99 | # %% 100 | # .. rubric:: Citation 101 | # 102 | # .. [#f1] Diffusion tensor MRI `data `_; 2000. 103 | -------------------------------------------------------------------------------- /examples/vector/README.rst: -------------------------------------------------------------------------------- 1 | Vector datasets 2 | =============== 3 | -------------------------------------------------------------------------------- /examples/vector/plot_0_vector.py: -------------------------------------------------------------------------------- 1 | """ 2 | Vector, 1D{2} dataset 3 | --------------------- 4 | """ 5 | # %% 6 | # The 1D{2} datasets are one-dimensional, :math:`d=1`, with two-component 7 | # dependent variable, :math:`p=2`. Such datasets are more common with the 8 | # weather forecast, such as the wind velocity predicting at a location 9 | # as a function of time. 10 | # 11 | # The following is an example of a simulated 1D vector field dataset. 12 | import matplotlib.pyplot as plt 13 | 14 | import csdmpy as cp 15 | 16 | filename = "https://www.ssnmr.org/sites/default/files/CSDM/vector/1D_vector.csdf" 17 | vector_data = cp.load(filename) 18 | print(vector_data.data_structure) 19 | 20 | # %% 21 | # The tuple of the dimension and dependent variable instances from this example 22 | # are 23 | x = vector_data.dimensions 24 | y = vector_data.dependent_variables 25 | 26 | # %% 27 | # with coordinates 28 | print(x[0].coordinates) 29 | 30 | # %% 31 | # In this example, the components of the dependent variable are 32 | # vectors as seen from the 33 | # :attr:`~csdmpy.DependentVariable.quantity_type` 34 | # attribute of the corresponding dependent variable instance. 35 | print(y[0].quantity_type) 36 | 37 | # %% 38 | # From the value `vector_2`, `vector` indicates a vector dataset, while `2` 39 | # indicates the number of vector components. 40 | 41 | # %% 42 | # **Visualizing the dataset** 43 | 44 | plt.figure(figsize=(5, 3.5)) 45 | cp.plot(vector_data) 46 | plt.tight_layout() 47 | plt.show() 48 | -------------------------------------------------------------------------------- /examples/vector/plot_1_vector.py: -------------------------------------------------------------------------------- 1 | """ 2 | Vector, 2D{2} dataset 3 | ^^^^^^^^^^^^^^^^^^^^^ 4 | """ 5 | # %% 6 | # The 2D{2} datasets are two-dimensional, :math:`d=2`, 7 | # with one two-component dependent variable, :math:`p=2`. 8 | # The following is an example of a simulated electric field vector dataset of a 9 | # dipole as a function of two linearly sampled spatial dimensions. 10 | import csdmpy as cp 11 | 12 | domain = "https://www.ssnmr.org/sites/default/files/CSDM" 13 | filename = f"{domain}/vector/electric_field/electric_field_base64.csdf" 14 | 15 | vector_data = cp.load(filename) 16 | print(vector_data.data_structure) 17 | 18 | # %% 19 | # The tuple of the dimension and dependent variable instances from this example 20 | # are 21 | x = vector_data.dimensions 22 | y = vector_data.dependent_variables 23 | 24 | # %% 25 | # with the respective coordinates (viewed only up to five values), as 26 | print(x[0].coordinates[:5]) 27 | 28 | # %% 29 | print(x[1].coordinates[:5]) 30 | 31 | # %% 32 | # The components of the dependent variable are vector components as seen 33 | # from the :attr:`~csdmpy.DependentVariable.quantity_type` 34 | # attribute of the corresponding dependent variable instance. 35 | print(y[0].quantity_type) 36 | 37 | # %% 38 | # **Visualizing the dataset** 39 | # 40 | # Let's visualize the vector data using the *streamplot* method 41 | # from the matplotlib package. Before we could visualize, however, there 42 | # is an initial processing step. We use the Numpy library for processing. 43 | import numpy as np 44 | 45 | X, Y = np.meshgrid(x[0].coordinates, x[1].coordinates) # (x, y) coordinate pairs 46 | U, V = y[0].components[0], y[0].components[1] # U and V are the components 47 | R = np.sqrt(U**2 + V**2) # The magnitude of the vector 48 | R /= R.min() # Scaled magnitude of the vector 49 | Rlog = np.log10(R) # Scaled magnitude of the vector on a log scale 50 | 51 | # %% 52 | # In the above steps, we calculate the X-Y grid points along with a 53 | # scaled magnitude of the vector dataset. The magnitude is scaled such that the 54 | # minimum value is one. Next, calculate the log of the scaled magnitude to 55 | # visualize the intensity on a logarithmic scale. 56 | 57 | # %% 58 | # And now, the streamplot vector plot 59 | import matplotlib.pyplot as plt 60 | 61 | plt.streamplot( 62 | X.value, Y.value, U, V, density=1, linewidth=Rlog, color=Rlog, cmap="viridis" 63 | ) 64 | 65 | plt.xlim([x[0].coordinates[0].value, x[0].coordinates[-1].value]) 66 | plt.ylim([x[1].coordinates[0].value, x[1].coordinates[-1].value]) 67 | 68 | # Set axes labels and figure title. 69 | plt.xlabel(x[0].axis_label) 70 | plt.ylabel(x[1].axis_label) 71 | plt.title(y[0].name) 72 | 73 | # Set grid lines. 74 | plt.grid(color="gray", linestyle="--", linewidth=0.5) 75 | 76 | plt.tight_layout() 77 | plt.show() 78 | -------------------------------------------------------------------------------- /pyplot/getting_started.py: -------------------------------------------------------------------------------- 1 | import csdmpy as cp 2 | 3 | domain = "https://www.ssnmr.org/sites/default/files/CSDM" 4 | filename = f"{domain}/test/test01.csdf" # replace this with your file's name. 5 | testdata1 = cp.load(filename) 6 | print(testdata1.description) 7 | 8 | # Accessing dimensions and dependent variables of the dataset 9 | x = testdata1.dimensions 10 | y = testdata1.dependent_variables 11 | print(x[0].description) 12 | print(y[0].description) 13 | 14 | # Coordinates along the dimension 15 | print(x[0].coordinates) 16 | print(x[0].coordinates.value) 17 | 18 | # Components of the dependent variable¶ 19 | print(y[0].components) 20 | print(y[0].components.shape) 21 | 22 | import matplotlib.pyplot as plt 23 | 24 | plt.figure(figsize=(5, 3.5)) 25 | plt.plot(x[0].coordinates, y[0].components[0]) 26 | plt.xlabel(x[0].axis_label) 27 | plt.ylabel(y[0].axis_label[0]) 28 | plt.title(y[0].name) 29 | plt.tight_layout() 30 | plt.show() 31 | -------------------------------------------------------------------------------- /pyplot/oneD111_plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | 4 | import csdmpy as cp 5 | 6 | # Create a test 1D{1, 1, 1, 1, 1} dataset. ==================================== 7 | 8 | # Step-1: Create dimension objects. 9 | x = cp.as_dimension(np.arange(40) * 0.5 - 10, unit="µm", label="x") 10 | 11 | # Step-2: Create dependent variable objects. 12 | units = ["cm", "s", "m/s", ""] 13 | y = [ 14 | cp.as_dependent_variable(np.random.rand(40) + 10, unit=units[i], name=f"test-{i}") 15 | for i in range(4) 16 | ] 17 | 18 | # Step-3: Create the CSDM object with Dimension and Dependent variable objects. 19 | csdm = cp.CSDM(dimensions=[x], dependent_variables=y) 20 | 21 | 22 | # Plot ======================================================================== 23 | plt.figure(figsize=(5, 3.5)) 24 | # create the axes with `projection="csdm"` 25 | ax = plt.subplot(projection="csdm") 26 | # use matplotlib plot function with csdm object. 27 | ax.plot(csdm) 28 | plt.title("Data plotted on the same figure") 29 | plt.tight_layout() 30 | plt.show() 31 | 32 | 33 | # The plot on separate axes =================================================== 34 | 35 | # Split the CSDM object into multiple single dependent-variable CSDM objects. 36 | sub_type = csdm.split() 37 | 38 | # create the axes with `projection="csdm"` 39 | _, ax = plt.subplots(2, 2, figsize=(8, 6), subplot_kw={"projection": "csdm"}) 40 | # now use matplotlib plot function with csdm object. 41 | ax[0, 0].plot(sub_type[0]) 42 | ax[0, 1].plot(sub_type[1]) 43 | ax[1, 0].plot(sub_type[2]) 44 | ax[1, 1].plot(sub_type[3]) 45 | plt.title("Data plotted separately") 46 | plt.tight_layout() 47 | plt.show() 48 | -------------------------------------------------------------------------------- /pyplot/oneD_plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | 4 | import csdmpy as cp 5 | 6 | # Create a test 1D{1} dataset. ================================================ 7 | 8 | # Step-1: Create dimension objects. 9 | x = cp.as_dimension(np.arange(10) * 0.1 + 15, unit="s", label="t1") 10 | 11 | # Step-2: Create dependent variable objects. 12 | y = cp.as_dependent_variable(np.random.rand(10), unit="cm", name="test-0") 13 | 14 | # Step-3: Create the CSDM object with Dimension and Dependent variable objects. 15 | csdm = cp.CSDM(dimensions=[x], dependent_variables=[y]) 16 | 17 | 18 | # Plot ======================================================================== 19 | plt.figure(figsize=(5, 3.5)) 20 | # create the axes with `projection="csdm"` 21 | ax = plt.subplot(projection="csdm") 22 | # use matplotlib plot function with csdm object. 23 | ax.plot(csdm) 24 | plt.tight_layout() 25 | plt.show() 26 | 27 | 28 | # Scatter ===================================================================== 29 | plt.figure(figsize=(5, 3.5)) 30 | # create the axes with `projection="csdm"` 31 | ax = plt.subplot(projection="csdm") 32 | # use matplotlib plot function with csdm object. 33 | ax.scatter(csdm, marker="x", color="red") 34 | plt.tight_layout() 35 | plt.show() 36 | -------------------------------------------------------------------------------- /pyplot/twoD111_plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | 4 | import csdmpy as cp 5 | 6 | # Create a test 2D{1} dataset. ================================================ 7 | 8 | # Step-1: Create dimension objects. 9 | x1 = cp.as_dimension(np.arange(10) * 0.1 + 15, unit="s", label="t1") 10 | x2 = cp.as_dimension(np.arange(10) * 12.5, unit="s", label="t2") 11 | 12 | # Step-2: Create dependent variable objects. 13 | y1 = cp.as_dependent_variable(np.diag(np.ones(10)), name="body-diagonal") 14 | y2 = cp.as_dependent_variable(np.diag(np.ones(5), 5), name="off-body-diagonal") 15 | 16 | # Step-3: Create the CSDM object with Dimension and Dependent variable objects. 17 | csdm = cp.CSDM(dimensions=[x1, x2], dependent_variables=[y1, y2]) 18 | 19 | # Plot imshow ================================================================= 20 | plt.figure(figsize=(5, 3.5)) 21 | # create the axes with `projection="csdm"` 22 | ax = plt.subplot(projection="csdm") 23 | # use matplotlib imshow function with csdm object. 24 | ax.imshow(csdm, origin="upper", aspect="auto", cmaps=["Blues", "Reds"], alpha=0.5) 25 | plt.tight_layout() 26 | plt.show() 27 | 28 | 29 | # Plot contourf =============================================================== 30 | plt.figure(figsize=(5, 3.5)) 31 | # create the axes with `projection="csdm"` 32 | ax = plt.subplot(projection="csdm") 33 | # use matplotlib contourf function with csdm object. 34 | ax.contourf(csdm, cmaps=["Blues", "Reds"], alpha=0.5) 35 | plt.tight_layout() 36 | plt.show() 37 | -------------------------------------------------------------------------------- /pyplot/twoD_plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | 4 | import csdmpy as cp 5 | 6 | # Create a test 2D{1} dataset. ================================================ 7 | 8 | # Step-1: Create dimension objects. 9 | x1 = cp.as_dimension(np.arange(10) * 0.1 + 15, unit="s", label="t1") 10 | x2 = cp.as_dimension(np.arange(10) * 12.5, unit="s", label="t2") 11 | 12 | # Step-2: Create dependent variable objects. 13 | y = cp.as_dependent_variable(np.diag(np.ones(10)), name="body-diagonal") 14 | 15 | # Step-3: Create the CSDM object with Dimension and Dependent variable objects. 16 | csdm = cp.CSDM(dimensions=[x1, x2], dependent_variables=[y]) 17 | 18 | # Plot imshow ================================================================= 19 | plt.figure(figsize=(5, 3.5)) 20 | # create the axes with `projection="csdm"` 21 | ax = plt.subplot(projection="csdm") 22 | # use matplotlib imshow function with csdm object. 23 | ax.imshow(csdm, origin="upper", aspect="auto") 24 | plt.tight_layout() 25 | plt.show() 26 | 27 | # Plot contour ================================================================ 28 | plt.figure(figsize=(5, 3.5)) 29 | # create the axes with `projection="csdm"` 30 | ax = plt.subplot(projection="csdm") 31 | # use matplotlib contour function with csdm object. 32 | ax.contour(csdm) 33 | plt.tight_layout() 34 | plt.show() 35 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 88 3 | include = '\.pyi?$' 4 | exclude = ''' 5 | /( 6 | \.git 7 | | \.hg 8 | | \.mypy_cache 9 | | \.tox 10 | | \.venv 11 | | _build 12 | | buck-out 13 | | build 14 | | dist 15 | )/ 16 | ''' 17 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | # required 2 | numpy>=1.20 3 | scipy>=1.10 4 | setuptools>=27.3 5 | numexpr>=2.10.0 6 | 7 | # for units 8 | astropy>=5.1 9 | 10 | # Dependencies of requests package 11 | requests>=2.21.0 12 | 13 | # Additional packages 14 | matplotlib>=3.0 15 | 16 | # development packages 17 | pytest-runner>=5.0 18 | pytest>=4.6.3 19 | pre-commit>=1.16.1 20 | coverage>=4.5.3 21 | pytest-cov 22 | codecov 23 | 24 | # doc build 25 | sphinxjp.themes.basicstrap 26 | sphinx<6.0 27 | sphinx-gallery>=0.6.2 28 | pillow>=7.1.2 # for sphinx-gallery images 29 | sphinx_copybutton>=0.3.0 30 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # required 2 | numpy>=1.20 3 | scipy>=1.10 4 | setuptools>=27.3 5 | numexpr>=2.10.0 6 | 7 | # for units 8 | astropy>=5.1 9 | 10 | # Dependencies of requests package 11 | requests>=2.21.0 12 | 13 | # Additional packages 14 | matplotlib>=3.3.3 15 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [aliases] 2 | test=pytest 3 | 4 | [tool:pytest] 5 | addopts = 6 | --cov='./' 7 | --ignore-glob='docs/auto_*' 8 | --ignore=docs/_build 9 | --ignore=examples 10 | --ignore=tutorials 11 | --ignore=pyplot 12 | --doctest-modules 13 | --doctest-glob='docs/*.rst' 14 | 15 | [coverage:run] 16 | omit = 17 | docs/conf.py 18 | setup.py 19 | csdmpy/helper_functions.py 20 | csdmpy/__main__.py 21 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | 4 | from setuptools import find_packages 5 | from setuptools import setup 6 | 7 | # Load package version number. 8 | with open("csdmpy/__init__.py") as f: 9 | for line in f.readlines(): 10 | if "__version__" in line: 11 | before_keyword, keyword, after_keyword = line.partition("=") 12 | version = after_keyword.strip()[1:-1] 13 | 14 | 15 | # What packages are required for this module to be executed? 16 | required = [ 17 | "numpy>=1.20", 18 | "setuptools>=27.3", 19 | "requests>=2.21.0", 20 | "numexpr>=2.7.0", 21 | ] 22 | extras = {"matplotlib": ["matplotlib>=3.0"]} 23 | setup_requires = ["setuptools>=27.3"] 24 | 25 | here = os.path.abspath(os.path.dirname(__file__)) 26 | 27 | # Import the README and use it as the long-description. 28 | # Note: this will only work if 'README.md' is present in your MANIFEST.in file! 29 | try: 30 | with open(os.path.join(here, "README.md"), encoding="utf-8") as f: 31 | long_description = "\n" + f.read() 32 | except FileNotFoundError: 33 | long_description = "" 34 | 35 | 36 | setup( 37 | name="csdmpy", 38 | version=version, 39 | description="A python module for the core scientific dataset model.", 40 | long_description=long_description, 41 | long_description_content_type="text/markdown", 42 | author="Deepansh Srivastava", 43 | author_email="srivastava.89@osu.edu", 44 | python_requires=">=3.9", 45 | url="https://github.com/DeepanshS/csdmpy/", 46 | packages=find_packages(), 47 | install_requires=required, 48 | setup_requires=setup_requires, 49 | extras_require=extras, 50 | tests_require=["pytest", "pytest-runner"], 51 | include_package_data=True, 52 | license="BSD-3-Clause", 53 | classifiers=[ 54 | # Trove classifiers 55 | # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers 56 | "Intended Audience :: Science/Research", 57 | "Intended Audience :: Developers", 58 | "Operating System :: OS Independent", 59 | "Development Status :: 4 - Beta", 60 | "License :: OSI Approved :: BSD License", 61 | "Programming Language :: Python", 62 | "Programming Language :: Python :: 3", 63 | "Programming Language :: Python :: 3.9", 64 | "Programming Language :: Python :: 3.10", 65 | "Programming Language :: Python :: 3.11", 66 | "Programming Language :: Python :: 3.12", 67 | "Programming Language :: Python :: 3.13", 68 | "Topic :: Scientific/Engineering", 69 | ], 70 | ) 71 | -------------------------------------------------------------------------------- /tests/csdm_new_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | import csdmpy as cp 5 | 6 | 7 | def test_csdm_new(): 8 | a = cp.CSDM(dimensions=[cp.as_dimension(np.arange(10))]) 9 | 10 | error = "Expecting a Dimension object" 11 | with pytest.raises(ValueError, match=f".*{error}.*"): 12 | a.dimensions.append(np.arange(5)) 13 | 14 | with pytest.raises(ValueError, match=f".*{error}.*"): 15 | a.dimensions[0] = np.arange(5) 16 | 17 | error = "Deleting items is not allowed" 18 | with pytest.raises(LookupError, match=f".*{error}.*"): 19 | del a.dimensions[0] 20 | 21 | assert a.dimensions[0] != np.arange(5) 22 | assert a.ndim == 1 23 | assert a.to_dict() == { 24 | "csdm": { 25 | "dimensions": [{"count": 10, "increment": "1.0", "type": "linear"}], 26 | "version": "1.0", 27 | } 28 | } 29 | 30 | 31 | def test_bad_csdm(): 32 | error = "A list of valid Dimension or equivalent dictionary objects" 33 | with pytest.raises(ValueError, match=f".*{error}.*"): 34 | cp.CSDM(dimensions="blah") 35 | 36 | error = "A list of valid DependentVariable or equivalent dictionary objects" 37 | with pytest.raises(ValueError, match=f".*{error}.*"): 38 | cp.CSDM(dependent_variables="blah") 39 | -------------------------------------------------------------------------------- /tests/csdmpy_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | import csdmpy as cp 5 | 6 | 7 | def test_join(): 8 | out = (np.random.rand(50).reshape(10, 5) * 10000).astype(int) 9 | out1 = np.random.rand(50).astype(float).reshape(10, 5) 10 | out2 = np.random.rand(50).astype(complex).reshape(10, 5) 11 | 12 | d_0 = cp.LinearDimension(count=5, increment="1s") 13 | d_1 = cp.LinearDimension(count=10, increment="1m") 14 | units = ["m", "s", "t"] 15 | dv = [ 16 | cp.DependentVariable( 17 | type="internal", 18 | quantity_type="scalar", 19 | unit=unit, 20 | components=item.ravel(), 21 | ) 22 | for unit, item in zip(units, [out, out1, out2]) 23 | ] 24 | 25 | obj = cp.CSDM(dimensions=[d_0, d_1], dependent_variables=[dv[0]]) 26 | obj1 = cp.CSDM(dimensions=[d_0, d_1], dependent_variables=dv[1:]) 27 | obj2 = cp.CSDM(dimensions=[d_0, d_1], dependent_variables=[dv[1]]) 28 | obj3 = cp.CSDM(dimensions=[d_0, d_1], dependent_variables=[dv[2]]) 29 | obj4 = cp.CSDM(dimensions=[d_0, d_1], dependent_variables=dv[::-1]) 30 | obj5 = cp.CSDM(dimensions=[d_1, d_0], dependent_variables=[dv[2]]) 31 | 32 | new = cp.join([obj, obj1, obj2, obj3, obj4]) 33 | 34 | assert len(new.y) == 8 35 | assert list(new.y) == [dv[0], dv[1], dv[2], dv[1], dv[2], dv[2], dv[1], dv[0]] 36 | 37 | error = "Cannot join CSDM objects with different dimensions" 38 | with pytest.raises(Exception, match=f".*{error}.*"): 39 | _ = cp.join([obj, obj5]) 40 | -------------------------------------------------------------------------------- /tests/file_read/fileread_test.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | 3 | import pytest 4 | 5 | import csdmpy as cp 6 | 7 | COMMON_PATH = path.join("tests", "file_read", "test_files") 8 | 9 | 10 | def file_testing(file_, error, error_type): 11 | with pytest.raises(error_type, match=f".*{error}.*"): 12 | cp.load(file_) 13 | 14 | 15 | def test_01(): 16 | file_ = path.join(COMMON_PATH, "1.csdfe") 17 | error = "'CSDM' is not a valid keyword for the CSD model." 18 | file_testing(file_, error, KeyError) 19 | 20 | 21 | def test_02(): 22 | file_ = path.join(COMMON_PATH, "2.csdfe") 23 | error = "Missing a required `version` key from the CSDM object." 24 | file_testing(file_, error, KeyError) 25 | 26 | 27 | def test_03(): 28 | file_ = path.join(COMMON_PATH, "3.csdfe") 29 | error = "Expecting an instance of type `int` for count, got `str`." 30 | file_testing(file_, error, TypeError) 31 | 32 | 33 | def test_04(): 34 | file_ = path.join(COMMON_PATH, "4.csdfe") 35 | error = "The value, `tensor`, is an invalid `quantity_type`" 36 | file_testing(file_, error, ValueError) 37 | 38 | 39 | def test_05(): 40 | file_ = path.join(COMMON_PATH, "5.csdfe") 41 | error = "The quantity_type, 'vector_2', requires exactly 2 component" 42 | file_testing(file_, error, Exception) 43 | 44 | 45 | def test_06(): 46 | file_ = path.join(COMMON_PATH, "6.csdfe") 47 | error = "The value, `float16`, is an invalid `numeric_type`" 48 | file_testing(file_, error, ValueError) 49 | 50 | 51 | def test_07(): 52 | file_ = path.join(COMMON_PATH, "7.csdfe") 53 | error = "Missing a required `coordinates` key from the MonotonicDimension" 54 | file_testing(file_, error, KeyError) 55 | 56 | 57 | def test_08(): 58 | file_ = path.join(COMMON_PATH, "8.csdfe") 59 | error = "A list of string labels are required, found int" 60 | file_testing(file_, error, ValueError) 61 | 62 | 63 | def test_09(): 64 | file_ = path.join(COMMON_PATH, "9.csdfe") 65 | error = "Missing a required `quantity_type` key from the DependentVariable" 66 | file_testing(file_, error, KeyError) 67 | 68 | 69 | def test_10(): 70 | file_ = path.join(COMMON_PATH, "10.csdfe") 71 | error = "Missing a required `numeric_type` key from the DependentVariable" 72 | file_testing(file_, error, KeyError) 73 | 74 | 75 | def test_11(): 76 | file_ = path.join(COMMON_PATH, "11.csdfe") 77 | error = "The `encoding` key is invalid for DependentVariable objects" 78 | file_testing(file_, error, KeyError) 79 | 80 | 81 | def test_12(): 82 | file_ = path.join(COMMON_PATH, "12.csdfe") 83 | error = "Missing a required 'type' key from the Dimension object." 84 | file_testing(file_, error, KeyError) 85 | 86 | 87 | def test_13(): 88 | file_ = path.join(COMMON_PATH, "13.csdfe") 89 | error = "Missing a required `count` key from the LinearDimension." 90 | file_testing(file_, error, KeyError) 91 | 92 | 93 | def test_14(): 94 | file_ = path.join(COMMON_PATH, "14.csdfe") 95 | error = "Missing a required `type` key from the DependentVariable." 96 | file_testing(file_, error, KeyError) 97 | 98 | 99 | def test_15(): 100 | file_ = path.join(COMMON_PATH, "15.csdfe") 101 | error = "The value, 'blah', is invalid for the `type` attribute" 102 | file_testing(file_, error, ValueError) 103 | 104 | 105 | def test_16(): 106 | file_ = path.join(COMMON_PATH, "16.csdfe") 107 | error = "Missing a required `labels` key from the LabeledDimension object." 108 | file_testing(file_, error, KeyError) 109 | -------------------------------------------------------------------------------- /tests/file_read/test_files/1.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "CSDM": { 3 | "version": "1.0", 4 | "read_only": true, 5 | "timestamp": "2016-03-12T16:41:00Z", 6 | "description": "An IR spectrum of caffeine.", 7 | "dimensions": [ 8 | { 9 | "type": "linear", 10 | "count": 1842, 11 | "increment": "1.930548614883216 cm^-1", 12 | "coordinates_offset": "449.41 cm^-1", 13 | "quantity_name": "wavenumber", 14 | "reciprocal": { 15 | "quantity_name": "length" 16 | } 17 | } 18 | ], 19 | "dependent_variables": [ 20 | { 21 | "name": "Caffeine", 22 | "type": "internal", 23 | "encoding": "base64", 24 | "numeric_type": "float32", 25 | "quantity_type": "scalar", 26 | "component_labels": [ 27 | "Transmittance" 28 | ], 29 | "components": [] 30 | } 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/file_read/test_files/10.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "read_only": true, 5 | "timestamp": "2016-03-12T16:41:00Z", 6 | "description": "An RBG image of a raccoon face.", 7 | "dependent_variables": [ 8 | { 9 | "type": "external", 10 | "components_url": "https://www.grandinetti.org/resources/CSDM/raccoon_raw.dat", 11 | "quantity_type": "pixel_3", 12 | "component_labels": [ 13 | "red", 14 | "green", 15 | "blue" 16 | ], 17 | "name": "raccoon face" 18 | } 19 | ], 20 | "dimensions": [ 21 | { 22 | "type": "linear", 23 | "count": 1024, 24 | "increment": "1.0", 25 | "label" : "horizontal index" 26 | }, 27 | { 28 | "type": "linear", 29 | "count": 768, 30 | "increment": "1.0", 31 | "label" : "vertical index" 32 | } 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/file_read/test_files/11.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "read_only": true, 5 | "timestamp": "2016-03-12T16:41:00Z", 6 | "description": "A Electron Paramagnetic Resonance simulated dataset.", 7 | "dependent_variables": [ 8 | { 9 | "type": "external", 10 | "components_url": "file:./xyinc2_raw_Vanadyl in Amanita muscaria.dat", 11 | "component_labels": ["Intensity Derivative"], 12 | "name": "Amanita.muscaria", 13 | "encoding": "raw", 14 | "numeric_type": "float32", 15 | "quantity_type": "scalar" 16 | } 17 | ], 18 | "dimensions": [ 19 | { 20 | "type": "linear", 21 | "count": 298, 22 | "quantity_name": "magnetic flux density", 23 | "coordinates_offset": "2750.0 G", 24 | "increment": "4.0 G" 25 | } 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/file_read/test_files/12.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "read_only": true, 5 | "timestamp": "2016-03-12T16:41:00Z", 6 | "description": "A UV-vis spectra of benzene vapours.", 7 | "dimensions": [ 8 | { 9 | "count": 4001, 10 | "increment": "0.01 nm", 11 | "coordinates_offset": "230.0 nm", 12 | "quantity_name": "length", 13 | "label": "wavelength", 14 | "reciprocal": { 15 | "quantity_name": "wavenumber" 16 | } 17 | } 18 | ], 19 | "dependent_variables": [ 20 | { 21 | "name": "Vapour of Benzene", 22 | "type": "internal", 23 | "encoding": "base64", 24 | "numeric_type": "float32", 25 | "component_labels": [ 26 | "Absorbance" 27 | ], 28 | "components": [] 29 | } 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/file_read/test_files/13.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "read_only": true, 5 | "timestamp": "2016-03-12T16:41:00Z", 6 | "description": "A UV-vis spectra of benzene vapours.", 7 | "dimensions": [ 8 | { 9 | "type": "linear", 10 | "increment": "0.01 nm", 11 | "coordinates_offset": "230.0 nm", 12 | "quantity_name": "length", 13 | "label": "wavelength", 14 | "reciprocal": { 15 | "quantity_name": "wavenumber" 16 | } 17 | } 18 | ], 19 | "dependent_variables": [ 20 | { 21 | "name": "Vapour of Benzene", 22 | "type": "internal", 23 | "encoding": "none", 24 | "numeric_type": "float32", 25 | "component_labels": [ 26 | "Absorbance" 27 | ], 28 | "components": [] 29 | } 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/file_read/test_files/14.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "read_only": true, 5 | "timestamp": "2016-03-12T16:41:00Z", 6 | "description": "A UV-vis spectra of benzene vapours.", 7 | "dimensions": [ 8 | { 9 | "type": "linear", 10 | "count": 4001, 11 | "increment": "0.01 nm", 12 | "coordinates_offset": "230.0 nm", 13 | "quantity_name": "length", 14 | "label": "wavelength", 15 | "reciprocal": { 16 | "quantity_name": "wavenumber" 17 | } 18 | } 19 | ], 20 | "dependent_variables": [ 21 | { 22 | "name": "Vapour of Benzene", 23 | "encoding": "base64", 24 | "numeric_type": "float32", 25 | "component_labels": [ 26 | "Absorbance" 27 | ], 28 | "components": [] 29 | } 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/file_read/test_files/15.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "read_only": true, 5 | "timestamp": "2016-03-12T16:41:00Z", 6 | "description": "A UV-vis spectra of benzene vapours.", 7 | "dimensions": [ 8 | { 9 | "type": "blah", 10 | "count": 4001, 11 | "increment": "0.01 nm", 12 | "coordinates_offset": "230.0 nm", 13 | "quantity_name": "length", 14 | "label": "wavelength", 15 | "reciprocal": { 16 | "quantity_name": "wavenumber" 17 | } 18 | } 19 | ], 20 | "dependent_variables": [ 21 | { 22 | "name": "Vapour of Benzene", 23 | "encoding": "base64", 24 | "numeric_type": "float32", 25 | "component_labels": [ 26 | "Absorbance" 27 | ], 28 | "components": [] 29 | } 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/file_read/test_files/16.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "read_only": true, 5 | "timestamp": "2016-03-12T16:41:00Z", 6 | "description": "A UV-vis spectra of benzene vapours.", 7 | "dimensions": [ 8 | { 9 | "type": "labeled", 10 | "quantity_name": "length" 11 | } 12 | ], 13 | "dependent_variables": [ 14 | { 15 | "name": "Vapour of Benzene", 16 | "encoding": "base64", 17 | "numeric_type": "float32", 18 | "component_labels": [ 19 | "Absorbance" 20 | ], 21 | "components": [] 22 | } 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/file_read/test_files/2.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "read_only": true, 4 | "timestamp": "2016-03-12T16:41:00Z", 5 | "description": "An IR spectrum of caffeine.", 6 | "dimensions": [ 7 | { 8 | "type": "linear", 9 | "count": 1842, 10 | "increment": "1.930548614883216 cm^-1", 11 | "coordinates_offset": "449.41 cm^-1", 12 | "quantity_name": "wavenumber", 13 | "reciprocal": { 14 | "quantity_name": "length" 15 | } 16 | } 17 | ], 18 | "dependent_variables": [ 19 | { 20 | "name": "Caffeine", 21 | "type": "internal", 22 | "encoding": "base64", 23 | "numeric_type": "float32", 24 | "quantity_type": "scalar", 25 | "component_labels": [ 26 | "Transmittance" 27 | ], 28 | "components": [] 29 | } 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/file_read/test_files/3.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "read_only": true, 5 | "timestamp": "2016-03-12T16:41:00Z", 6 | "description": "An IR spectrum of caffeine.", 7 | "dimensions": [ 8 | { 9 | "type": "linear", 10 | "count": "1842", 11 | "increment": "1.930548614883216 cm^-1", 12 | "coordinates_offset": "449.41 cm^-1", 13 | "quantity_name": "wavenumber", 14 | "reciprocal": { 15 | "quantity_name": "length" 16 | } 17 | } 18 | ], 19 | "dependent_variables": [ 20 | { 21 | "name": "Caffeine", 22 | "type": "internal", 23 | "encoding": "base64", 24 | "numeric_type": "float32", 25 | "quantity_type": "scalar", 26 | "component_labels": [ 27 | "Transmittance" 28 | ], 29 | "components": [] 30 | } 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/file_read/test_files/4.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "read_only": true, 5 | "timestamp": "2016-03-12T16:41:00Z", 6 | "description": "An IR spectrum of caffeine.", 7 | "dimensions": [ 8 | { 9 | "type": "linear", 10 | "count": 1842, 11 | "increment": "1.930548614883216 cm^-1", 12 | "coordinates_offset": "449.41 cm^-1", 13 | "quantity_name": "wavenumber", 14 | "reciprocal": { 15 | "quantity_name": "length" 16 | } 17 | } 18 | ], 19 | "dependent_variables": [ 20 | { 21 | "name": "Caffeine", 22 | "type": "internal", 23 | "encoding": "base64", 24 | "numeric_type": "float32", 25 | "quantity_type": "tensor", 26 | "component_labels": [ 27 | "Transmittance" 28 | ], 29 | "components": [] 30 | } 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/file_read/test_files/5.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "timestamp": "2019-03-21T12:41:00Z", 5 | "description": "A simulated sine curve.", 6 | "dependent_variables": [ 7 | { 8 | "type": "internal", 9 | "description": "A response dependent variable.", 10 | "numeric_type": "float32", 11 | "quantity_type": "vector_2", 12 | "components": [ 13 | [ 14 | 0.00000000e+00, 15 | 5.87785252e-01, 16 | 9.51056516e-01, 17 | 9.51056516e-01, 18 | 5.87785252e-01, 19 | 1.22464680e-16, 20 | -5.87785252e-01, 21 | -9.51056516e-01, 22 | -9.51056516e-01, 23 | -5.87785252e-01 24 | ] 25 | ] 26 | } 27 | ], 28 | "dimensions": [ 29 | { 30 | "type": "linear", 31 | "description": "A temporal dimension.", 32 | "count": 10, 33 | "increment": "0.1 s", 34 | "quantity_name": "time" 35 | } 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/file_read/test_files/6.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "timestamp": "2019-03-21T12:41:00Z", 5 | "description": "A simulated sine curve.", 6 | "dependent_variables": [ 7 | { 8 | "type": "internal", 9 | "description": "A response dependent variable.", 10 | "numeric_type": "float16", 11 | "quantity_type": "scalar", 12 | "components": [ 13 | [ 14 | 0.00000000e+00, 15 | 5.87785252e-01, 16 | 9.51056516e-01, 17 | 9.51056516e-01, 18 | 5.87785252e-01, 19 | 1.22464680e-16, 20 | -5.87785252e-01, 21 | -9.51056516e-01, 22 | -9.51056516e-01, 23 | -5.87785252e-01 24 | ] 25 | ] 26 | } 27 | ], 28 | "dimensions": [ 29 | { 30 | "type": "linear", 31 | "description": "A temporal dimension.", 32 | "count": 10, 33 | "increment": "0.1 s", 34 | "quantity_name": "time" 35 | } 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/file_read/test_files/7.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "timestamp": "2019-03-21T12:41:00Z", 5 | "description": "A simulated sine curve.", 6 | "dependent_variables": [ 7 | { 8 | "type": "internal", 9 | "description": "A response dependent variable.", 10 | "numeric_type": "float32", 11 | "quantity_type": "scalar", 12 | "components": [ 13 | [ 14 | 0.00000000e+00, 15 | 5.87785252e-01, 16 | 9.51056516e-01, 17 | 9.51056516e-01, 18 | 5.87785252e-01, 19 | 1.22464680e-16, 20 | -5.87785252e-01, 21 | -9.51056516e-01, 22 | -9.51056516e-01, 23 | -5.87785252e-01 24 | ] 25 | ] 26 | } 27 | ], 28 | "dimensions": [ 29 | { 30 | "type": "monotonic", 31 | "description": "A temporal dimension.", 32 | "count": 10, 33 | "increment": "0.1 s", 34 | "quantity_name": "time" 35 | } 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/file_read/test_files/8.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "version": "1.0", 4 | "timestamp": "2019-03-21T12:41:00Z", 5 | "description": "A simulated sine curve.", 6 | "dependent_variables": [ 7 | { 8 | "type": "internal", 9 | "description": "A response dependent variable.", 10 | "numeric_type": "float32", 11 | "quantity_type": "scalar", 12 | "components": [ 13 | [ 14 | 0.00000000e+00, 15 | 5.87785252e-01, 16 | 9.51056516e-01, 17 | 9.51056516e-01, 18 | 5.87785252e-01, 19 | 1.22464680e-16, 20 | -5.87785252e-01, 21 | -9.51056516e-01, 22 | -9.51056516e-01, 23 | -5.87785252e-01 24 | ] 25 | ] 26 | } 27 | ], 28 | "dimensions": [ 29 | { 30 | "type": "labeled", 31 | "description": "A dimension.", 32 | "labels": ["0", "1", 2, "3", "4", "5", "6", "7", "8", "9"] 33 | } 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/file_read/test_files/9.csdfe: -------------------------------------------------------------------------------- 1 | { 2 | "csdm": { 3 | "timestamp": "2019-05-21T13:43:00Z", 4 | "description": "Global Mean Sea Level (GMSL) rise from the late 19th to the Early 21st Century.", 5 | "dimensions": [ 6 | { 7 | "type": "linear", 8 | "increment": "0.08333333333 yr", 9 | "label": "Time", 10 | "coordinates_offset": "1880.0416666667 yr", 11 | "reciprocal": { 12 | "quantity_name": "frequency" 13 | }, 14 | "count": 1608, 15 | "quantity_name": "time" 16 | } 17 | ], 18 | "dependent_variables": [ 19 | { 20 | "type": "internal", 21 | "component_labels": [ 22 | "Global Mean Sea Level" 23 | ], 24 | "name": "Global Mean Sea Level", 25 | "unit": " mm", 26 | "components": [], 27 | "quantity_name": "length" 28 | } 29 | ], 30 | "read_only": true, 31 | "version": "1.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/import_test.py: -------------------------------------------------------------------------------- 1 | from os.path import split 2 | 3 | import numpy as np 4 | import pytest 5 | 6 | import csdmpy as cp 7 | 8 | 9 | def test_load_files(): 10 | assert split(cp.tests.test01)[1] == "test01.csdf" 11 | assert split(cp.tests.test02)[1] == "test02.csdf" 12 | 13 | 14 | def test_00(): 15 | error = "Missing the value for the required `filename` attribute." 16 | with pytest.raises(Exception, match=f".*{error}.*"): 17 | cp.load() 18 | 19 | 20 | def test_01(): 21 | dataset = cp.load(cp.tests.test01) 22 | 23 | assert dataset.y[0].type == "internal" 24 | 25 | # encoding is always set to 'base64' after import 26 | assert dataset.y[0].encoding == "base64" 27 | assert dataset.y[0].numeric_type == "float32" 28 | assert dataset.y[0].components.dtype == np.float32 29 | assert dataset.description == "A simulated sine curve." 30 | assert len(dataset.y) == 1 31 | assert len(dataset.dimensions) == 1 32 | assert dataset.dimensions[0].type == "linear" 33 | assert str(dataset.dimensions[0].increment) == "0.1 s" 34 | assert str(dataset.dimensions[0].origin_offset) == "0.0 s" 35 | assert dataset.dimensions[0].count == 10 36 | assert dataset.dimensions[0].quantity_name == "time" 37 | assert np.all(dataset.dimensions[0].coordinates.value == np.arange(10) * 0.1) 38 | 39 | 40 | def test_02(): 41 | dataset = cp.load(cp.tests.test02) 42 | 43 | assert dataset.y[0].type == "internal" 44 | 45 | # encoding is always set to 'base64' after import 46 | assert dataset.y[0].encoding == "base64" 47 | assert dataset.y[0].numeric_type == "float64" 48 | assert dataset.y[0].components.dtype == np.float64 49 | assert dataset.description == "Base64 encoding test" 50 | assert len(dataset.y) == 4 51 | assert len(dataset.dimensions) == 1 52 | assert dataset.dimensions[0].type == "monotonic" 53 | assert str(dataset.dimensions[0].origin_offset) == "0.0 cm" 54 | assert dataset.dimensions[0].count == 10 55 | assert dataset.dimensions[0].quantity_name == "length" 56 | assert dataset.size == dataset.y[0].components[0].size 57 | 58 | 59 | # def test03(): 60 | # dataset1 = cp.load(cp.tests.test03, sort_fft_order=False) 61 | # dataset2 = cp.load(cp.tests.test03, sort_fft_order=True) 62 | 63 | # dat1 = dataset1.y[0].components[0] 64 | # dat2 = dataset2.y[0].components[0] 65 | # assert np.all(sp.fft.fftshift(dat1) == dat2) 66 | 67 | 68 | def test04(): 69 | data1 = cp.load(cp.tests.test04) 70 | data2 = data1.copy() 71 | assert data1.data_structure == data2.data_structure 72 | -------------------------------------------------------------------------------- /tests/nmr_freq_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import csdmpy as cp 4 | 5 | 6 | def setup_reference_offset(offset): 7 | a = cp.LinearDimension( 8 | count=6, increment="1", coordinates_offset=f"{offset}", complex_fft=True 9 | ) 10 | array = np.asarray([-3, -2, -1, 0, 1, 2]) + offset 11 | assert np.allclose(a.coordinates, array) 12 | assert a.get_nmr_reference_offset() == offset 13 | 14 | b = cp.LinearDimension(count=6, increment="1", coordinates_offset=f"{-3 + offset}") 15 | assert np.allclose(b.coordinates, array) 16 | assert b.get_nmr_reference_offset() == offset 17 | 18 | b = cp.LinearDimension(count=6, increment="-1", coordinates_offset=f"{2 + offset}") 19 | assert np.allclose(b.coordinates, np.asarray([2, 1, 0, -1, -2, -3]) + offset) 20 | assert b.get_nmr_reference_offset() == offset 21 | 22 | b = cp.LinearDimension(count=5, increment="-1", coordinates_offset=f"{2 + offset}") 23 | assert np.allclose(b.coordinates, np.asarray([2, 1, 0, -1, -2]) + offset) 24 | assert b.get_nmr_reference_offset() == offset 25 | 26 | b = cp.LinearDimension(count=5, increment="1", coordinates_offset=f"{-2 + offset}") 27 | assert np.allclose(b.coordinates, np.asarray([-2, -1, 0, 1, 2]) + offset) 28 | assert b.get_nmr_reference_offset() == offset 29 | 30 | 31 | def test_00(): 32 | setup_reference_offset(0) 33 | setup_reference_offset(10) 34 | setup_reference_offset(-12.12) 35 | setup_reference_offset(61.12) 36 | -------------------------------------------------------------------------------- /tests/numpy_wrapper/apodization_test.py: -------------------------------------------------------------------------------- 1 | """Apodization module""" 2 | import numpy as np 3 | 4 | import csdmpy as cp 5 | 6 | data = np.ones(5 * 10).reshape(10, 5) 7 | dim1 = {"type": "linear", "count": 5, "increment": "1 s"} 8 | dim2 = {"type": "linear", "count": 10, "increment": "1 m"} 9 | dv = {"type": "internal", "components": [data.ravel()], "quantity_type": "scalar"} 10 | obj = cp.CSDM(dimensions=[dim1, dim2], dependent_variables=[dv]) 11 | 12 | 13 | def test_sin(): 14 | """sin test""" 15 | test_cp = cp.apodize.sin(obj, "(2*3.1415*0.1) s^-1", dimension=(0)) 16 | test_np = np.sin(2 * 3.1415 * 0.1 * np.arange(5)) * data[0, :] 17 | assert np.allclose(test_np, test_cp.y[0].components[0][0, :]) 18 | 19 | test_cp = cp.apodize.sin(obj, "(2*3.1415*0.1) m^-1", dimension=1) 20 | test_np = np.sin(2 * 3.1415 * 0.1 * np.arange(10)) * data[:, 0] 21 | assert np.allclose(test_np, test_cp.y[0].components[0][:, 0]) 22 | 23 | 24 | def test_cos(): 25 | """cos test""" 26 | test_cp = cp.apodize.cos(obj, "(2*3.1415*0.1) s^-1", dimension=(0)) 27 | test_np = np.cos(2 * 3.1415 * 0.1 * np.arange(5)) * data[0, :] 28 | assert np.allclose(test_np, test_cp.y[0].components[0][0, :]) 29 | 30 | test_cp = cp.apodize.cos(obj, "(2*3.1415*0.1) m^-1", dimension=1) 31 | test_np = np.cos(2 * 3.1415 * 0.1 * np.arange(10)) * data[:, 0] 32 | assert np.allclose(test_np, test_cp.y[0].components[0][:, 0]) 33 | 34 | 35 | def test_tan(): 36 | """tan test""" 37 | test_cp = cp.apodize.tan(obj, "(2*3.1415*0.1) s^-1", dimension=(0)) 38 | test_np = np.tan(2 * 3.1415 * 0.1 * np.arange(5)) * data[0, :] 39 | assert np.allclose(test_np, test_cp.y[0].components[0][0, :]) 40 | 41 | test_cp = cp.apodize.tan(obj, "(2*3.1415*0.1) m^-1", dimension=1) 42 | test_np = np.tan(2 * 3.1415 * 0.1 * np.arange(10)) * data[:, 0] 43 | assert np.allclose(test_np, test_cp.y[0].components[0][:, 0]) 44 | 45 | 46 | def test_arcsin(): 47 | """arc sin test""" 48 | test_cp = cp.apodize.arcsin(obj, "(1/(2*3.1415*10)) s^-1", dimension=(0)) 49 | test_np = np.arcsin(1 / (2 * 3.1415 * 10) * np.arange(5)) * data[0, :] 50 | assert np.allclose(test_np, test_cp.y[0].components[0][0, :]) 51 | 52 | test_cp = cp.apodize.arcsin(obj, "(1/(2*3.1415*10)) m^-1", dimension=1) 53 | test_np = np.arcsin(1 / (2 * 3.1415 * 10) * np.arange(10)) * data[:, 0] 54 | assert np.allclose(test_np, test_cp.y[0].components[0][:, 0]) 55 | 56 | 57 | def test_arccos(): 58 | """arc cos test""" 59 | test_cp = cp.apodize.arccos(obj, "(1/(2*3.1415*10)) s^-1", dimension=(0)) 60 | test_np = np.arccos(1 / (2 * 3.1415 * 10) * np.arange(5)) * data[0, :] 61 | assert np.allclose(test_np, test_cp.y[0].components[0][0, :]) 62 | 63 | test_cp = cp.apodize.arccos(obj, "(1/(2*3.1415*10)) m^-1", dimension=1) 64 | test_np = np.arccos(1 / (2 * 3.1415 * 10) * np.arange(10)) * data[:, 0] 65 | assert np.allclose(test_np, test_cp.y[0].components[0][:, 0]) 66 | 67 | 68 | def test_arctan(): 69 | """arc tan test""" 70 | test_cp = cp.apodize.arctan(obj, "(2*3.1415*10) s^-1", dimension=(0)) 71 | test_np = np.arctan(2 * 3.1415 * 10 * np.arange(5)) * data[0, :] 72 | assert np.allclose(test_np, test_cp.y[0].components[0][0, :]) 73 | 74 | test_cp = cp.apodize.arctan(obj, "(2*3.1415*10) m^-1", dimension=1) 75 | test_np = np.arctan(2 * 3.1415 * 10 * np.arange(10)) * data[:, 0] 76 | assert np.allclose(test_np, test_cp.y[0].components[0][:, 0]) 77 | 78 | 79 | def test_exp(): 80 | """exp test""" 81 | test_cp = cp.apodize.exp(obj, "-0.1 s^-1", dimension=(0)) 82 | test_np = np.exp(-0.1 * np.arange(5)) * data[0, :] 83 | assert np.allclose(test_np, test_cp.y[0].components[0][0, :]) 84 | 85 | test_cp = cp.apodize.exp(obj, "-0.1 m^-1", dimension=1) 86 | test_np = np.exp(-0.1 * np.arange(10)) * data[:, 0] 87 | assert np.allclose(test_np, test_cp.y[0].components[0][:, 0]) 88 | -------------------------------------------------------------------------------- /tests/numpy_wrapper/change_shape_test.py: -------------------------------------------------------------------------------- 1 | """Test for the csdm object""" 2 | from os import remove 3 | 4 | import numpy as np 5 | 6 | import csdmpy as cp 7 | 8 | data = np.random.rand(4, 3, 2) 9 | dim1 = cp.Dimension(type="linear", count=2, increment="1") 10 | dim2 = cp.Dimension(type="linear", count=3, increment="1") 11 | dim3 = cp.Dimension(type="linear", count=4, increment="1") 12 | dv = {"type": "internal", "components": [data.ravel()], "quantity_type": "scalar"} 13 | obj_1 = cp.CSDM(dimensions=[dim1, dim2, dim3], dependent_variables=[dv]) 14 | 15 | # data1 = np.random.rand(15 * 5 * 10).reshape(15, 5, 10) * 1e3 + 10 16 | # dv = {"type": "internal", "components": [data1.ravel()], "quantity_type": "scalar"} 17 | # obj_2 = cp.CSDM(dimensions=[dim1, dim2, dim3], dependent_variables=[dv]) 18 | 19 | # --------------------------------------------------------------- 20 | # test for ufunc that apply to dimensionless dependent variables. 21 | # __ufunc_list_dimensionless_unit__ 22 | 23 | 24 | def test_00(): 25 | """shape test""" 26 | test1 = obj_1.T 27 | out = obj_1.y[0].components[0] 28 | assert np.allclose(test1.y[0].components[0], out.T) 29 | test1.save("test_abc.csdf") 30 | 31 | test2 = cp.load("test_abc.csdf") 32 | assert test1 == test2 33 | remove("test_abc.csdf") 34 | 35 | 36 | def test_index_assignment(): 37 | test_1 = obj_1.copy() 38 | test_1[:, :, 0] = 0 39 | assert np.allclose(test_1.y[0].components[0, 0, :, :], 0) 40 | 41 | 42 | def test_indexing(): 43 | test_1 = obj_1[:, :, 0] 44 | assert len(test_1.x) == 2 45 | assert test_1.x[0] == dim1 46 | assert test_1.x[1] == dim2 47 | 48 | test_1 = obj_1[:, -1, :] 49 | assert len(test_1.x) == 2 50 | assert test_1.x[0] == dim1 51 | assert test_1.x[1] == dim3 52 | 53 | test_1 = obj_1[0, :, :] 54 | assert len(test_1.x) == 2 55 | assert test_1.x[0] == dim2 56 | assert test_1.x[1] == dim3 57 | 58 | test_1 = obj_1[0, 0, :] 59 | assert len(test_1.x) == 1 60 | assert test_1.x[0] == dim3 61 | 62 | test_1 = obj_1[:, 0, 0] 63 | assert len(test_1.x) == 1 64 | assert test_1.x[0] == dim1 65 | 66 | test_1 = obj_1[0, :, 0] 67 | assert len(test_1.x) == 1 68 | assert test_1.x[0] == dim2 69 | 70 | 71 | def test_transpose(): 72 | test_1 = np.transpose(obj_1) 73 | assert test_1.T == obj_1 74 | assert test_1.shape == (4, 3, 2) 75 | 76 | test_1 = np.transpose(obj_1, (1, 0, 2)) 77 | np.testing.assert_allclose( 78 | test_1.y[0].components[0], np.transpose(obj_1.y[0].components[0], (1, 2, 0)) 79 | ) 80 | assert test_1.shape == (3, 2, 4) 81 | 82 | test_1 = np.transpose(obj_1, axes=(1, 2, 0)) 83 | np.testing.assert_allclose( 84 | test_1.y[0].components[0], np.transpose(obj_1.y[0].components[0], (1, 0, 2)) 85 | ) 86 | assert test_1.shape == (3, 4, 2) 87 | -------------------------------------------------------------------------------- /tests/numpy_wrapper/dimension_reduction_test.py: -------------------------------------------------------------------------------- 1 | """Test for the csdm object 2 | 1) sum, mean, var, std, prod. 3 | """ 4 | import numpy as np 5 | import pytest 6 | 7 | import csdmpy as cp 8 | 9 | data = np.random.rand(50 * 15).reshape(15, 5, 10) 10 | dim = [ 11 | {"type": "linear", "count": 10, "increment": "1"}, 12 | {"type": "linear", "count": 5, "increment": "1"}, 13 | {"type": "linear", "count": 15, "increment": "1"}, 14 | ] 15 | dv = {"type": "internal", "components": [data.ravel()], "quantity_type": "scalar"} 16 | test_1 = cp.CSDM(dimensions=dim, dependent_variables=[dv]) 17 | 18 | 19 | def test_exceptions(): 20 | error = r"Index/Indices are expected as integer" 21 | with pytest.raises(TypeError, match=error): 22 | test_1.sum(axis=0.2) 23 | 24 | error = r"Index/Indices are expected as integer" 25 | with pytest.raises(TypeError, match=error): 26 | test_1.sum(axis=(1, 0.2)) 27 | 28 | error = r"The `index` 4 cannot be greater than the total number of dimensions - 1" 29 | with pytest.raises(IndexError, match=error): 30 | test_1.sum(axis=4) 31 | 32 | 33 | def test_sum_cumsum(): 34 | dimensions = [0, 1, 2] 35 | i = [[1, 2], [0, 2], [0, 1]] 36 | for np_fn in [np.sum, np.cumsum]: 37 | assert np.allclose( 38 | np_fn(a=test_1, axis=0).y[0].components, np_fn(data, axis=-1) 39 | ) 40 | assert np.allclose(np_fn(test_1, 0).y[0].components, np_fn(data, axis=-1)) 41 | assert np.allclose(np_fn(test_1, 1).y[0].components, np_fn(data, axis=-2)) 42 | for index, dimension in zip(i, dimensions): 43 | res = np_fn(test_1, axis=dimension) 44 | components = res.y[0].components[0] 45 | assert np.allclose(components, np_fn(data, axis=-dimension - 1)) 46 | assert res.dimensions[0] == test_1.dimensions[index[0]] 47 | assert res.dimensions[1] == test_1.dimensions[index[1]] 48 | 49 | dimensions = [(0, 1), [0, 2], (1, 2)] 50 | i = [2, 1, 0] 51 | for index, dimension in zip(i, dimensions): 52 | res = np.sum(test_1, axis=dimension) 53 | components = res.y[0].components[0] 54 | dim_ = tuple(-i - 1 for i in dimension) 55 | assert np.allclose(components, np.sum(data, axis=dim_)) 56 | assert res.dimensions[0] == test_1.dimensions[index] 57 | 58 | res = test_1.sum() 59 | assert np.allclose(res, data.sum()) 60 | 61 | assert np.allclose(test_1.sum(-1).y[0].components, data.sum(axis=0)) 62 | 63 | 64 | def test_reduction_multi_axis(): 65 | cp_fn = ["prod", "sum", "mean", "var", "std"] 66 | np_fn = [np.prod, np.sum, np.mean, np.var, np.std] 67 | for fn_np, fn_cp in zip(np_fn, cp_fn): 68 | dimensions = [0, 1, 2] 69 | i = [[1, 2], [0, 2], [0, 1]] 70 | for index, dimension in zip(i, dimensions): 71 | res = fn_np(test_1, axis=dimension) 72 | components = res.y[0].components[0] 73 | print(dimension) 74 | assert np.allclose(components, fn_np(data, axis=-dimension - 1)) 75 | assert res.dimensions[0] == test_1.dimensions[index[0]] 76 | assert res.dimensions[1] == test_1.dimensions[index[1]] 77 | 78 | dimensions = [(0, 1), [0, 2], (1, 2)] 79 | i = [2, 1, 0] 80 | for index, dimension in zip(i, dimensions): 81 | res = test_1.__getattribute__(fn_cp)(axis=dimension) 82 | components = res.y[0].components[0] 83 | dim_ = tuple(-i - 1 for i in dimension) 84 | assert np.allclose(components, fn_np(data, axis=dim_)) 85 | assert res.dimensions[0] == test_1.dimensions[index] 86 | 87 | res = test_1.__getattribute__(fn_cp)() 88 | assert np.allclose(res, fn_np(data)) 89 | 90 | 91 | def test_reduction_single_axis(): 92 | dimensions = [0, 1, 2] 93 | i = [[1, 2], [0, 2], [0, 1]] 94 | cp_fn = ["cumprod", "cumsum", "argmin", "argmax"] 95 | np_fn = [np.cumprod, np.cumsum, np.argmin, np.argmax] 96 | for fn_np, fn_cp in zip(np_fn, cp_fn): 97 | for index, dimension in zip(i, dimensions): 98 | res = fn_np(test_1, axis=dimension) 99 | components = res.y[0].components[0] 100 | assert np.allclose(components, fn_np(data, axis=-dimension - 1)) 101 | assert res.dimensions[0] == test_1.dimensions[index[0]] 102 | assert res.dimensions[1] == test_1.dimensions[index[1]] 103 | 104 | res = test_1.__getattribute__(fn_cp)() 105 | assert np.allclose(res, fn_np(data)) 106 | -------------------------------------------------------------------------------- /tests/numpy_wrapper/np_pad_flip_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import csdmpy as cp 4 | 5 | 6 | def test_1_linear(): 7 | test_a = np.arange(10 * 40).reshape(10, 40) 8 | csdm = cp.as_csdm(test_a) 9 | csdm_pad = np.pad(csdm, (2, 3)) 10 | 11 | np.testing.assert_allclose(csdm_pad.x[1].coordinates, np.arange(15) - 2) 12 | np.testing.assert_allclose(csdm_pad.x[0].coordinates, np.arange(45) - 2) 13 | 14 | csdm_pad = np.pad(csdm, pad_width=((2, 3), (1, 4))) 15 | np.testing.assert_allclose(csdm_pad.x[1].coordinates, np.arange(15) - 1) 16 | np.testing.assert_allclose(csdm_pad.x[0].coordinates, np.arange(45) - 2) 17 | 18 | csdm_pad = np.pad(csdm, pad_width=5, constant_values=((500, -500), (1000, -1000))) 19 | np.testing.assert_allclose(csdm_pad[0, 0], 500) 20 | np.testing.assert_allclose(csdm_pad[49, 19], -500) 21 | 22 | csdm_pad = np.pad(csdm, pad_width=(5,)) 23 | np.testing.assert_allclose(csdm_pad[0, 0], 0) 24 | np.testing.assert_allclose(csdm_pad[49, 19], 0) 25 | 26 | 27 | def test_2_monotonic(): 28 | array = np.arange(10 * 40).reshape(10, 40) 29 | d_v = cp.as_dependent_variable(array) 30 | d_1 = cp.as_dimension(np.exp(np.arange(10) / 10)) 31 | d_2 = cp.as_dimension(np.arange(40)) 32 | csdm = cp.CSDM(dimensions=[d_1, d_2], dependent_variables=[d_v]) 33 | 34 | padded = np.pad(csdm, ((2, 3),)) 35 | np.testing.assert_allclose(padded.x[0].coordinates[:2], [0.78965816, 0.89482908]) 36 | 37 | 38 | def test_3_labeled(): 39 | array = np.arange(10 * 40).reshape(10, 40) 40 | d_v = cp.as_dependent_variable(array) 41 | d_1 = cp.as_dimension(["3"] * 2 + ["5"] * 7 + ["1"]) 42 | d_2 = cp.as_dimension(np.arange(40)) 43 | csdm = cp.CSDM(dimensions=[d_1, d_2], dependent_variables=[d_v]) 44 | 45 | padded = np.pad(csdm, ((2, 3),)) 46 | np.testing.assert_equal(padded.x[0].coordinates[:2], ["0", "0"]) 47 | 48 | 49 | def test_flip(): 50 | test_a = np.arange(10 * 40).reshape(10, 40) 51 | csdm = cp.as_csdm(test_a) 52 | 53 | csdm_flip = np.flip(csdm) 54 | np.testing.assert_allclose(np.argmax(csdm_flip), 0) 55 | 56 | csdm_flip = np.flip(csdm, 1) 57 | np.testing.assert_allclose(np.argmax(csdm_flip), 39) 58 | 59 | csdm_flip = np.flip(csdm, axis=0) 60 | np.testing.assert_allclose(np.argmax(csdm_flip), 360) 61 | -------------------------------------------------------------------------------- /tests/numpy_wrapper/np_tile_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import csdmpy as cp 4 | 5 | 6 | def test_1_linear(): 7 | dim1 = cp.as_dimension(np.arange(4)) 8 | dim2 = cp.as_dimension(np.arange(10)) 9 | dv = cp.as_dependent_variable(np.arange(40)) 10 | dataset = cp.CSDM(dimensions=[dim1, dim2], dependent_variables=[dv]) 11 | 12 | new_dim1 = cp.LinearDimension(count=5, increment="2 Hz") 13 | new_dim2 = cp.LinearDimension(count=20, increment="1 s") 14 | 15 | ds1 = np.tile(dataset, (1, new_dim2, new_dim1)) 16 | ds2 = np.tile(dataset, (1, 2, new_dim1)) 17 | 18 | assert ds1.shape == (4, 20, 5) 19 | assert ds2.shape == (4, 20, 5) 20 | 21 | tiled = np.tile(dv.components[0], (new_dim1.count, 2, 1)) 22 | np.allclose(ds1.y[0].components[0], tiled) 23 | np.allclose(ds2.y[0].components[0], tiled) 24 | -------------------------------------------------------------------------------- /tests/numpy_wrapper/numpy_csdm_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | import csdmpy as cp 5 | 6 | data = np.random.rand(15, 5, 10) 7 | dim_1 = {"type": "linear", "count": 10, "increment": "1"} 8 | dim_2 = {"type": "linear", "count": 5, "increment": "1"} 9 | dim_3 = {"type": "linear", "count": 15, "increment": "1"} 10 | d_v = {"type": "internal", "components": [data.ravel()], "quantity_type": "scalar"} 11 | test_1 = cp.CSDM(dimensions=[dim_1, dim_2, dim_3], dependent_variables=[d_v]) 12 | 13 | test_2 = cp.CSDM( 14 | dimensions=[dim_1], dependent_variables=[cp.as_dependent_variable(np.ones(10) * 2)] 15 | ) 16 | 17 | 18 | def test_mult(): 19 | res = np.ones(10) * 2 20 | data_new = test_1 * res[:, None, None] 21 | assert np.allclose(data_new.y[0].components[0], data * res[None, None, :]) 22 | 23 | data_new = res[:, None, None] * test_1 24 | assert np.allclose(data_new.y[0].components[0], res[None, None, :] * data) 25 | 26 | test_a = test_1.copy() 27 | test_a *= res[:, None, None] 28 | assert np.allclose(test_a.y[0].components[0], data * res[None, None, :]) 29 | 30 | data_new = test_1 * test_2 31 | assert np.allclose(data_new.y[0].components[0], data * res[None, None, :]) 32 | 33 | 34 | def test_div(): 35 | res = np.ones(10) * 2 36 | data_new = test_1 / res[:, None, None] 37 | assert np.allclose(data_new.y[0].components[0], data / res[None, None, :]) 38 | 39 | data_new = res[:, None, None] / test_1 40 | assert np.allclose(data_new.y[0].components[0], res[None, None, :] / data) 41 | 42 | test_a = test_1.copy() 43 | test_a /= res[:, None, None] 44 | assert np.allclose(test_a.y[0].components[0], data / res[None, None, :]) 45 | 46 | data_new = test_1 / test_2 47 | assert np.allclose(data_new.y[0].components[0], data / res[None, None, :]) 48 | 49 | 50 | def test_raise(): 51 | test_dvs = cp.CSDM(dimensions=[dim_1], dependent_variables=[d_v, d_v]) 52 | error = "'CSDM' and multi dependent variable CSDM" 53 | with pytest.raises(TypeError, match=f".*{error}.*"): 54 | _ = test_1 * test_dvs 55 | -------------------------------------------------------------------------------- /tests/save_file_test.py: -------------------------------------------------------------------------------- 1 | from os import remove 2 | 3 | import csdmpy as cp 4 | 5 | 6 | def setup(): 7 | d_x = cp.Dimension(type="labeled", labels=["🍈", "🍉", "🍋", "🍌", "🥑", "🍍"]) 8 | d_y = cp.DependentVariable( 9 | type="internal", 10 | numeric_type="float32", 11 | quantity_type="scalar", 12 | components=[[0.5, 0.25, 1, 2, 1, 0.25]], 13 | ) 14 | data = cp.CSDM( 15 | description="An emoji dataset", dimensions=[d_x], dependent_variables=[d_y] 16 | ) 17 | return data 18 | 19 | 20 | def test_csdf_base64(): 21 | data = setup() 22 | data.save("my_file_base64.csdf") 23 | remove("my_file_base64.csdf") 24 | 25 | 26 | def test_csdf_none(): 27 | data = setup() 28 | data.y[0].encoding = "none" 29 | data.save("my_file_none.csdf") 30 | remove("my_file_none.csdf") 31 | 32 | 33 | def test_csdfe(): 34 | data = setup() 35 | data.y[0].encoding = "raw" 36 | data.save("my_file_raw.csdfe") 37 | remove("my_file_raw.csdfe") 38 | remove("my_file_raw_0.dat") 39 | -------------------------------------------------------------------------------- /tests/serialization_test.py: -------------------------------------------------------------------------------- 1 | from os import remove 2 | 3 | import numpy as np 4 | 5 | import csdmpy as cp 6 | 7 | 8 | def setup(): 9 | dimension1 = cp.as_dimension(np.arange(10)) 10 | dimension2 = cp.as_dimension(np.arange(20)) 11 | data = cp.as_dependent_variable(np.random.rand(20, 10)) 12 | 13 | csdm = cp.CSDM(dimensions=[dimension1, dimension2], dependent_variables=[data]) 14 | 15 | return csdm 16 | 17 | 18 | def test_application(): 19 | 20 | csdm1 = setup() 21 | csdm1.application = {"test": "root"} 22 | csdm1.dimensions[0].application = {"test": "d0"} 23 | csdm1.dimensions[0].reciprocal.application = {"test": "reciprocal-d0"} 24 | csdm1.dimensions[1].application = {"test": "d1"} 25 | csdm1.dimensions[1].reciprocal.application = {"test": "reciprocal-d1"} 26 | csdm1.y[0].application = {"test": "dv0"} 27 | 28 | csdm1.y[0].encoding = "base64" 29 | csdm1.save("csdm1.csdf") 30 | csdm1_test = cp.load("csdm1.csdf", application=True) 31 | assert csdm1_test == csdm1 32 | remove("csdm1.csdf") 33 | -------------------------------------------------------------------------------- /tests/sparse_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from csdmpy.dependent_variable.sparse import check_sparse_sampling_key_value 5 | from csdmpy.dependent_variable.sparse import SparseSampling 6 | 7 | sparse_sampling = { 8 | "dimension_indexes": [0], 9 | "sparse_grid_vertexes": [0, 5, 10, 15, 20, 25], 10 | "unsigned_integer_type": "uint16", 11 | } 12 | 13 | 14 | def test_01(): 15 | s_p = SparseSampling(**sparse_sampling) 16 | assert s_p.dimension_indexes == [0] 17 | 18 | assert np.all(s_p.sparse_grid_vertexes == [0, 5, 10, 15, 20, 25]) 19 | 20 | assert s_p.description == "" 21 | assert s_p.encoding == "none" 22 | assert s_p.unsigned_integer_type.value == "uint16" 23 | assert s_p.application is None 24 | 25 | 26 | def test_02(): 27 | sparse_sampling = { 28 | "dimension_indexes": [0], 29 | } 30 | 31 | error = "Missing a required `sparse_grid_vertexes`" 32 | with pytest.raises(KeyError, match=f".*{error}.*"): 33 | check_sparse_sampling_key_value(sparse_sampling) 34 | 35 | 36 | def test_03(): 37 | sparse_sampling = { 38 | "sparse_grid_vertexes": [0, 5, 10, 15, 20, 25], 39 | } 40 | 41 | error = "Missing a required `dimension_indexes`" 42 | with pytest.raises(KeyError, match=f".*{error}.*"): 43 | check_sparse_sampling_key_value(sparse_sampling) 44 | 45 | 46 | def test_04(): 47 | sparse_sampling = { 48 | "encoding": "base64", 49 | "dimension_indexes": [0], 50 | "sparse_grid_vertexes": [0, 5, 10, 15, 20, 25], 51 | } 52 | error = "Missing a required `unsigned_integer_type`" 53 | with pytest.raises(KeyError, match=f".*{error}.*"): 54 | check_sparse_sampling_key_value(sparse_sampling) 55 | 56 | 57 | def test_05(): 58 | sparse_sampling = { 59 | "encoding": "base64", 60 | "unsigned_integer_type": "float32", 61 | "dimension_indexes": [0], 62 | "sparse_grid_vertexes": [0, 5, 10, 15, 20, 25], 63 | } 64 | error = "float32 is an invalid `unsigned_integer_type` enumeration" 65 | with pytest.raises(ValueError, match=f".*{error}.*"): 66 | check_sparse_sampling_key_value(sparse_sampling) 67 | 68 | 69 | def test_06(): 70 | sp1 = SparseSampling(**sparse_sampling) 71 | sp2 = SparseSampling(**sparse_sampling) 72 | 73 | assert sp1 == sp2 74 | -------------------------------------------------------------------------------- /tests/statistics_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import csdmpy as cp 4 | import csdmpy.statistics as stat 5 | 6 | 7 | def get_gaussian(x, b, c): 8 | return np.exp(-((x - b) ** 2) / (2 * c**2)) 9 | 10 | 11 | def test_01(): 12 | x = np.arange(100) * 2 - 100.0 13 | gauss = get_gaussian(x, 5.0, 4.0) 14 | csdm = cp.as_csdm(gauss, unit="T") 15 | csdm.dimensions[0] = cp.as_dimension(x, unit="µm") 16 | 17 | gauss_integral = 4.0 * np.sqrt(2 * np.pi) 18 | 19 | # integration 20 | int_csdm = stat.integral(csdm) 21 | assert np.allclose(int_csdm.value, gauss_integral) 22 | assert str(int_csdm.unit) == "T um" 23 | 24 | # mean 25 | mean_csdm = stat.mean(csdm)[0] 26 | assert np.allclose(mean_csdm.value, 5.0) 27 | assert str(mean_csdm.unit) == "um" 28 | 29 | # variance 30 | var_csdm = stat.var(csdm)[0] 31 | assert np.allclose(var_csdm.value, 16.0) 32 | assert str(var_csdm.unit) == "um2" 33 | 34 | # standard deviation 35 | std_csdm = stat.std(csdm)[0] 36 | assert np.allclose(std_csdm.value, 4.0) 37 | assert str(std_csdm.unit) == "um" 38 | 39 | 40 | def test_02(): 41 | x = np.arange(100) - 50.0 42 | y = np.arange(500) * 0.1 - 25.0 43 | gauss1 = get_gaussian(x, 5.0, 4.0)[np.newaxis, :] 44 | gauss2 = get_gaussian(y, 0.50, 0.40)[:, np.newaxis] 45 | csdm = cp.as_csdm(gauss1 * gauss2, unit="K") 46 | csdm.dimensions[1] = cp.as_dimension(y, unit="s") 47 | csdm.dimensions[0] = cp.as_dimension(x, unit="deg") 48 | 49 | gauss_integral = 4.0 * 2 * np.pi * 0.4 50 | 51 | # integration 52 | int_csdm = stat.integral(csdm) 53 | assert np.allclose(int_csdm.value, gauss_integral) 54 | assert str(int_csdm.unit) in ["deg K s", "K deg s"] 55 | 56 | # mean 57 | mean_csdm = stat.mean(csdm) 58 | assert np.allclose(mean_csdm[0].value, 5.0) 59 | assert np.allclose(mean_csdm[1].value, 0.5) 60 | assert str(mean_csdm[0].unit) == "deg" 61 | assert str(mean_csdm[1].unit) == "s" 62 | 63 | # variance 64 | var_csdm = stat.var(csdm) 65 | assert np.allclose(var_csdm[0].value, 16.0) 66 | assert np.allclose(var_csdm[1].value, 0.16) 67 | assert str(var_csdm[0].unit) == "deg2" 68 | assert str(var_csdm[1].unit) == "s2" 69 | 70 | # standard deviation 71 | std_csdm = stat.std(csdm) 72 | assert np.allclose(std_csdm[0].value, 4.0) 73 | assert np.allclose(std_csdm[1].value, 0.4) 74 | assert str(std_csdm[0].unit) == "deg" 75 | assert str(std_csdm[1].unit) == "s" 76 | -------------------------------------------------------------------------------- /tests/unit_test.py: -------------------------------------------------------------------------------- 1 | from csdmpy.units import ScalarQuantity 2 | 3 | 4 | def test_unit(): 5 | a = ScalarQuantity("1 tr").quantity 6 | assert str(a) == "1.0 tr" 7 | assert str(a.to("cycle")) == "1.0 cycle" 8 | # assert ScalarQuantity(a).format() == '1.0 tr' 9 | 10 | a = ScalarQuantity("10 cm^-1/s") 11 | assert str(a) == "10.0 cm^-1 * s^-1" 12 | assert ScalarQuantity(a).quantity == a.quantity 13 | 14 | a = ScalarQuantity("1 deg").quantity 15 | assert str(a) == "1.0 deg" 16 | assert str(ScalarQuantity(a)) == "1.0 °" 17 | assert str(ScalarQuantity("1 deg")) == "1.0 °" 18 | 19 | a = ScalarQuantity("(54.3/2) ppm").quantity 20 | assert str(a) == "27.15 ppm" 21 | assert str(ScalarQuantity(a)) == "27.15 ppm" 22 | 23 | a = ScalarQuantity("(54.3/2) (µHz/Hz)").quantity 24 | assert str(a) == "27.15 uHz / Hz" 25 | assert str(ScalarQuantity(a)) in ["27.15 Hz^-1 * µHz", "27.15 µHz * Hz^-1"] 26 | assert str(a.to("ppm")) == "27.15 ppm" 27 | 28 | a = ScalarQuantity("5 kg * m / s").quantity 29 | b = a * ScalarQuantity("1 m / s").quantity 30 | assert str(a) == "5.0 kg m / s" 31 | assert str(ScalarQuantity(a)) == "5.0 kg * m * s^-1" 32 | assert str(ScalarQuantity(b)) in ["5.0 kg * m^2 * s^-2", "5.0 m^2 * kg * s^-2"] 33 | assert ScalarQuantity(b).__format__("unit") in [ 34 | "kg * m^2 * s^-2", 35 | "m^2 * kg * s^-2", 36 | ] 37 | assert str(b.to("J")) == "5.0 J" 38 | 39 | a = ScalarQuantity("5e-7 s").quantity 40 | assert str(a) == "5e-07 s" 41 | assert str(ScalarQuantity(a)) == "5e-07 s" 42 | assert str(ScalarQuantity(a.to("us"))) == "0.5 µs" 43 | assert ScalarQuantity(a.to("us")).__format__("unit") == "µs" 44 | 45 | a = ScalarQuantity("5e-7 * 2 s").quantity 46 | assert str(a) == "1e-06 s" 47 | assert str(ScalarQuantity(a)) == "1e-06 s" 48 | assert str(ScalarQuantity(a.to("us"))) == "1.0 µs" 49 | -------------------------------------------------------------------------------- /tests/utils_test.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | import pytest 3 | 4 | import csdmpy 5 | from csdmpy.utils import check_and_assign_bool 6 | from csdmpy.utils import check_encoding 7 | from csdmpy.utils import np_check_for_out 8 | from csdmpy.utils import NumericType 9 | from csdmpy.utils import QuantityType 10 | 11 | 12 | def test_encoding(): 13 | assert check_encoding("base64") == "base64" 14 | assert check_encoding("raw") == "raw" 15 | assert check_encoding("none") == "none" 16 | 17 | error = "is an invalid `encoding` enumeration literal. The allowed values are" 18 | with pytest.raises(ValueError, match=f".*{error}.*"): 19 | check_encoding("text") 20 | 21 | 22 | def test_quantity_type(): 23 | assert QuantityType("pixel_4").value == "pixel_4" 24 | assert QuantityType("pixel_4").p == 4 25 | assert QuantityType("scalar").value == "scalar" 26 | assert QuantityType("vector_15").value == "vector_15" 27 | assert QuantityType("vector_15").p == 15 28 | assert QuantityType("matrix_13_3").value == "matrix_13_3" 29 | assert QuantityType("matrix_13_3").p == 39 30 | assert QuantityType("symmetric_matrix_10").value == "symmetric_matrix_10" 31 | assert QuantityType("symmetric_matrix_10").p == 55 32 | 33 | error = "is an invalid `quantity_type` enumeration literal. The allowed values are" 34 | with pytest.raises(ValueError, match=f".*{error}.*"): 35 | QuantityType("RGB") 36 | 37 | 38 | def test_numeric_type(): 39 | assert NumericType("uint8").value == "uint8" 40 | assert NumericType("uint8").dtype == "