diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..769d3c5 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,19 @@ +.github + +*.pyc + +env + +**/__pycache__ +**/.pytest_cache + +.idea/** + +**/dist +**/build +**/*.egg-info* + +tests/* +paper + +.DS_Store \ No newline at end of file diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..43e2629 --- /dev/null +++ b/.flake8 @@ -0,0 +1,10 @@ +[flake8] +exclude = + .git, + __pycache__, + build, + dist, + env, + venv, +max-line-length = 127 +max-complexity=10 \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5ab0ddf --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,9 @@ +--- +# Documentation +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file +version: 2 +updates: +- package-ecosystem: github-actions + directory: / + schedule: + interval: monthly diff --git a/.github/workflows/autotest.yml b/.github/workflows/flake8.yml similarity index 59% rename from .github/workflows/autotest.yml rename to .github/workflows/flake8.yml index bbca626..46346d8 100644 --- a/.github/workflows/autotest.yml +++ b/.github/workflows/flake8.yml @@ -1,31 +1,32 @@ -name: CI workflow +name: flake8 on: # this workflow triggered on below condition [push, pull_request] push: - branches: [ master ] + branches: [ main ] pull_request: - branches: [ master ] + branches: [ '*' ] + +# cancel previous similar workflow runs +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: build: runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.5, 3.6, 3.7, 3.8] steps: - - uses: actions/checkout@v2 - - name: Set up python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - name: Set up python + uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} + python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flake8 pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install flake8 - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index bbca626..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: CI workflow - -on: - # this workflow triggered on below condition [push, pull_request] - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.5, 3.6, 3.7, 3.8] - - steps: - - uses: actions/checkout@v2 - - name: Set up python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install flake8 pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..2e065ad --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,81 @@ +name: test + +on: + # this workflow triggered on below condition [push, pull_request] + push: + branches: [ main ] + pull_request: + branches: [ "*" ] + +# cancel previous similar workflow runs +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test_cli: + + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11"] + os: [ubuntu-latest, windows-latest, macos-latest] + fail-fast: false + + runs-on: ${{ matrix.os }} + + steps: + + - uses: actions/checkout@v4 + + - name: Set up python ${{ matrix.python-version }} + + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install package + run: | + python -m pip install --upgrade pip + pip install . + + - name: Version and help + run: | + brkraw --version + brkraw --help + + - name: "smoke end-to-end test: use CLI on tutorial data" + run: make demo + + + test_tutorial: + + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11"] + os: [ubuntu-latest, windows-latest, macos-latest] + fail-fast: false + + runs-on: ${{ matrix.os }} + + steps: + + - uses: actions/checkout@v4 + + - name: Set up python ${{ matrix.python-version }} + + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install .[dev] + + - name: Install tutorial + run: make tests/tutorials + + - name: Test tutorial notebook + run: | + python -m pytest --nbmake tests/tutorials/JupyterNotebooks/01_GettingStarted.ipynb + tree tests/tutorials/raw \ No newline at end of file diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml new file mode 100644 index 0000000..a8afdc8 --- /dev/null +++ b/.github/workflows/validation.yml @@ -0,0 +1,24 @@ +--- +name: validation + +on: + push: + branches: [main] + pull_request: + branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + + validate_cff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Check whether the citation metadata from CITATION.cff is valid + uses: citation-file-format/cffconvert-github-action@2.0.0 + with: + args: --validate + diff --git a/.gitignore b/.gitignore index 98c5b69..1e681b8 100644 --- a/.gitignore +++ b/.gitignore @@ -8,8 +8,7 @@ ui/styles/*.css dist build *.pid -test -test/* *.egg-info *.egg-info/* -.DS_Store \ No newline at end of file +.DS_Store +tests/tutorials \ No newline at end of file diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..00551eb --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,49 @@ +cff-version: 1.2.0 + +title: "brkraw" + +version: "0.3.10" + +abstract: Bruker PvDataset Loader + +message: "If you use this software, please cite it as below." + +repository-code: "https://github.com/BrkRaw/brkraw" + +identifiers: + - description: This is the collection of archived snapshots of all releases + type: doi + value: "10.5281/zenodo.245546149" + +contact: + - email: shlee@unc.edu + family-names: SungHo + given-names: Lee + +authors: + - email: shlee@unc.edu + family-names: SungHo + given-names: Lee + + - email: banwoomi@unc.edu + family-names: Woomi + given-names: Ban + + - family-names: Dumas + given-names: Jaiden + + - family-names: Devenyi + given-names: Gabriel A. + + - email: shihy@neurology.unc.edu + family-names: Yen-Yu + given-names: Ian Shih + +license: GPL-3.0 + +keywords: + - bruker + - data_handler + - converter + - administrator_tool + - brain imaging data structure diff --git a/CODE_OF_CONDUCT b/CODE_OF_CONDUCT.md similarity index 100% rename from CODE_OF_CONDUCT rename to CODE_OF_CONDUCT.md diff --git a/CONTRIBUTING b/CONTRIBUTING deleted file mode 100644 index 3fa4da1..0000000 --- a/CONTRIBUTING +++ /dev/null @@ -1,17 +0,0 @@ -# Contributing - -When contributing to this repository, please first discuss the change you wish to make via issue, -email, or any other method with the owners of this repository before making a change. - -Please note we have a code of conduct, please follow it in all your interactions with the project. - -## Pull Request Process - -1. Ensure any install or build dependencies are removed before the end of the layer when doing a - build. -2. Update the README.md with details of changes to the interface, this includes new environment - variables, exposed ports, useful file locations and container parameters. -3. Increase the version numbers in any examples files and the README.md to the new version that this - Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). -4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you - do not have permission to do that, you may request the second reviewer to merge it for you. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bdfaf10..3fa4da1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,17 @@ -Here is how to contribute. +# Contributing -TODO: +When contributing to this repository, please first discuss the change you wish to make via issue, +email, or any other method with the owners of this repository before making a change. + +Please note we have a code of conduct, please follow it in all your interactions with the project. + +## Pull Request Process + +1. Ensure any install or build dependencies are removed before the end of the layer when doing a + build. +2. Update the README.md with details of changes to the interface, this includes new environment + variables, exposed ports, useful file locations and container parameters. +3. Increase the version numbers in any examples files and the README.md to the new version that this + Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). +4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you + do not have permission to do that, you may request the second reviewer to merge it for you. \ No newline at end of file diff --git a/Dockerfile.dev b/Dockerfile.dev index debd4b9..f4bb431 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,12 +1,12 @@ # This docker file build a editable image. # You could directly edit the source code at `/home/brkraw to make changes. Or you could mount your brkraw code folder to /home/brkraw -FROM python:3.7 +FROM python:3.11 WORKDIR /home RUN mkdir ./brkraw WORKDIR /home/brkraw COPY . . -RUN python -m pip install -e /home/brkraw +RUN python -m pip install --editable /home/brkraw RUN mkdir /data WORKDIR /data diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..30cb7df --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +clean: + rm -rf tests/tutorials + +tests/tutorials: + git clone https://github.com/BrkRaw/tutorials.git tests/tutorials + +tests/tutorials/SampleData/20190724_114946_BRKRAW_1_1: tests/tutorials + unzip -uq tests/tutorials/SampleData/20190724_114946_BRKRAW_1_1.zip -d tests/tutorials/SampleData/ + +tests/tutorials/bids_map.csv: tests/tutorials/SampleData/20190724_114946_BRKRAW_1_1 + brkraw bids_helper tests/tutorials/SampleData/20190724_114946_BRKRAW_1_1 \ + tests/tutorials/bids_map + +tests/tutorials/raw: tests/tutorials/bids_map.csv + brkraw bids_convert tests/tutorials/SampleData/20190724_114946_BRKRAW_1_1 \ + tests/tutorials/bids_map.csv \ + --output tests/tutorials/raw + +demo: tests/tutorials + brkraw info tests/tutorials/SampleData/20190724_114946_BRKRAW_1_1.zip + make tests/tutorials/raw \ No newline at end of file diff --git a/brkraw/lib/pvobj.py b/brkraw/lib/pvobj.py index 3631345..e737952 100644 --- a/brkraw/lib/pvobj.py +++ b/brkraw/lib/pvobj.py @@ -37,8 +37,8 @@ def _update_studyinfo(self): subject = self._subject self.user_account = subject.headers['OWNER'] self.subj_id = get_value(subject, 'SUBJECT_id') - self.study_id = get_value(subject, 'SUBJECT_study_nr') - self.session_id = get_value(subject, 'SUBJECT_study_name') + self.study_id = get_value(subject, 'SUBJECT_study_name') + self.session_id = get_value(subject, 'SUBJECT_study_nr') # [20210820] Add-paravision 360 related. title = subject.headers['TITLE'] diff --git a/brkraw/scripts/brkraw.py b/brkraw/scripts/brkraw.py index 509141e..a27c96e 100644 --- a/brkraw/scripts/brkraw.py +++ b/brkraw/scripts/brkraw.py @@ -86,6 +86,8 @@ def main(): bids_helper.add_argument("-f", "--format", help="file format of BIDS dataheets. Use this option if you did not specify the extension on output. The available options are (csv/tsv/xlsx) (default: csv)", type=str, default='csv') bids_helper.add_argument("-j", "--json", help="create JSON syntax template for " "parsing metadata from the header", action='store_true') + bids_helper.add_argument("-s", "--subj", help="switch subject and study IDs", action='store_true') + bids_helper.add_argument("-t", "--sess", help="switch session and study ID", action='store_true') # bids_convert bids_convert.add_argument("input", help=input_dir_str, type=str) @@ -267,6 +269,12 @@ def main(): path = os.path.abspath(args.input) ds_output = os.path.abspath(args.output) make_json = args.json + swap_id = args.subj + swap_sess = args.sess + + if swap_id and swap_sess: + import warnings + warnings.warn('\nBoth switch subject/study IDs and switch session/study ID options are on. You probably do not want this!\n') # [220202] for back compatibility ds_fname, ds_output_ext = os.path.splitext(ds_output) @@ -276,10 +284,10 @@ def main(): ds_format = args.format # [220202] make compatible with csv, tsv and xlsx - output = '{}.{}'.format(ds_output, ds_format) + output = '{}.{}'.format(ds_fname, ds_format) Headers = ['RawData', 'SubjID', 'SessID', 'ScanID', 'RecoID', 'DataType', - 'task', 'acq', 'ce', 'rec', 'dir', 'run', 'modality', 'Start', 'End'] + 'task', 'acq', 'ce', 'rec', 'dir', 'run', 'inv', 'flip', 'mt', 'part', 'modality', 'Start', 'End'] df = pd.DataFrame(columns=Headers) # if the path directly contains scan files for one participant @@ -301,12 +309,19 @@ def main(): pvobj = dset.pvobj rawdata = pvobj.path - subj_id = pvobj.subj_id + + if swap_id: + subj_id = pvobj.study_id + else: + subj_id = pvobj.subj_id + + if swap_sess: + sess_id = pvobj.study_id + else: + sess_id = pvobj.session_id # make subj_id bids appropriate subj_id = cleanSubjectID(subj_id) - - sess_id = pvobj.session_id # make sess_id bids appropriate sess_id = cleanSessionID(sess_id) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ad6c3d6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,45 @@ +[build-system] +build-backend = "hatchling.build" +requires = ["hatchling"] + +[project] +classifiers = [ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Science/Research', + 'Topic :: Scientific/Engineering :: Medical Science Apps.', + 'Natural Language :: English', +] +dependencies = [ + 'nibabel>=3.0.2', + 'numpy>=1.18.0', + 'pandas>=1.0.0', + 'pillow>=7.1.1', + 'tqdm>=4.45.0', + 'openpyxl>=3.0.3', + 'xlrd>=1.0.0' +] +description = "Bruker PvDataset Loader" +license = {text = "GNLv3"} +version = "0.3.10" +maintainers = [{name = "SungHo Lee", email = 'shlee@unc.edu'}] +name = "brkraw" +readme = "README.md" +requires-python = ">=3.7" +keywords = ['bruker', 'data_handler', 'converter', 'administrator_tool'] + +[project.urls] +Homepage = "https://github.com/brkraw/brkraw" + +[project.optional-dependencies] +SimpleITK = [ + 'SimpleITK>=1.2.4' +] +dev = [ + "flake8", + "pytest", + "nbmake" +] + +[project.scripts] +brkraw = "brkraw.scripts.brkraw:main" +brk-backup = 'brkraw.scripts.brk_backup:main' \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100644 index 2494c6e..0000000 --- a/setup.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/scripts/env python -""" -Bruker PVdataset loader / converter -""" -from distutils.core import setup -from setuptools import find_packages -import re -import io - -__version__ = re.search( - r'__version__\s*=\s*[\'"]([^\'"]*)[\'"]', - io.open('brkraw/__init__.py', encoding='utf_8_sig').read() - ).group(1) - -__author__ = 'SungHo Lee' -__email__ = 'shlee@unc.edu' -__url__ = 'https://github.com/brkraw/brkraw' - -setup(name='brkraw', - version=__version__, - description='Bruker PvDataset Loader', - python_requires='>3.5', - author=__author__, - author_email=__email__, - url=__url__, - license='GNLv3', - packages=find_packages(), - install_requires=['nibabel>=3.0.2', - 'numpy>=1.18.0', - 'pandas>=1.0.0', - 'pillow>=7.1.1', - 'tqdm>=4.45.0', - 'openpyxl>=3.0.3', - 'xlrd>=1.0.0'], - extras_require = { - 'SimpleITK': ['SimpleITK>=1.2.4'] - }, - entry_points={ - 'console_scripts': [ - 'brkraw=brkraw.scripts.brkraw:main', - 'brk-backup=brkraw.scripts.brk_backup:main', - ], - }, - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Science/Research', - 'Topic :: Scientific/Engineering :: Medical Science Apps.', - 'Natural Language :: English', - ], - keywords = 'bruker data_handler converter administrator_tool' - )