Code Monkey home page Code Monkey logo

pyxnat's Introduction

pyxnat

https://coveralls.io/repos/github/pyxnat/pyxnat/badge.svg?branch=master

https://gitlab.com/xgrg/tweetit/-/raw/master/resources/008-pyxnat-v1.4.gif?inline=false

Where to get it

The source code is currently hosted on GitHub at: https://github.com/pyxnat/pyxnat

Binary installers for the latest released version are available at the Python package index. pyxnat can be installed using pip with the following command:

pip install pyxnat

Dependencies

  • requests v2.20 or higher
  • python-lxml v4.3.2 or higher recommended, earlier versions may work.

For development purposes:

See the full installation instructions for recommended and optional dependencies.

Installation from sources

To install pyxnat from source, from the pyxnat directory (same one where you found this file after cloning the git repo), execute:

python setup.py install

Documentation

The official documentation is hosted at: https://pyxnat.github.io/pyxnat

Running the test suite

Until v1.1 tests were exclusively performed on XNAT Central using a dedicated user account (nosetests). Yet some tests were not allowed to run due to restricted permissions. In v1.1, tests were restructured and were directed to two independent XNAT instances based on permission level. Hence XNAT Central is still used for most tests with read access whereas other tests requiring write permissions are run on a local XNAT instance in a Docker container.

Consequently, running the test suite now requires the following:

  • pytest v7.1+
  • coverage v3.6+
  • docker v18+

Setting up a local Docker-powered XNAT instance may be achieved easily using docker-compose and any available recipe. We recommend the one from the following repository (maintained by the XNAT team). Once the repository cloned, run the following command (possibly as sudo)

docker-compose up -d

After a couple of minutes, the XNAT instance should be up and running locally. You may check it out visiting http://localhost.

The script tests/setup_xnat.py may then be executed to populate the local instance before running the tests.

Finally run the tests with the following command (from the root of the project):

pytest --cov pyxnat

The file .github/workflows/ci.yml (used for CI) features these described steps and may be referred to for further information.

Building the documentation

Building the docs requires to have setuptools and sphinx (v2.0+) installed. Then run the command:

python setup.py build_sphinx

The docs are built in the build/sphinx/html folder.

Contribute to pyxnat

To contribute to pyxnat, first create an account on GitHub. Once this is done, fork the pyxnat repository to have you own repository, clone it using git clone on the computers where you want to work. Make changes in your clone, push them to your GitHub fork, test them on several computers and when you are happy with them, send a pull request to the main repository.

License

BSD 3

pyxnat's People

Contributors

a-detiste avatar bariskanber avatar bud42 avatar chaselgrove avatar ckolbptb avatar davidjj avatar dommcintyre avatar jhuguetn avatar johnflavin avatar just-david avatar karchie avatar koekie avatar locastre avatar marinagrprat avatar nicholsn avatar nrgxnat-bot avatar rherrick avatar roelant001 avatar satra avatar sburns avatar unidesigner avatar vferat avatar xgrg avatar yarikoptic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyxnat's Issues

connecting to central returns incomprehensible error

In [1]: from pyxnat import Interface

In [2]: central = Interface(server="https://central.xnat.org")
User: satra
Password: 
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/software/temp/nipype-tutorial/temp/<ipython-input-2-ed92d8411f01> in <module>()
----> 1 central = Interface(server="https://central.xnat.org")

/software/virtualenvs.EPD/7.2/devpype/lib/python2.7/site-packages/pyxnat/core/interfaces.pyc in __init__(self, server, user, password, cachedir, config, anonymous)
    196 
    197         if self._interactive:
--> 198             self._get_entry_point()
    199 
    200         self.inspect()

/software/virtualenvs.EPD/7.2/devpype/lib/python2.7/site-packages/pyxnat/core/interfaces.pyc in _get_entry_point(self)
    228             except Exception, e:
    229                 if not '/data/JSESSION' in str(e):
--> 230                     raise e
    231 
    232         return self._entry

TypeError: a float is required

SchemaManager class

What is the right way to call the titled class?

Here's what I had:
...
from pyxnat import manage
manage.SchemaManager.add(self=manage.SchemaManager,
url='http://central.xnat.org/schemas/xnat/xnat.xsd')

.../pyxnat/core/manage.py", line 131, in add
etree.fromstring(self._intf._exec(url))
AttributeError: type object 'SchemaManager' has no attribute '_intf'

Btw, where should the .xsd file be put in if I were to add my own customized .xsd?

Thanks in advance!

Latest pypi release not working

New release cannot be used after installing, seems like derivatives ain't being included in the package (setup.py issue). See error:

jhuguet@WS:~/temp/pyxnat$ ipython

In [1]: import pyxnat
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-facebc6aed92> in <module>
----> 1 import pyxnat
...
ImportError: cannot import name 'derivatives' from 'pyxnat.core' (/.../lib/python3.7/site-packages/pyxnat/core/__init__.py)

Receiving empty list, not list of projects

Dear all,

First time using pyxnat, not being able to make it work... what am I doing wrong?

import pyxnat
central = pyxnat.Interface(server="https://myserver.com",
                        user='myusername',
                        password='mypassword')
my_projects = central.select.projects().get()

This returns an empty list, yet the web interface shows me 6 different projects.

What should I have done differently?

Thanks!

Anderson

nosetests deprecation in Debian

Greetings,

For information, the Debian project intends to sunset nosetests, as it is unmaintained for several years, and replaced by other test engines such as pytest. As such, the pyxnat package is affected by Debian Bug #1018603. I thought you might want to be aware of the issue.

For what it's worth, I wrapped up a patch to fix/workaround the issue, but it depends on some previous distribution specific modifications. In any case you might be interested of its existence. I haven't patched all the occurrences of nosetest projects and users to replace by pytest, or some naming more generic though, to keep the change simple enough.

Have a nice day, :)
Étienne.

docs: define resources in the tutorial page

while trying to follow the useful tutorial here:
https://pyxnat.github.io/pyxnat/starters_tutorial.html

I notice the term "resources" is often used, but not defined. I can guess the generic meaning of it (and that it's more than and different from just Files), but it would help to clarify what resources refer to and what it doesn't. Is it all folders and files in a path, or imaging data alone, or something else?

i'd have sent in a PR if I knew the answer but I don't as I am getting started with pyxnat etc .. cc @xgrg

Please tag releases in sync with pypi

Hi,
I'm trying to upgrade the pyxnat Debian package. While pypi offers version 1.2.1.2.post2 as latest version the latest tag on Github is 1.2. On the other hand the download on pypi is incomplete since it does not contain examples and tests. Since we really want examples and tests inside the Debian package I need to decise for the "outdated" version 1.2 which is a suboptimal situation. Thus please keep tags in sync with PyPi.
Thank you, Andreas.

ship or kill pyxnat/examples

ATM 2 examples are provided under pyxnat/examples. 1 of them (central_example.py) seems to be doing something without crashing (but also without printing out anything). The other one (examples.py) is not usable as is due to non-anonymous access

moreover they are killed from the distribution:

$> grep examples MANIFEST.in 
prune pyxnat/examples

Such examples would be very useful if shipped as a part of the documentation, so I would advise to move them outside of the code tree under doc/ and provide in source distribution... otherwise there is no reason to drag them along

Python3 Conversion

Are there any plans making pyxnat python3 compatible in the future? I don't have time in the near future to help with it, but I was curious if this was on the roadmap for pyxnat.

Sphinx documentation: support Sphinx > 1.2b3

The problem isn't actually with distutils. The problem is with sphinx. the newest version of Sphinx errors out when using the version of autosummary built into the pyxnat code base.

using Sphinx version 1.2b3 allow the build to succeed.

When attempting to distribute pyxnat 9.5.4 to pypi i discovered that python 2.7 no longer supports distutils which is used by pyxnat to build and ship to pypi.
distutils should be replace by setuptools.
other projects have had the same growing pain:

macs3-project/MACS#49

Cache lookups fail intermittently because URI is None

To reproduce:

files = interface.select.projects().subjects().experiments().scans().resources().files()
type(files)    # returns pyxnat.core.resources.Files
f = files.fetchone()
type(f)    # returns pyxnat.core.resources.File

For each of the following, I've pasted the bottom of the stack trace

. f.id()

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pyxnat/core/interfaces.pyc in _exec(self, uri, method, body, headers)
365                     print('send: GET CACHE %s' % uri)
366 
--> 367                 info, content = self._http.cache.get(uri
368                                                      ).split('\r\n\r\n', 1)
369 

AttributeError: 'NoneType' object has no attribute 'split'

. f.get_copy()

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pyxnat/core/resources.pyc in get_copy(self, dest)
1786         if not dest:
1787             dest = os.path.join(self._intf._http.cache.cache, 'workspace',
 -> 1788                                 *self._absuri.strip('/').split('/')[1:])
1789 
1790         if not os.path.exists(os.path.dirname(dest)):

AttributeError: 'NoneType' object has no attribute 'strip'

. f.get()

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pyxnat/core/interfaces.pyc in _exec(self, uri, method, body, headers)
365                     print('send: GET CACHE %s' % uri)
366 
--> 367                 info, content = self._http.cache.get(uri
368                                                      ).split('\r\n\r\n', 1)
369 

AttributeError: 'NoneType' object has no attribute 'split'

I also obtained the Files collection using:

files = interface.select('/projects/tp0/subjects/fmrifxnat_S00001/experiments/fmrifxnat_E00001/scans/1/resources//files')

When the pyxnat.core.resource.File methods work, they return:

. f.id()

'3_plane_loc-00003.dcm'

. f.get_copy()

'tmp/[email protected]_8080.xnat/workspace/projects/tp0/subjects/fmrifxnat_S00001/experiments/fmrifxnat_E00001/scans/1/resources/1/files/3_plane_loc-00003.dcm'

. f.get()

'tmp/[email protected]_8080.xnat/3cd148c018ed293920c9671666675d45'

Setup:
pyxnat 0.9.4, Python 2.7.4, Mac OS X 10.8

Resource download does not work in WinOS

Function get() (module: resources.py; class: Resource) for downloading resource contents throws an error when used in WinOS. See a reproducible example below,

Example code:

import pyxnat
xnat = pyxnat.Interface(config='.cfg')
c.select.experiment(experiment).scan('301').resource('NIFTI').get(outdir,extract=True)

Error raised:

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-40-fb7d8dd2d5f5> in <module>
----> 1 r.get(outdir,extract=True)

~\anaconda3\envs\pyxnat\lib\site-packages\pyxnat\core\resources.py in get(self, dest_dir, extract)
   1668                 dest_dir,
   1669                 uri_last(self._uri),
-> 1670                 member.split('files', 1)[1].split(os.sep, 1)[1]
   1671                 )
   1672 

IndexError: list index out of range

Digging a bit on the error cause, seems to be a path-related issue (a mix of Unix/Windows paths). The aforementioned get() function downloads a ZIP file, unzips its contents and flattens the directory tree provided by XNAT.
However, since the ZIP downloaded was created on a Linux platform (XNAT server) it passes in all file names with slashes (not backslashes). As a result, method namelist() from ZipFile module returns a list of Posix-based non-absolute paths used by pyxnat to compose final local paths to be used and manipulated. Those path are not Windows-compliant and some path string operations fail.

Fix proposal

A fix proposal would include using a mechanism (using pathlib?) for automatically translating paths to comply with local OS configuration and keep code working as expected.
However, a deeper refactoring effort regarding paths manipulation and composition is suggested/desired (GSoC?).

Inspect class structure method not working?

Using pyxnat 1.1.0.2 with python3.7 in anaconda on Ubuntu 16.04 LTS , when it is connected to a test xnat server, the output of [my_xnatServer].inspect.structure() gives the following error:

.../pyxnat/core/help.py", line 310, in structure
print('- %s') % 'PROJECTS'
TypeError: unsupported operand type(s) for %: 'NoneType' and 'str'

Any suggestion? This may also help me to understand the rest hierarchy better. Thanks in advance!

pyxnat.Interface() displays IP and xnat password

Whenever I connect to xnat via 'pyxnat.Interface()', my username, ID and password is displayed which is of course an privacy issue when uploading my scripts to github.
Has there yet been an attempt to make it non-verbose / not display the output?

Anaconda PackagesNotFoundError installing `requirements-dev.txt` packages

When setting up a Python 3 virtual environment with Anaconda, specific versions of nose and coverage packages from requirements-dev.txt cannot be found in the main Anaconda channels (defaults and conda-forge). Moreover, I don't see a reason why we should force/restrict the usage of those specific older versions. I suggest removing such restrictions.

is it possible to push data to prearchive ?

Hello pyxnaters, thank you for your work on pyxnat.
I am using pyxnat to automatically load thousands of DICOM data to an XNAT server. I sometimes end up with some corrupted scans (and DICOM ressources) whereas original DICOM data are not corrupted . Ressources and associated Xnat entities created can not be deleted either by pyxnat or XNAT graphical interface (error 500 load ressource).
Hence, I would like to know if it is possible to push data into XNAT prearchive using pyxnat.
Thank you in advance,
Alex

ValueError on Split

If the "xml path" of a constraint contains more than one slash ("/"), core/search.py throws a "ValueError: need more than 1 value to unpack" on line 47.

Changing line 47 from:

element_name, field_ID = column.split('/')

To

 element_name, field_ID = column.split('/',1)

Fixes the issue. This allows the where clause to contain a constraint like:

[('neuroinfo:extendedboldqc/manual/review','!=','COMPLETE')]

Concurrent access results in XNAT write failure

When an imaging pipeline involving many pyxnat write operations is deployed to a cluster environment, the execution fails sporadically in one of several XNAT access tasks app. 80% into the 2-day pipeline. There is no useful error message, simply an indication of which task failed. The problem defies isolation or reproduction. The cause might be due to a concurrency conflict, possibly arising from one of the following causes:

  • the pyxnat config file specifies a temp directory that is not shared by all concurrent jobs, resulting in inconsistent cache content
  • the pyxnat config file specifies a temp directory that is shared by some concurrent jobs, resulting in unsynchronized pyxnat write conflicts across jobs
  • the non-reentrant pyxnat's custom non-http2lib cache is corrupted
  • an XNAT archive directory access race condition

The work-around is to serialize pipeline XNAT to a single node at a time.

Are the above causes plausible?

Is there a best practice for running pyxnat concurrently?

Resource Sharing Issue

The current implementation for subject and experiment sharing does not provide the ability to rename subjects/experiments when sharing. This impacts the linkage between a subject and that subject's affiliated experiments in the project which the subject is shared into.

The code in question can be found in resources.py on lines 1338 and 1372. As a proposed workaround, I have found the following to provide the desired output for my use case:

import pyxnat as xnat
proj = 'project_id'
proj2 = 'project_id_to_share_into'
subj = 'subject_id'
expr = 'experiment_id'
cxn = xnat.Interface('<login_credentials>')
uri1 = '%s/REST/projects/%s/subjects/%s'%(cxn._server,proj,subj)
uri2 = uri1+'/experiments/%s'%(expr)
tail = '/projects/%s'%(proj2)
s1 = uri1+tail
s2 = uri2+tail
parmbase = [('event_reason', 'standard sharing')]
subject_share_parms = parmbase+[('label', 'label_in_shared_project')]
cxn._http.put(s1,params=subject_share_parms)
experiment_share_parms = parmbase+[('label','experiment_label_in_shared_project')]
cxn._http.put(s2,params=experiment_share_parms)

Could tests requiring real server connection auto-skip if no server is available?

Tried to run the tests via

PYTHONPATH=$PWD /usr/bin/nosetests -v --exclude="test_(del_provenance|attr_mset|subject._delete)" pyxnat 

but 40 of them error out seems to be similarly with e.g.

======================================================================
ERROR: pyxnat.tests.attributes_test.test_fancy_resource_create
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/tests/attributes_test.py", line 28, in test_fancy_resource_createxperiment.create(**field_data)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/resources.py", line 383, in create
    parent_element.create(**params)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/resources.py", line 383, in create
    parent_element.create(**params)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/resources.py", line 393, in create
    output = self._intf._exec(create_uri, 'PUT')
  File "/usr/lib/python2.7/dist-packages/requests/adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
ConnectionError: HTTPConnectionPool(host='localhost', port=80): Max retries exceeded with url: /REST/projects/nosetests?xsiType=xnat:projectData (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fe0facce190>: Failed to establish a new connection: [Errno 111] Connection refused',))

IMHO it would be best if tests were decorated to be skipped automatically if there is no XNAT server available on localhost:80 (unless such one is served by the test harness somehow).

Demanding unconditionally having XNAT server (via docker as now) to test complicates testing in scenarios where no docker could be installed/configured for that purpose (thus probably related to #76)

Central XNAT shutdown

Central XNAT will be decommissioned on October 15 2023. Address the collateral effects this might have on pyxnat CI testing.

Merge pull request and update PyPI

Hi Folks,

We are working on a package that depends on pyxnat. To operate correctly, our package requires the changes in my Pull Request that's currently open. If nobody objects in the next day or two, I plan to merge the PR and also update the pyxnat version on PyPI. Also, if anyone has other changes, please submit a PR.

Thanks,
Brian

Incorrect version reported when installing with pip3 from PyPi

Working on upgrading our software to Py3. I will likely fork pyxnat and contribute Py3 versions, however currently when trying to install the current version, it's reporting an incorrect version to pip

$ docker run -it --rm python:3.6 /bin/bash
root@d16657555da8:/# pip install --upgrade pyxnat
Collecting pyxnat
  Downloading https://files.pythonhosted.org/packages/9f/4b/5796b1e2913b5a6424af382c4850c8402e40851157952ff8cbcf11d1436c/pyxnat-1.0.1.0.tar.gz (623kB)
    100% |████████████████████████████████| 624kB 9.7MB/s
Collecting requests (from pyxnat)
  Downloading https://files.pythonhosted.org/packages/ff/17/5cbb026005115301a8fb2f9b0e3e8d32313142fe8b617070e7baad20554f/requests-2.20.1-py2.py3-none-any.whl (57kB)
    100% |████████████████████████████████| 61kB 14.9MB/s
Collecting lxml (from pyxnat)
  Downloading https://files.pythonhosted.org/packages/03/a4/9eea8035fc7c7670e5eab97f34ff2ef0ddd78a491bf96df5accedb0e63f5/lxml-4.2.5-cp36-cp36m-manylinux1_x86_64.whl (5.8MB)
    100% |████████████████████████████████| 5.8MB 5.0MB/s
Collecting chardet<3.1.0,>=3.0.2 (from requests->pyxnat)
  Downloading https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 12.4MB/s
Collecting urllib3<1.25,>=1.21.1 (from requests->pyxnat)
  Downloading https://files.pythonhosted.org/packages/62/00/ee1d7de624db8ba7090d1226aebefab96a2c71cd5cfa7629d6ad3f61b79e/urllib3-1.24.1-py2.py3-none-any.whl (118kB)
    100% |████████████████████████████████| 122kB 11.6MB/s
Collecting idna<2.8,>=2.5 (from requests->pyxnat)
  Downloading https://files.pythonhosted.org/packages/4b/2a/0276479a4b3caeb8a8c1af2f8e4355746a97fab05a372e4a2c6a6b876165/idna-2.7-py2.py3-none-any.whl (58kB)
    100% |████████████████████████████████| 61kB 14.6MB/s
Collecting certifi>=2017.4.17 (from requests->pyxnat)
  Downloading https://files.pythonhosted.org/packages/56/9d/1d02dd80bc4cd955f98980f28c5ee2200e1209292d5f9e9cc8d030d18655/certifi-2018.10.15-py2.py3-none-any.whl (146kB)
    100% |████████████████████████████████| 153kB 12.9MB/s
Building wheels for collected packages: pyxnat
  Running setup.py bdist_wheel for pyxnat ... done
  Stored in directory: /root/.cache/pip/wheels/93/79/12/65c6b6589a79aa1d5874547782f94105cff904c027310c7b15
Successfully built pyxnat
Installing collected packages: chardet, urllib3, idna, certifi, requests, lxml, pyxnat
Successfully installed certifi-2018.10.15 chardet-3.0.4 idna-2.7 lxml-4.2.5 pyxnat-0.0.0 requests-2.20.1 urllib3-1.24.1

Note that is says pyxnat-0.0.0 was installed.

Note this works fine under Docker 2.7:

$ dk run -it --rm python:2.7 /bin/bash
root@af5a1dc6576b:/# pip install --upgrade pyxnat
Collecting pyxnat
  Downloading https://files.pythonhosted.org/packages/9f/4b/5796b1e2913b5a6424af382c4850c8402e40851157952ff8cbcf11d1436c/pyxnat-1.0.1.0.tar.gz (623kB)
    100% |████████████████████████████████| 624kB 2.3MB/s
Collecting requests (from pyxnat)
  Downloading https://files.pythonhosted.org/packages/ff/17/5cbb026005115301a8fb2f9b0e3e8d32313142fe8b617070e7baad20554f/requests-2.20.1-py2.py3-none-any.whl (57kB)
    100% |████████████████████████████████| 61kB 6.9MB/s
Collecting lxml (from pyxnat)
  Downloading https://files.pythonhosted.org/packages/e5/14/f4343239f955442da9da1919a99f7311bc5627522741bada61b2349c8def/lxml-4.2.5-cp27-cp27mu-manylinux1_x86_64.whl (5.8MB)
    100% |████████████████████████████████| 5.8MB 258kB/s
Collecting idna<2.8,>=2.5 (from requests->pyxnat)
  Downloading https://files.pythonhosted.org/packages/4b/2a/0276479a4b3caeb8a8c1af2f8e4355746a97fab05a372e4a2c6a6b876165/idna-2.7-py2.py3-none-any.whl (58kB)
    100% |████████████████████████████████| 61kB 8.9MB/s
Collecting urllib3<1.25,>=1.21.1 (from requests->pyxnat)
  Downloading https://files.pythonhosted.org/packages/62/00/ee1d7de624db8ba7090d1226aebefab96a2c71cd5cfa7629d6ad3f61b79e/urllib3-1.24.1-py2.py3-none-any.whl (118kB)
    100% |████████████████████████████████| 122kB 7.5MB/s
Collecting certifi>=2017.4.17 (from requests->pyxnat)
  Downloading https://files.pythonhosted.org/packages/56/9d/1d02dd80bc4cd955f98980f28c5ee2200e1209292d5f9e9cc8d030d18655/certifi-2018.10.15-py2.py3-none-any.whl (146kB)
    100% |████████████████████████████████| 153kB 6.6MB/s
Collecting chardet<3.1.0,>=3.0.2 (from requests->pyxnat)
  Downloading https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 6.7MB/s
Building wheels for collected packages: pyxnat
  Running setup.py bdist_wheel for pyxnat ... done
  Stored in directory: /root/.cache/pip/wheels/93/79/12/65c6b6589a79aa1d5874547782f94105cff904c027310c7b15
Successfully built pyxnat
Installing collected packages: idna, urllib3, certifi, chardet, requests, lxml, pyxnat
Successfully installed certifi-2018.10.15 chardet-3.0.4 idna-2.7 lxml-4.2.5 pyxnat-1.0.1.0 requests-2.20.1 urllib3-1.24.1
You are using pip version 9.0.1, however version 18.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

Tests won't run any more on Docker-based XNAT instance.

For some reason, Docker-based tests are now giving issues (appeared after c197197 on https://github.com/xgrg/pyxnat).

First Travis returned errors about address begin already used (so binding port 22 would fail.)
(see: https://travis-ci.org/xgrg/pyxnat/jobs/639074174#L10049).
Hence running the Docker-based instance fails, then the tests run properly but CI takes it as a fail (https://travis-ci.org/xgrg/pyxnat/jobs/639074174#L301)

I started cleaning .travis.yml and upgraded docker-compose which was installed from source version 1.8, now is 1.23.

I also forked https://github.com/NrgXnat/xnat-docker-compose to fiddle with the image recipe. Commenting the line binding port 22 would allow the docker-compose line to run without failing (https://travis-ci.org/xgrg/pyxnat/jobs/639103945#L292) but then the Docker-based tests fail for other reasons.
For example, pyxnat cannot fetch a list of projects (https://travis-ci.org/xgrg/pyxnat/jobs/639103945#L562)

At the moment, I left it so that if no project list is found, then Docker-based tests are skipped. This makes CI pass until this issue is taken care of specifically.

Tests run properly on a local workstation.

Byte objects as caught errors are not being parsed

With Python3 migration, failed requests actions return a byte-typed object (and not an string/unicode as was with Python2). Code capturing exceptions from requests-related errors is not taking that change into account and skips parsing error messages. See:

if isinstance(msg_or_exception, (str, unicode)):
# parse the message
msg = msg_or_exception
error = parse_error_message(msg)

We could include the following fragment at the top of the function (or just get rid of the error message parsing feature):

if isinstance(msg_or_exception, byte):  
    msg_or_exception = msg_or_exception.decode()

scan attribute not being set

petScanData/parameters/startTime refuses to be set.

scan.attrs.mset(attr_dict) works if we remove the startTime entry, but mset() fails completely if startTime is present.

How can I best troubleshoot this?

JsonTable undefined in select.scans

Just picked up pyxnat and was going through the tutorial in an ipython session and was confronted by this:

In [13]: CNDA.select.scans(subject_id='CNDA_S08197').get()

NameError                                 Traceback (most recent call last)
/home/tomb/<ipython-input-13-6178429cdc23> in <module>()
----> 1 CNDA.select.scans(subject_id='CNDA_S08197').get()

/projects/schiz/software/LabPython/lib/python2.6/site-packages/pyxnat-0.9.0-py2.6.egg/pyxnat/core/select.pyc in scans(self, project_id, subject_id, subject_label, experiment_id, experiment_label, experiment_type, scan_type, columns, constraints)
    376          ]
    377 
--> 378         return JsonTable(self._intf._get_json(uri)).where(**c)
    379 
    380     def tag(self, name):

NameError: global name 'JsonTable' is not defined

Is this a missing import, a not-yet-implemented feature, or am I trying to use select.scan incorrectly?

Searching for data type without specifying columns does not necessarily return all columns

if no columns attribute is specified during a search with pyxnat.select(datatype).where(conditions) pyxnat defaults to getting a list of columns using pyxnat.inspect(datatype).

However pyxnat.inspect(datatype) does not return the full list of possible columns.

It would be better if pyxnat allowed the search to go without specifying the columns as XNAT's search api would then give all possible columns back.

Additionally, switching search from using CSV to json or XML would be more performant than using the CSV to jsontable functionality it uses now.

Introductions

Hey everyone I added @bud42 to the pyxnat team. As I'm leaving academia in the near future 😥 I wanted someone at Vanderbilt to have access to pyxnat.

XNAT REST API inconsistency derives in unexpected exception when listing Experiment resources

XNAT REST API

Although all the following calls are accepted by XNAT, the REST API does not behave equally with:

/data/projects/PROJ/subjects/SUBJ/experiments/EXP/resources?format=FORMAT
/data/experiments/EXP_UID/resources?format=FORMAT

than with:

/data/projects/PROJ/experiments/EXP/resources?format=FORMAT

Basically, the later does not provide with a list of resources as expected. The REST API simply returns the whole Experiment object information bundled either in XML or JSON (depending on FORMAT). CSV not supported.

pyxnat

Moving to pyxnat, this mentioned inconsistency generates unexpected KeyError exception raise (and frustrations to the user) for calls as follows:

interface = pyxnat.Interface(...)
list(interface.select.project('PROJ').experiment('EXP).resources())

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-83-715e448f4e98> in <module>
----> 1 list(c.select.project('PROJ').experiment('EXP').resources())

/.../envs/pyxnat_baseline/lib/python3.7/site-packages/pyxnat/core/resources.py in __iter__(self)
    689             for res in self._call([id_header] + self._columns):
    690                 try:
--> 691                     eid = unquote(res[id_header])
    692                     if fnmatch(eid, self._pattern):
    693                         klass_name = uri_last(self._cbase

KeyError: 'xnat_abstractresource_id'

Tracking down the problem

The raised error is generated when pyxnat attempts to iterate over the CObject instance (i.e. experiment resources) collected from an Experiment object. This is done by calling Interface._get_json() using the Experiment object URI (an URI that XNAT REST API does not like). As seen below, this method returns an XML object (Experiment) roughly encapsulated in a JSON structure which then generates the KeyError exception as seen above:

interface._get_json('/data/projects/PROJ/experiments/EXP/resources?format=json')

[{'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>': '<xnat:MRSession ID="EXP" project="PROJ" label="EXP_LABEL" ...'},
 {'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>': '<xnat:date>2001-01-01</xnat:date>'},
 {'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>': '<xnat:time>11:11:11</xnat:time>'},
 {'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>': '<xnat:resources>'},
...

Expected JSON object returned:

interface._get_json('/data/experiments/EXP/resources?format=json')

[{'xnat_abstractresource_id': '14180',
  'label': 'ACME',
  'element_name': 'xnat:resourceCatalog',
  'category': 'resources',
  'cat_id': 'EXP',
  'cat_desc': ' ',
  'file_count': '17',
  'file_size': '322649598',
  'tags': '',
  'content': '',
  'format': ''},
 ...

Proposal

As a way to avoid that issue -and perhaps awaiting for a fix in XNAT's REST API itself- I would suggest setting the uri property of any Experiment object instantiated from a Project object to the canonical form /data/experiments/{EXPERIMENT_ID} thus receiving the expected behaviour from the XNAT REST API.

Tests failing with authentication error

As part of the Zurich chapter of Brainhack global, we're looking to package your software for Gentoo Linux. The tests on version 1.0.1.0 fail with:

  • XPathEvalError: Undefined namespace prefix
  • what seems like an authentication error (code 403) - e.g. on the following address, which however works if accessed in the web browser or with wget

Full log here: http://bpaste.net/show/a67cc9ce3b7c

Any idea what can be done about this?

IndexError in SchemaManager.add for central.xnat.org

The following sequence generates an IndexError when attempting to add the xnat.xsd schema:

>>> import pyxnat.core
>>> xnat = pyxnat.core.Interface('http://central.xnat.org', 'bwark', 'yeujEhT9XLssXuoW2bzv')
>>> xnat.manage.schemas.add('xnat.xsd')
Traceback (most recent call last):
  File "/Users/barry/development/.virtualenvs/xnat/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 2746, in run_code
    exec code_obj in self.user_global_ns, self.user_ns
  File "<ipython-input-7-63d9eb19e08c>", line 1, in <module>
    xnat.manage.schemas.add('xnat.xsd')
  File "/Users/barry/development/.virtualenvs/xnat/lib/python2.7/site-packages/pyxnat/core/manage.py", line 136, in add
    self._init()
  File "/Users/barry/development/.virtualenvs/xnat/lib/python2.7/site-packages/pyxnat/core/manage.py", line 114, in _init
    content)[0]
IndexError: list index out of range
>>> xnat.manage.schemas.add('/schemas/xnat/xnat.xsd')
Traceback (most recent call last):
  File "/Users/barry/development/.virtualenvs/xnat/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 2746, in run_code
    exec code_obj in self.user_global_ns, self.user_ns
  File "<ipython-input-8-d9444a631fd6>", line 1, in <module>
    xnat.manage.schemas.add('/schemas/xnat/xnat.xsd')
  File "/Users/barry/development/.virtualenvs/xnat/lib/python2.7/site-packages/pyxnat/core/manage.py", line 136, in add
    self._init()
  File "/Users/barry/development/.virtualenvs/xnat/lib/python2.7/site-packages/pyxnat/core/manage.py", line 114, in _init
    content)[0]
IndexError: list index out of range

Refactor `help.py` informative functions with prints

Two methods from help module just print out informative data that could better be returned as a text string or similar. That would ease its CI testing and validation.

Specifically,

  • structure from Inspector class, see here
  • __call__ from SchemasInspector class, see here

tests failing on a Debian wheezy/sid box

On current master release/0.9.1-51-g0e62fc5 (with my pull request release/0.9.1-52-g9e0d3d5) running via

$> PYTHONPATH=$PWD /usr/bin/nosetests -v --exclude="test_(del_provenance|attr_mset|subject._delete)" pyxnat

some tests fail (I have lxml 2.3.2 if that is of any relevance)

pyxnat.tests.xpass_test.test_find_plus_line ... ok
pyxnat.tests.xpass_test.test_find_token ... ok
pyxnat.tests.xpass_test.test_parse_xnat_pass ... ok
pyxnat.tests.xpath_test.test_xpath_checkout ... ERROR
pyxnat.tests.xpath_test.test_elements ... ERROR
pyxnat.tests.xpath_test.test_keys ... ERROR
pyxnat.tests.xpath_test.test_values ... ERROR
pyxnat.tests.xpath_test.test_element_attrs ... ERROR

======================================================================
ERROR: pyxnat.tests.xpath_test.test_xpath_checkout
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/tests/xpath_test.py", line 7, in test_xpath_checkout
    assert 'OAS1_0001' in central.xpath.subjects() and \
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 114, in subjects
    return self.__call__('//xnat:Subject/attribute::ID')
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 39, in __call__
    return self._tree.xpath(xpath, namespaces=self._nsmap)
  File "lxml.etree.pyx", line 1447, in lxml.etree._Element.xpath (src/lxml/lxml.etree.c:41728)
  File "xpath.pxi", line 321, in lxml.etree.XPathElementEvaluator.__call__ (src/lxml/lxml.etree.c:117734)
  File "xpath.pxi", line 239, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:116911)
  File "xpath.pxi", line 224, in lxml.etree._XPathEvaluatorBase._raise_eval_error (src/lxml/lxml.etree.c:116728)
XPathEvalError: Undefined namespace prefix

======================================================================
ERROR: pyxnat.tests.xpath_test.test_elements
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/tests/xpath_test.py", line 11, in test_elements
    assert 'fs:region' in central.xpath.elements()
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 139, in elements
    for element in self.__call__('//xnat:Subject/descendant::*'):
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 39, in __call__
    return self._tree.xpath(xpath, namespaces=self._nsmap)
  File "lxml.etree.pyx", line 1447, in lxml.etree._Element.xpath (src/lxml/lxml.etree.c:41728)
  File "xpath.pxi", line 321, in lxml.etree.XPathElementEvaluator.__call__ (src/lxml/lxml.etree.c:117734)
  File "xpath.pxi", line 239, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:116911)
  File "xpath.pxi", line 224, in lxml.etree._XPathEvaluatorBase._raise_eval_error (src/lxml/lxml.etree.c:116728)
XPathEvalError: Undefined namespace prefix

======================================================================
ERROR: pyxnat.tests.xpath_test.test_keys
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/tests/xpath_test.py", line 14, in test_keys
    assert 'ID' in central.xpath.keys()
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 119, in keys
    return self.element_keys('xnat:Subject')
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 163, in element_keys
    for element in self.__call__('//%s' % name):
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 39, in __call__
    return self._tree.xpath(xpath, namespaces=self._nsmap)
  File "lxml.etree.pyx", line 1447, in lxml.etree._Element.xpath (src/lxml/lxml.etree.c:41728)
  File "xpath.pxi", line 321, in lxml.etree.XPathElementEvaluator.__call__ (src/lxml/lxml.etree.c:117734)
  File "xpath.pxi", line 239, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:116911)
  File "xpath.pxi", line 224, in lxml.etree._XPathEvaluatorBase._raise_eval_error (src/lxml/lxml.etree.c:116728)
XPathEvalError: Undefined namespace prefix

======================================================================
ERROR: pyxnat.tests.xpath_test.test_values
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/tests/xpath_test.py", line 17, in test_values
    assert 'OAS1_0002' in central.xpath.values('ID')
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 124, in values
    return self.element_values('xnat:Subject', key)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 174, in element_values
    for subject in self.__call__('//%s' % name):
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 39, in __call__
    return self._tree.xpath(xpath, namespaces=self._nsmap)
  File "lxml.etree.pyx", line 1447, in lxml.etree._Element.xpath (src/lxml/lxml.etree.c:41728)
  File "xpath.pxi", line 321, in lxml.etree.XPathElementEvaluator.__call__ (src/lxml/lxml.etree.c:117734)
  File "xpath.pxi", line 239, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:116911)
  File "xpath.pxi", line 224, in lxml.etree._XPathEvaluatorBase._raise_eval_error (src/lxml/lxml.etree.c:116728)
XPathEvalError: Undefined namespace prefix

======================================================================
ERROR: pyxnat.tests.xpath_test.test_element_attrs
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/tests/xpath_test.py", line 20, in test_element_attrs
    assert isinstance(central.xpath.element_attrs('fs:region'), list)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 153, in element_attrs
    for element in self.__call__('//%s' % name):
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/core/xpath_store.py", line 39, in __call__
    return self._tree.xpath(xpath, namespaces=self._nsmap)
  File "lxml.etree.pyx", line 1447, in lxml.etree._Element.xpath (src/lxml/lxml.etree.c:41728)
  File "xpath.pxi", line 321, in lxml.etree.XPathElementEvaluator.__call__ (src/lxml/lxml.etree.c:117734)
  File "xpath.pxi", line 239, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:116911)
  File "xpath.pxi", line 224, in lxml.etree._XPathEvaluatorBase._raise_eval_error (src/lxml/lxml.etree.c:116728)
XPathEvalError: Undefined namespace prefix

======================================================================
FAIL: pyxnat.tests.resources_test.test_get_file
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/tests/resources_test.py", line 159, in test_get_file
    assert os.path.exists(custom)
AssertionError: 
    assert <module 'os' from '/usr/lib/python2.7/os.pyc'>.path.exists('/home/yoh/.tmp/6914adbe815611e29d4700216a237482')
    assert not <module 'os' from '/usr/lib/python2.7/os.pyc'>.path.exists('/home/yoh/.tmp/[email protected]/970603a3479cbb338c0c173e92ccdb6c')
    <File Object> hello.txt.get()
>>  assert <module 'os' from '/usr/lib/python2.7/os.pyc'>.path.exists('/home/yoh/.tmp/6914adbe815611e29d4700216a237482')
    <module 'os' from '/usr/lib/python2.7/os.pyc'>.remove('/home/yoh/.tmp/6914adbe815611e29d4700216a237482')


======================================================================
FAIL: pyxnat.tests.resources_test.test_get_dir_file
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/yoh/deb/gits/pkg-exppsy/pyxnat/pyxnat/tests/resources_test.py", line 184, in test_get_dir_file
    assert os.path.exists(custom)
AssertionError: 
    assert <module 'os' from '/usr/lib/python2.7/os.pyc'>.path.exists('/home/yoh/.tmp/69e1c33a815611e29d4700216a237482')
    assert not <module 'os' from '/usr/lib/python2.7/os.pyc'>.path.exists('/home/yoh/.tmp/[email protected]/28c4701fbe69c6677c6c4fff0f3cbff6')
    <File Object> dir/hello.txt.get()
>>  assert <module 'os' from '/usr/lib/python2.7/os.pyc'>.path.exists('/home/yoh/.tmp/69e1c33a815611e29d4700216a237482')
    <module 'os' from '/usr/lib/python2.7/os.pyc'>.remove('/home/yoh/.tmp/69e1c33a815611e29d4700216a237482')


Name                        Stmts   Miss  Cover   Missing
---------------------------------------------------------
pyxnat                         19      0   100%   
pyxnat.core                     8      0   100%   
pyxnat.core.array              51     24    53%   25, 30, 33, 36, 41, 44, 167-190
pyxnat.core.attributes         56     10    82%   43-47, 100-109, 146, 185
pyxnat.core.cache             201     69    66%   29, 31, 38-47, 78-79, 113, 127-128, 138-145, 148-149, 159, 191, 198-204, 207, 210, 220-223, 250, 255-264, 279-292, 298, 304-312, 322, 330, 336-345, 356, 383-384, 386-387
pyxnat.core.downloadutils      51     44    14%   32-37, 87-150
pyxnat.core.errors             63     29    54%   12-24, 27-43, 54-60, 64, 66, 72-75
pyxnat.core.help              279    163    42%   7-8, 62-65, 195, 287, 293-313, 340, 386-403, 406-424, 428-449, 452-478, 487-512, 515-516, 519-520, 523-524, 527-528, 531-552, 555-578, 581-602, 606-608, 664-681, 684-708
pyxnat.core.httputil           14      0   100%   
pyxnat.core.interfaces        235     82    65%   102-103, 119, 125-134, 143, 147, 152, 155, 199, 204, 213-217, 228-231, 247, 254, 262-264, 299, 312, 326-343, 349-355, 369-371, 413, 426, 436-438, 445, 467-482, 497-519, 522, 525, 531-532
pyxnat.core.jsonutil          152     26    83%   15, 30, 41, 60-77, 81, 86, 119-126, 142, 159, 240, 291-292, 300-301, 319
pyxnat.core.manage            102     56    45%   56, 66-89, 104-116, 120-121, 136-147, 153-154, 201, 211, 223, 236, 250, 269-279, 294-297, 306-308, 317
pyxnat.core.pathutil           17     15    12%   4-23
pyxnat.core.provenance        126     30    76%   47-48, 51, 54, 72-74, 91, 94, 106-109, 130-138, 141-149, 240, 291-304
pyxnat.core.resources         850    366    57%   54-57, 144, 150, 153, 178-183, 186, 200, 209, 220, 289-312, 319-323, 363, 367, 372-384, 405, 418, 443-448, 455-460, 465-468, 541-551, 554, 604, 623, 650-653, 667-680, 683-684, 696-713, 716-739, 745-746, 761, 764-797, 830-849, 856-861, 866-869, 901, 903-906, 908-909, 913, 956, 962, 967-968, 1009, 1024, 1035-1037, 1149, 1152-1154, 1160-1171, 1206-1290, 1299-1322, 1338, 1349, 1359, 1372, 1383, 1393, 1398, 1404, 1409, 1423-1434, 1452, 1463, 1473, 1477, 1483, 1487, 1490, 1516, 1556-1612, 1621-1633, 1641-1644, 1651, 1658, 1666-1668, 1674-1676, 1716, 1749, 1784, 1788, 1829-1833, 1860, 1863-1865, 1911-1917, 1927, 1932, 1937, 1947, 1967, 1974-1975, 1978-1979, 1985, 1992-1993, 1996-1997, 2003, 2010-2011, 2014-2015, 2022, 2033, 2045, 2070-2078, 2098, 2118
pyxnat.core.schema             49     36    27%   69-122, 125-127, 133-140, 147
pyxnat.core.search            260    111    57%   140, 186-220, 223-242, 245-286, 317-322, 375, 409-410, 413-421, 448-449, 496-499, 519, 552-569, 588-609, 617, 681, 683-687, 689-690, 694, 703, 718-719, 722, 728
pyxnat.core.select            169     27    84%   76, 116, 132, 178, 184-185, 266-268, 280-282, 287-289, 292-294, 297, 319-322, 325, 337, 351, 361-366, 370
pyxnat.core.tags               91     65    29%   18-19, 23-31, 34, 37, 40, 43-44, 50-53, 57, 60-64, 67-74, 77-78, 81, 84-88, 91-97, 100-107, 110-116, 119-124
pyxnat.core.uriutil            77     17    78%   60-67, 108-112, 122-134
pyxnat.core.users              23      2    91%   80-82
pyxnat.core.xpass              44      5    89%   6, 10-15
pyxnat.core.xpath_store        92     42    54%   12-19, 37, 46-52, 59-62, 71-86, 101-102, 129, 140-146, 154-156, 164-167, 175-177, 182
---------------------------------------------------------
TOTAL                        3029   1219    60%   
----------------------------------------------------------------------
Ran 91 tests in 836.030s

FAILED (errors=5, failures=2)

draw subinstance not working

Just curious how it would look as suggested from Advanced tutorial:

.../pyxnat/core/help.py", line 505, in experiments
self._draw_rest_resource(graph, save=None)
.../pyxnat/core/help.py", line 521, in _draw_rest_resource
pos = nx.graphviz_layout(graph, prog='twopi', args='')
AttributeError: module 'networkx' has no attribute 'graphviz_layout'

nosetests xnat central password expired

I tried to run the tests of pyxnat, but the password of the nosetests user on xnat central was expired. I tried to set it to the same password but xnat central doesn't permit this.
Next step was to try and set another password and then change back, of course this isn't permitted either ;)

So, long story short: the new password is "nose".

Maybe you can get one of the xnat central admins to set the password back to the original one and make sure the password for this account cannot expire?

Sorry for any inconvenience!

SSLE error (cached)

Working of an example BIDS type upload for the Cam-CAN data (https://issues.dpuk.org/dpuk/node/-/snippets/10) I've been trying to upload some data for a new project, but when running a script very similar to that example (the only change being the url and project names) I get an SSLE error:

ssl.SSLCertVerificationError: ("hostname 'xnat_final.cam.ac.uk' doesn't match 'xnat_test.cam.ac.uk'",)

This seems to suggest my prior test-run (on xnat_test.cam.ac.uk) is cached somewhere and its still trying to use an old url even though that url isn't anywhere in my code..? Is there some command to either flush the cache or force it to use the new url?

IndexError: list index out of range

Under some circumstances, core/search.py will raise an IndexError when XNAT returns data but incomplete row header information. This can happen when, for example, rows are returned but one or more columns were requested which do not exist in the queried XNAT, or when the column headers to not match the specified requested columns (due to nested schemas derived from schemas in different namespaces). Wrapping the where clause in a try / except does not help as this would result in an empty data set when in fact rows were returned by XNAT. To fix this / enable this, one can change lines 710-717 from:

    for column in self._columns:
        headers_of_interest.append(
            difflib.get_close_matches(
                column.split(self._row + '/')[0].lower() \
                    or column.split(self._row + '/')[1].lower(),
                headers)[0]
            )

To:

    for column in self._columns:
        try:
            headers_of_interest.append(
                difflib.get_close_matches(
                    column.split(self._row + '/')[0].lower() \
                        or column.split(self._row + '/')[1].lower(),
                    headers)[0]
                )
        except IndexError:
            headers_of_interest.append('unknown')

central.select('//subjects').where(constraints).get() returns empty when Nresults=1

I'm a novice in working with pyXNAT, so sorry if this is expected behavior and for not suggesting a fix.

central.select('//subjects').where(constraints).get() returns empty when only one subject fits the constraints, for more subjects it works. To test if my constraints were correct I tried:

experiments=interface.select('xnat:subjectData', ['xnat:subjectData/SUBJECT_ID']).where(constraints).data

Which did return the intended subject in a 1:1 jsonTable.

Performance issue

Performance issue found when attempting to get a list of file labels of a Resource object.

Using EObject label() method generates a per-file new GET request to the whole list of resource files which -in my opinion- is highly redundant and rather slow when resource has lots of files (see test below).

Performance test with ASHS resource of ~790 files using label() method:

import timeit
code1 = """
import pyxnat
c = pyxnat.Interface(config='.pyxnat.cfg')
flist = c.select.experiment('ACME_E00001').resource('ASHS').files()
fnamelist = [f.label() for f in flist]
"""
elapsed_time = timeit.timeit(code1, number=10)/10
print(elapsed_time)

67.44406228000298

Same test using _urn private property (see here):

import timeit
code2 = """
import pyxnat
c = pyxnat.Interface(config='.pyxnat.cfg')
flist = c.select.experiment('ACME_E00001').resource('ASHS').files()
fnamelist = [f._urn for f in flist]
"""
elapsed_time = timeit.timeit(code2, number=10)/10
print(elapsed_time)

0.18539366999757476

Issue with resource.file(myfile).get() if myfile is in a sub-directory

Dear pyxnat,

I try to download resource files for a given subject/experiment as follows:

  1. I make a list of all the available files: files = interface.project(WW).subject(XX).experiment(YY).resource(ZZ).files().get()
  2. Then I use this list of file names to actually get the files:
    for filename in files:
    interface.project(WW).subject(XX).experiment(YY).resource(ZZ).file(filename).get(pathtowhatever/filename)

The problem is that some files are located in a subdirectory at the resources/resource_label level and thus the request to get the file crashes:
pyxnat.core.errors.DataError: Cannot get file: does not exists

Is there a way round?

Thank you in advance for your help.

Regards

file.get_copy() not working if not preceded by file.get()

Hi,

thanks for the wonderful library. I think I might have discovered an issue.
When calling file.get_copy(), I receive the error:

*self._absuri.strip('/').split('/')[1:])
AttributeError: 'NoneType' object has no attribute 'strip'"

When diving into the code, you see there is indeed no check self._absuri == None. In contrary with file.get() where there is such a check.

I am not sure wether this is intended behavior, but this leads to strange code if you want to download file with get_copy(), e.g.
pathz=[]
for f in recon.out_resource('NIFTI').files():
print "Downloading files!"
f.get()
pathz.append(f.get_copy())

I hope this was useful information.
Thanks
Felix

incorrect authentication interface

Dear pyxnat

it appears that there is a problem with xnat authentication mechanism.

the mechanism asks for a username and a password, but xnat supports several user databases for
authentication purposes. The internal xnat logic fails if several databases contain same username.
As far as I can tell, this is an internal design flaw of XNAT and one cannot expect this to be fixed.

However, the HTTP FORM POST interface (which is used by web browsers) works correctly.

i suggest pyxnat implements this interface.
Here is an example how to use it with curl

curl -c COOKIE_FILE
--data-urlencode login_method=SERVICE
--data-urlencode j_username=USER
--data-urlencode j_password=PASS
'http://url.of.xnat.server/xnat/j_spring_security_check'

SERVICE is the name of the authentication database...

Best wishes and thank you for your help

LF

Failing to download data

Hello,

I have been using pyxnat to query an xnat database (searching for all MPRAGE scans) and then the download would take place in another platform (nipype). Now I would like to download the data using pyxnat and I am getting into trouble.

This is my code:

#!/usr/bin/env python
import sys, os, getpass                           
from pyxnat import Interface

userName = raw_input('Type XNAT User Name: ')
passWord = getpass.getpass('Type XNAT Password: ')
projectID = raw_input('Type XNAT Project ID: ')
server = 'SERVER'

print 'INPUT'
print 'Server: ', server
print 'Username: ', userName
print 'Password: ', ''.join(['*']*len(passWord))
print 'ProjectID: ', projectID 
	
central = Interface(server=server, user=userName, password=passWord, cachedir='/home/cache_dir/')
subjects = central.select.project(projectID).subjects().get()
allSessions = []
number_subjects = 0

# browse through project, collect subjects/sessions/scans
for i, subject in enumerate(subjects):
	label = central.select.project(projectID).subject(subject).label()
	print label, ('%i/%i' % (i+1, len(subjects)))
	sessions = central.select.project(projectID).subjects(subject).experiments().get()
	allSessions.append(sessions)

subjectCounter = 0
for s, subjectID in enumerate(subjects):
	subjectLabel = central.select.project(projectID).subject(subjectID).label()
	for experimentID in allSessions[s]:


		# retrieve scan numbers that fit specific label
		scans = central.select.project(projectID).subject(subjectID).experiments(experimentID).scans()
		scanIDs = scans.get()
		coll = central.select.project(projectID).subject(subjectID).experiments(experimentID)
		for ese in coll:
			explab = ese.attrs.get('label')
		scanNumber_MPRAGE = []
		num=0
		for s in scans:
			test = s.attrs.get('type')
			if 'MPRAGE'==test:
				scanNumber_mIP.append(scanIDs[num])
			num+=1
		if len(scanNumber_MPRAGE) == 1:
			print "Running nipype with parameters scanNumber_mIP=" + str([scanNumber_MPRAGE[0]])

			number_nipype_subjects+=1
			filenames = central.select.project(projectID).subject(subjectID).experiments(experimentID).scans(scanNumber_MPRAGE[0]).resources('*').files('*.dcm')
			filenamesID=filenames.get()


print "The total number of MPRAGE datasets found is = " + str(number_subjects)


This code runs without error and the print output tells me that the correct number of scans was found. However the cache dir is empty and there are no dcm files there. Printing the filenamesID variable to the screen gives the list of the correct dcm files, but they do not seem to be saved anywhere. I also tried

filenamesID=filenames.get_copy('/home/cache_dir/')  

but this gave an error ('Files object has no attribute get_copy'). Would anyone know what I am doing wrong?

Many thanks,

Maria.

In [12]: filenamesID
Out[12]: 
['1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-98-15h3n8c.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-70-13l21fc.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-24-akykqb.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-86-sluf4k.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-121-1mgkdr.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-42-1chwje0.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-65-o61yjy.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-48-1fiwzf7.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-3-1m929iq.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-38-17slen4.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-28-1m95wyv.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-58-17q60q5.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-63-mciing.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-71-jr8wa6.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-92-koxh5g.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-31-65tqj5.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-19-1owd7kj.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-23-1wahcsu.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-53-47jvn2.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-30-1upm8yu.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-99-j67ffb.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-47-15zooo6.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-52-1eqsx7a.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-20-15117ps.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-50-1w4t827.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-35-18n1bpl.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-100-1v82lkl.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-33-o6uucq.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-11-1ydp6yv.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-113-1tat6ml.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-110-r3zqi.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-85-ykb1lg.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-102-1r1jzle.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-61-wgdo4v.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-54-8hxdn4.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-27-ezf62.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-5-1oeghma.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-25-aa1hv0.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-88-ajf68a.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-112-vrpgs.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-29-6e75w.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-101-dawsnm.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-114-1qzwxir.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-66-1eqwnhz.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-8-d84unb.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-59-fuhfhv.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-15-1p7se7m.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-22-pm3ig7.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-111-f0sifh.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-82-bi1gkt.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-78-1gfsodr.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-34-1nq5dgo.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-49-dly30r.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-60-1c0jca5.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-45-wwxv39.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-95-6tux1w.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-117-sgjrmq.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-75-1a7c2ka.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-69-cebo4.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-68-2nakry.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-43-6sknu0.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-7-1dpyvv6.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-56-ys8r89.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-62-2heky.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-106-cygxiv.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-74-1ky5pn7.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-84-obmqz7.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-57-1fabubu.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-21-1h42q6d.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-37-dipzfm.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-83-ama2nk.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-16-4xehbo.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-109-boifnv.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-13-1hxfe2e.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-93-yqjwb4.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-44-i67q03.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-17-1ecpt5z.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-108-1l4mrn2.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-90-1q87ys1.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-67-4h57hl.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-12-17g3uiz.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-105-1j2572.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-103-z1h3fa.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-76-bnlshi.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-64-1etjp69.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-36-15e1ttd.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-94-78koky.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-79-1v6itgx.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-81-clyzv9.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-73-1wbb4x0.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-72-167i2d6.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-91-slmkdm.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-119-alhudm.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-96-ruziug.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-116-102mus5.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-104-1sduf89.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-4-nkxi21.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-55-14qowsx.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-6-pk4119.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-118-oqincb.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-32-1riylxr.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-40-qel3s7.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-97-1mp8tct.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-9-mrd5ec.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-80-2jwt82.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-2-p44yxc.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-14-1v3wox6.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-115-16gpcj3.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-51-1ses3rs.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-77-qt1884.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-39-16wu0pv.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-46-irkbam.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-87-rq317w.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-18-1ps4lhs.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-89-nt8pz5.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-10-1n8qxao.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-1-19xk7kh.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-107-1xdik5o.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-120-1v0jgzu.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-41-lqgqpe.dcm',
 '1.3.12.2.1107.5.2.36.40436.30000016102815570423100000022-18-26-711zys.dcm']

Wrong `cache_dir` variable (session_mirror.py)

Wrong use of scan_cache_dir path variable at copy_session() when traversing across session resources at mirroring process. See here:

res_cache_dir = op.join(scan_cache_dir, res_label)

Throwing the following error,

Traceback (most recent call last):
  File "sessionmirror.py", line 711, in <module>
    main(args)
  File "sessionmirror.py", line 705, in main
    copy_session(src_sess, dst_sess, '/tmp')
  File "sessionmirror.py", line 491, in copy_session
    res_cache_dir = op.join(scan_cache_dir, res_label)
UnboundLocalError: local variable 'scan_cache_dir' referenced before assignment

Fix proposal

Use session_cache_dir instead.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.