Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
include *.txt *.py
include pylocator/camera.png pylocator/image_reader.glade
recursive-include pylocator *.rst *.py
graft doc
graft doc/_static
graft doc/_templates
include README LICENSE
recursive-include pylocator *.py
recursive-include doc *
exclude doc/build/*
global-exclude *~ *.swp
60 changes: 36 additions & 24 deletions README
Original file line number Diff line number Diff line change
@@ -1,38 +1,50 @@
The PyLocator-program
=====================
PyLocator
=========

A little program for localization of EEG-electrodes from MRI-recordings.
Uses VTK for a neat 3d-interface.
PyLocator is a Qt-based visualisation tool for inspecting 3-D NIfTI volumes
and annotating EEG electrodes. The modern port replaces the historic PyGTK
interface with a PySide6/VTK application that runs on contemporary Linux and
Windows systems.

Building the docs
----------------------
Installation
------------

To build the docs you need to have setuptools and sphinx (>=0.5) installed.
Run the command::
Create and activate a Python 3.11 virtual environment and install the runtime
dependencies with::

python setup.py build_sphinx
pip install -r requirements.txt

You can then install PyLocator itself in editable mode while keeping the CLI
entry point available::

The docs are built in the build/sphinx/html directory.
pip install -e .

Running PyLocator
-----------------

Making a source tarball
----------------------------
Once installed you can start the GUI directly from the command line::

To create a source tarball, eg for packaging or distributing, run the
following command::
pylocator <path-to-volume.nii.gz>

python setup.py sdist
When no filename is supplied the application starts with an empty viewport and
provides an **Open…** action to select a NIfTI file. The status bar and the
volume information dock show basic metadata such as voxel spacing and the value
range of the currently loaded dataset.

The tarball will be created in the `dist` directory. This command will
compile the docs, and the resulting tarball can be installed with
no extra dependencies than the Python standard library. You will need
setuptool and sphinx.
Documentation
-------------

Making a release and uploading it to PyPI
------------------------------------------
The Sphinx documentation that ships with the legacy project is still available
and can be built with::

python setup.py build_sphinx

This command is only run by project manager, to make a release, and
upload in to PyPI::
The generated HTML pages are written to ``doc/build``.

python setup.py sdist bdist_egg register upload
Development notes
-----------------

The new Qt port deliberately focuses on volume loading and rendering first.
Legacy features such as marker editing, surface visualisation and undo/redo
have not been migrated yet. Contributions that rebuild these workflows on top
of the modern architecture are very welcome.
6 changes: 3 additions & 3 deletions bin/pylocator
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#! /usr/bin/python
#!/usr/bin/env python3
"""Run pylocator"""

import getopt
Expand All @@ -17,8 +17,8 @@ def main():
def info_exit(option = None, value = None):
"""Print usage information and abort execution"""
if not (option in ["-h", "--help"] or option == None):
print "Wrong argument:", option, ",", value
print USAGE
print("Wrong argument:", option, ",", value)
print(USAGE)
sys.exit(0)
try:
options, args = getopt.getopt(
Expand Down
8 changes: 4 additions & 4 deletions doc/src/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
master_doc = 'index'

# General information about the project.
project = u'PyLocator'
copyright = u'2011-2012, Thorsten Kranz'
project = 'PyLocator'
copyright = '2011-2012, Thorsten Kranz'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
Expand Down Expand Up @@ -168,8 +168,8 @@
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
latex_documents = [
('index', 'pylocator.tex', ur'PyLocator Documentation',
ur'Thorsten Kranz', 'manual'),
('index', 'pylocator.tex', r'PyLocator Documentation',
r'Thorsten Kranz', 'manual'),
]

# The name of an image file (relative to this directory) to place at the top of
Expand Down
112 changes: 30 additions & 82 deletions doc/src/install.rst
Original file line number Diff line number Diff line change
@@ -1,111 +1,59 @@
Installation
============

.. index:: dependencies

Dependencies
-------------
PyLocator relies on a bunch of libraries:

* `VTK <http://www.vtk.org>`_: 3d-visualization
* `nibabel <http://nipy.sourceforge.net/nibabel/>`_: Reading the Nifti-format for MRI data
* `NumPy <http://www.scipy.org>`_: Sophisticated array-types for Python
* `GTK+ <http://www.pygtk.org/>`_: For the GUI.
* `GTK+ OpenGL Extension <http://projects.gnome.org/gtkglext/>`_

On a Debian-like environement, these dependencies can usually be resolved via a simple::
------------

sudo apt-get install python-vtk python-nibabel python-numpy python-gtk2 python-gtkglext1
PyLocator now relies on a modern Qt/VTK stack:

This should prepare your system for PyLocator. On Windows and OS X, things are a little bit
more complicated, but Python distributions like `EPD <http://www.enthought.com/products/epd.php>`_
or `Python(x,y) <http://www.pythonxy.com/>`_ should be helpful here. The main problem will be to
get **gtkgtlext** working. If you have any hints, e.g., binary packages, please let me know.
* `VTK <https://vtk.org>`_ for 3-D visualisation
* `Nibabel <https://nipy.org/nibabel>`_ for reading NIfTI volumes
* `NumPy <https://numpy.org>`_ for numerical data handling
* `PySide6 <https://wiki.qt.io/Qt_for_Python>`_ for the Qt user interface

Depending on your configuration, nibabel has to be downloaded separately.
The recommended way to install these dependencies is via ``pip`` inside a
Python 3.11 virtual environment::

Can you help with detailed instructions for these operating systems? Please tell me!
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Running ``pip install -e .`` afterwards exposes the ``pylocator`` console entry
point and keeps the working copy editable.

How to download
---------------
The source code of PyLocator is kept in a public GIT repository:

http://www.github.com/nipy/PyLocator

.. index:: repository
.. index:: source code

You can simply clone this repository via::

git clone git://github.com/nipy/PyLocator.git

There is a binary package for Debian-like systems (Debian, Ubuntu, ...) available.
It will make sure that all requirements are installed and add an entry to your
applications menu.

.. image:: _static/download_deb.png
:align: center
:target: http://pylocator.thorstenkranz.de/download/pylocator_1.0_all.deb

It is tested with Ubuntu Oneiric and Natty. If you successfully installed it on
other flavours and versions, please let me know.

Alternatively, you can download a tarball that is updated once in a while from
The source code lives on GitHub::

http://pylocator.thorstenkranz.de/download/pylocator_1.0b3.tar.gz
git clone https://github.com/nipy/PyLocator.git

Extract this archive using your preferred archive manager or in a terminal using something like::

tar xfvz pylocator_1.0b3.tar.gz
You can use the repository directly for development or installation.

How to install
---------------
From Debian-package
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Installation of Debian packages should be straight-forward. Usually you just have
to double click the downloaded file and confirm the installation. If you prefer to
work in a terminal, you can::

sudo dpkg -i pylocator_1.0b3_all.deb

That's it!
--------------

From PyPI
^^^^^^^^^^^^^^^^^^^^
PyLocator is registered at PyPI, the Python Package Index. This makes
installation easy also for non-debian systems.
If you have setuptools installed, simply type::
^^^^^^^^^

sudo easy_install PyLocator
The PyPI package can be installed with::

and the setuptools will do the magic for you.
pip install pylocator

From source
^^^^^^^^^^^^^^^^^^^^
Once you obtained the source code, enter the PyLocator-directory and type::

python setup.py build
python setup.py install --user # For per-user installation
# or
sudo python setup.py install # system-wide installation

After these steps, the package *pylocator* should be properly installed. You can then run the program
by running::
^^^^^^^^^^^

python ~/.local/lib/python2.?/site-packages/pylocator/pylocator.py
If you are working from a clone simply run::

in case of a per-user installation or::
pip install -e .

python /usr/local/lib/python2.?/site-packages/pylocator/pylocator.py

or similar in case of a system-wide installation. Replace the *2.?* by your python version number.

This solution isn't perfect yet, I'll clean it up soon. Of course you can create some little bash-script
that calls this for you and put it into ~/bin/pylocator or similar::

#! /bin/bash
python ~/.local/lib/python2.?/site-packages/pylocator/pylocator.py $@
Afterwards the ``pylocator`` command is available on your ``PATH``::

pylocator /path/to/volume.nii.gz

Binary packages
---------------

The historical Debian packages for the GTK version are no longer maintained.
Building native packages for the Qt port is on the roadmap; contributions and
packaging notes are welcome.
6 changes: 3 additions & 3 deletions doc/src/sphinxext/autosummary.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
import sphinx.addnodes, sphinx.roles
from sphinx.util import patfilter

from docscrape_sphinx import get_doc_object
from .docscrape_sphinx import get_doc_object


def setup(app):
Expand Down Expand Up @@ -288,7 +288,7 @@ def _import_by_name(name):
# ... then as MODNAME, MODNAME.OBJ1, MODNAME.OBJ1.OBJ2, ...
last_j = 0
modname = None
for j in reversed(range(1, len(name_parts)+1)):
for j in reversed(list(range(1, len(name_parts)+1))):
last_j = j
modname = '.'.join(name_parts[:j])
try:
Expand All @@ -305,7 +305,7 @@ def _import_by_name(name):
return obj
else:
return sys.modules[modname]
except (ValueError, ImportError, AttributeError, KeyError), e:
except (ValueError, ImportError, AttributeError, KeyError) as e:
raise ImportError(e)

#------------------------------------------------------------------------------
Expand Down
14 changes: 7 additions & 7 deletions doc/src/sphinxext/autosummary_generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@

"""
import glob, re, inspect, os, optparse, pydoc
from autosummary import import_by_name
from .autosummary import import_by_name

try:
from phantom_import import import_phantom_module
from .phantom_import import import_phantom_module
except ImportError:
import_phantom_module = lambda x: x

Expand All @@ -42,7 +42,7 @@ def main():

# read
names = {}
for name, loc in get_documented(args).items():
for name, loc in list(get_documented(args).items()):
for (filename, sec_title, keyword, toctree) in loc:
if toctree is not None:
path = os.path.join(os.path.dirname(filename), toctree)
Expand All @@ -58,8 +58,8 @@ def main():

try:
obj, name = import_by_name(name)
except ImportError, e:
print "Failed to import '%s': %s" % (name, e)
except ImportError as e:
print("Failed to import '%s': %s" % (name, e))
continue

fn = os.path.join(path, '%s.rst' % name)
Expand Down Expand Up @@ -127,8 +127,8 @@ def get_documented_in_docstring(name, module=None, filename=None):
return get_documented_in_lines(lines, module=name, filename=filename)
except AttributeError:
pass
except ImportError, e:
print "Failed to import '%s': %s" % (name, e)
except ImportError as e:
print("Failed to import '%s': %s" % (name, e))
return {}

def get_documented_in_lines(lines, module=None, filename=None):
Expand Down
6 changes: 3 additions & 3 deletions doc/src/sphinxext/comment_eater.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from cStringIO import StringIO
from io import StringIO
import compiler
import inspect
import textwrap
import tokenize

from compiler_unparse import unparse
from .compiler_unparse import unparse


class Comment(object):
Expand Down Expand Up @@ -68,7 +68,7 @@ def __init__(self):
def process_file(self, file):
""" Process a file object.
"""
for token in tokenize.generate_tokens(file.next):
for token in tokenize.generate_tokens(file.__next__):
self.process_token(*token)
self.make_index()

Expand Down
8 changes: 4 additions & 4 deletions doc/src/sphinxext/compiler_unparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
"""

import sys
import cStringIO
import io
from compiler.ast import Const, Name, Tuple, Div, Mul, Sub, Add

def unparse(ast, single_line_functions=False):
s = cStringIO.StringIO()
s = io.StringIO()
UnparseCompilerAst(ast, s, single_line_functions)
return s.getvalue().lstrip()

Expand Down Expand Up @@ -504,7 +504,7 @@ def __binary_op(self, t, symbol):
# Check if parenthesis are needed on left side and then dispatch
has_paren = False
left_class = str(t.left.__class__)
if (left_class in op_precedence.keys() and
if (left_class in list(op_precedence.keys()) and
op_precedence[left_class] < op_precedence[str(t.__class__)]):
has_paren = True
if has_paren:
Expand All @@ -517,7 +517,7 @@ def __binary_op(self, t, symbol):
# Check if parenthesis are needed on the right side and then dispatch
has_paren = False
right_class = str(t.right.__class__)
if (right_class in op_precedence.keys() and
if (right_class in list(op_precedence.keys()) and
op_precedence[right_class] < op_precedence[str(t.__class__)]):
has_paren = True
if has_paren:
Expand Down
Loading