Skip to content

Commit

Permalink
Merge pull request #7 from ArcanaFramework/frametree-refactor
Browse files Browse the repository at this point in the history
Changes for Frametree refactor
  • Loading branch information
tclose authored Aug 23, 2024
2 parents f1bd9ca + 1a27a0e commit 2d8ef00
Show file tree
Hide file tree
Showing 17 changed files with 78 additions and 78 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}

build:
Expand All @@ -81,7 +81,7 @@ jobs:
- name: Install build tools
run: python3 -m pip install --break-system-packages build twine
- name: Build source and wheel distributions
run: python3 -m build
run: python3 -m build
- name: Check distributions
run: twine check dist/*
- uses: actions/upload-artifact@v3
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ __pycache__
~*
/test-data/dicom-dataset
*.venv
/pydra2app/xnat/_version.py
/pipeline2app/xnat/_version.py
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
# Pydra2App - XNAT
[![tests](https://github.com/arcanaframework/pydra2app-xnat/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/ArcanaFramework/pydra2app-xnat/actions/workflows/ci-cd.yml)
[![codecov](https://codecov.io/gh/arcanaframework/pydra2app-xnat/branch/main/graph/badge.svg?token=UIS0OGPST7)](https://codecov.io/gh/arcanaframework/pydra2app-xnat)
[![Python versions](https://img.shields.io/pypi/pyversions/pydra2app-xnat.svg)](https://pypi.python.org/pypi/pydra2app-xnat/)
[![Latest Version](https://img.shields.io/pypi/v/pydra2app-xnat.svg)](https://pypi.python.org/pypi/pydra2app-xnat/)
[![docs](https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat)](https://arcanaframework.github.io/pydra2app)
# Pipeline2App - XNAT
[![tests](https://github.com/arcanaframework/pipeline2app-xnat/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/ArcanaFramework/pipeline2app-xnat/actions/workflows/ci-cd.yml)
[![codecov](https://codecov.io/gh/arcanaframework/pipeline2app-xnat/branch/main/graph/badge.svg?token=UIS0OGPST7)](https://codecov.io/gh/arcanaframework/pipeline2app-xnat)
[![Python versions](https://img.shields.io/pypi/pyversions/pipeline2app-xnat.svg)](https://pypi.python.org/pypi/pipeline2app-xnat/)
[![Latest Version](https://img.shields.io/pypi/v/pipeline2app-xnat.svg)](https://pypi.python.org/pypi/pipeline2app-xnat/)
[![docs](https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat)](https://arcanaframework.github.io/pipeline2app)

An extension for the [Pydra2App](http://arcanaframework.github.io/pydra2app) framework that support for building [XNAT](https://xnat.org) "apps" (container service docker images)
An extension for the [Pipeline2App](http://arcanaframework.github.io/pipeline2app) framework that support for building [XNAT](https://xnat.org) "apps" (container service docker images)

## Quick Installation

This extension can be installed for Python 3 using *pip*:

```
$ pip3 install pydra2app-xnat
$ pip3 install pipeline2app-xnat
```

This will also install the core Pydra2App package and any required dependencies.
This will also install the core Pipeline2App package and any required dependencies.

## License

Expand Down
4 changes: 2 additions & 2 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
coverage:
range: "50...100"
ignore: # files and folders that will be removed during processing
ignore: # files and folders that will be removed during processing
- "**/tests"
- "arcana/xnat/_version.py"
- "pipeline2app/xnat/_version.py"
status:
project:
default:
Expand Down
30 changes: 15 additions & 15 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
import xnat4tests
import medimages4tests.dummy.nifti
import medimages4tests.dummy.dicom.mri.fmap.siemens.skyra.syngo_d13c
from pydra2app.core.image.base import BaseImage
from pipeline2app.core.image.base import BaseImage
from frametree.common import Clinical
from frametree.core.set import Dataset
from frametree.core.frameset import FrameSet
from fileformats.medimage import NiftiGzX, NiftiGz, DicomSeries, NiftiX
from fileformats.text import Plain as Text
from fileformats.image import Png
Expand Down Expand Up @@ -129,7 +129,7 @@ def arcana_home(work_dir):

TEST_XNAT_DATASET_BLUEPRINTS = {
"basic": TestXnatDatasetBlueprint( # dataset name
dim_lengths=[1, 1, 3], # number of timepoints, groups and members respectively
dim_lengths=[1, 1, 3], # number of visits, groups and members respectively
scans=[
ScanBP(
name="scan1", # scan type (ID is index)
Expand Down Expand Up @@ -190,7 +190,7 @@ def arcana_home(work_dir):
derivatives=[
FileBP(
path="deriv1",
row_frequency=Clinical.timepoint,
row_frequency=Clinical.visit,
datatype=Text,
filenames=["file.txt"],
),
Expand All @@ -202,20 +202,20 @@ def arcana_home(work_dir):
),
FileBP(
path="deriv3",
row_frequency=Clinical.batch,
row_frequency=Clinical.groupedvisit,
datatype=Directory,
filenames=["dir"],
),
FileBP(
path="deriv4",
row_frequency=Clinical.dataset,
row_frequency=Clinical.constant,
datatype=Text,
filenames=["file.txt"],
),
],
),
"multi": TestXnatDatasetBlueprint( # dataset name
dim_lengths=[2, 2, 2], # number of timepoints, groups and members respectively
dim_lengths=[2, 2, 2], # number of visits, groups and members respectively
scans=[
ScanBP(
name="scan1",
Expand All @@ -225,7 +225,7 @@ def arcana_home(work_dir):
id_patterns={
"group": r"subject::group(\d+)member\d+",
"member": r"subject::group\d+member(\d+)",
"timepoint": r"session::timepoint(\d+).*",
"visit": r"session::visit(\d+).*",
},
derivatives=[
FileBP(
Expand All @@ -242,7 +242,7 @@ def arcana_home(work_dir):
),
FileBP(
path="deriv3",
row_frequency=Clinical.timepoint,
row_frequency=Clinical.visit,
datatype=Directory,
filenames=["doubledir"],
),
Expand All @@ -254,19 +254,19 @@ def arcana_home(work_dir):
),
FileBP(
path="deriv5",
row_frequency=Clinical.dataset,
row_frequency=Clinical.constant,
datatype=Text,
filenames=["file.txt"],
),
FileBP(
path="deriv6",
row_frequency=Clinical.batch,
row_frequency=Clinical.groupedvisit,
datatype=Text,
filenames=["file.txt"],
),
FileBP(
path="deriv7",
row_frequency=Clinical.matchedpoint,
row_frequency=Clinical.matchedvisit,
datatype=Text,
filenames=["file.txt"],
),
Expand Down Expand Up @@ -380,23 +380,23 @@ def access_dataset(
access_method: str,
xnat_repository: Xnat,
xnat_archive_dir: Path,
) -> Dataset:
) -> FrameSet:
if access_method == "cs":
proj_dir = xnat_archive_dir / project_id / "arc001"
store = XnatViaCS(
server=xnat_repository.server,
user=xnat_repository.user,
password=xnat_repository.password,
cache_dir=xnat_repository.cache_dir,
row_frequency=Clinical.dataset,
row_frequency=Clinical.constant,
input_mount=proj_dir,
output_mount=Path(mkdtemp()),
)
elif access_method == "api":
store = xnat_repository
else:
assert False, f"unrecognised access method {access_method}"
return store.load_dataset(project_id, name="")
return store.load_frameset(project_id, name="")


@pytest.fixture(scope="session")
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from pydra2app.core.cli import ext
from pipeline2app.core.cli import ext


@ext.group(name="xnat")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import click
from pydra2app.core.command import entrypoint_opts
from pydra2app.xnat import XnatApp
from pipeline2app.core.command import entrypoint_opts
from pipeline2app.xnat import XnatApp
from .base import xnat_group


Expand All @@ -10,27 +10,27 @@
launches a pipeline in a single command. To be used within the command configuration
of an XNAT Container Service ready Docker image.
DATASET_LOCATOR string containing the nickname of the data store, the ID of the
ADDRESS string containing the nickname of the data store, the ID of the
dataset (e.g. XNAT project ID or file-system directory) and the dataset's name
in the format <store-nickname>//<dataset-id>[@<dataset-name>]
""",
)
@click.argument("dataset_locator")
@click.argument("address")
@entrypoint_opts.data_columns
@entrypoint_opts.parameterisation
@entrypoint_opts.execution
@entrypoint_opts.debugging
@entrypoint_opts.dataset_config
def cs_entrypoint(
dataset_locator,
address,
spec_path,
**kwargs,
):

image_spec = XnatApp.load(spec_path)

image_spec.command.execute(
dataset_locator,
address,
**kwargs,
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
XNAT_USER_KEY = "XNAT_USER"
XNAT_PASS_KEY = "XNAT_PASS"
XNAT_AUTH_FILE_KEY = "XNAT_AUTH_FILE"
XNAT_AUTH_FILE_DEFAULT = Path("~/.pydra2app_xnat_user_token.json").expanduser()
XNAT_AUTH_FILE_DEFAULT = Path("~/.pipeline2app_xnat_user_token.json").expanduser()


def load_auth(server, user, password, auth_file):
Expand All @@ -30,7 +30,7 @@ def load_auth(server, user, password, auth_file):
if auth_file == XNAT_AUTH_FILE_DEFAULT and not Path(auth_file).exists():
raise RuntimeError(
"An auth file must be provided if no server is. "
"Use pydra2app ext xnat save-token to create one"
"Use pipeline2app ext xnat save-token to create one"
)
click.echo(f"Reading existing alias/token pair from '{str(auth_file)}")
with open(auth_file) as fp:
Expand Down Expand Up @@ -284,7 +284,7 @@ def save_token(auth_file, server, user, password):
JSON file using the XNAT instance's REST API.
MANIFEST_FILE is a JSON file containing a list of container images built in a release
created by `pydra2app deploy xnat build`
created by `pipeline2app deploy xnat build`
Authentication credentials can be passed through the {XNAT_USER_KEY}
and {XNAT_PASS_KEY} environment variables. Otherwise, tokens can be saved
Expand Down
16 changes: 8 additions & 8 deletions pydra2app/xnat/command.py → pipeline2app/xnat/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import re
import attrs
from fileformats.core import FileSet, to_mime
from pydra2app.core.command.base import ContainerCommand
from pipeline2app.core.command.base import ContainerCommand
from frametree.xnat import XnatViaCS
from frametree.common import Clinical

Expand All @@ -16,8 +16,8 @@ class XnatCommand(ContainerCommand):

image: ty.Optional[XnatApp] = None

# Hard-code the data_space of XNAT commands to be clinical
DATA_SPACE = Clinical
# Hard-code the axes of XNAT commands to be clinical
AXES = Clinical

def make_json(self):
"""Constructs the XNAT CS "command" JSON config, which specifies how XNAT
Expand All @@ -39,13 +39,13 @@ def make_json(self):

output_args = self.add_output_fields(cmd_json)

flag_arg = self.add_pydra2app_flags_field(cmd_json)
flag_arg = self.add_pipeline2app_flags_field(cmd_json)

xnat_input_args = self.add_inputs_from_xnat(cmd_json)

cmd_json["command-line"] = " ".join(
self.image.activate_conda()
+ ["pydra2app", "ext", "xnat", "cs-entrypoint", "xnat-cs//[PROJECT_ID]"]
+ ["pipeline2app", "ext", "xnat", "cs-entrypoint", "xnat-cs//[PROJECT_ID]"]
+ input_args
+ output_args
+ param_args
Expand Down Expand Up @@ -205,14 +205,14 @@ def add_output_fields(self, cmd_json):

return cmd_args

def add_pydra2app_flags_field(self, cmd_json):
def add_pipeline2app_flags_field(self, cmd_json):

# Add input for dataset name
FLAGS_KEY = "#PYDRA2APP_FLAGS#"
cmd_json["inputs"].append(
{
"name": "Pydra2App_flags",
"description": "Flags passed to `run-pydra2app-pipeline` command",
"description": "Flags passed to `run-pipeline2app-pipeline` command",
"type": "string",
"default-value": (
"--plugin serial "
Expand Down Expand Up @@ -342,4 +342,4 @@ def path2xnatname(cls, path):
return re.sub(r"[^a-zA-Z0-9_]+", "_", path)

COMMAND_INPUT_TYPES = {bool: "bool", str: "string", int: "number", float: "number"}
VALID_FREQUENCIES = (Clinical.session, Clinical.dataset)
VALID_FREQUENCIES = (Clinical.session, Clinical.constant)
6 changes: 3 additions & 3 deletions pydra2app/xnat/deploy.py → pipeline2app/xnat/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
import logging
import json
import xnat
from pydra2app.core.exceptions import Pydra2AppError
from pydra2app.core.utils import extract_file_from_docker_image
from pipeline2app.core.exceptions import Pydra2AppError
from pipeline2app.core.utils import extract_file_from_docker_image


logger = logging.getLogger("pydra2app-xnat")
logger = logging.getLogger("pipeline2app-xnat")

INTERNAL_INPUTS = ("Pydra2App_flags", "PROJECT_ID", "SUBJECT_LABEL", "SESSION_LABEL")

Expand Down
10 changes: 5 additions & 5 deletions pydra2app/xnat/image.py → pipeline2app/xnat/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
from neurodocker.reproenv import DockerRenderer
from frametree.xnat import XnatViaCS
from frametree.core.serialize import ClassResolver, ObjectConverter
from frametree.core.store import DataStore
from pydra2app.core.image import App
from frametree.core.store import Store
from pipeline2app.core.image import App
from .command import XnatCommand


@attrs.define(kw_only=True)
class XnatApp(App):

PIP_DEPENDENCIES = (
"pydra2app-xnat",
"pipeline2app-xnat",
"fileformats-medimage",
"fileformats-medimage-extras",
)
Expand Down Expand Up @@ -121,10 +121,10 @@ def save_store_config(
else:
ip_address = "host.docker.internal" # Mac/Windows local debug
xnat_cs_store_entry["server"] = "http://" + ip_address + ":8080"
DataStore.save_configs(
Store.save_configs(
{"xnat-cs": xnat_cs_store_entry}, config_path=build_dir / "stores.yaml"
)
dockerfile.run(command="mkdir -p /root/.pydra2app")
dockerfile.run(command="mkdir -p /root/.pipeline2app")
dockerfile.run(command=f"mkdir -p {str(XnatViaCS.CACHE_DIR)}")
dockerfile.copy(
source=["./stores.yaml"],
Expand Down
Loading

0 comments on commit 2d8ef00

Please sign in to comment.