summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOnderwaater <onderwaa@esrf.fr>2015-11-25 14:19:56 +0100
committerOnderwaater <onderwaa@esrf.fr>2015-11-25 14:19:56 +0100
commit2e072ce50ecffd6faebf4a597da7795409543228 (patch)
tree92186a3ca4f88c73be66cd7a0fc72b922a8631bf
parentc8c1c339e6ccd330ba7c7e5e1e5c0423e6ff32de (diff)
sixs backend commit
-rw-r--r--binoculars/backends/sixs.py403
-rw-r--r--binoculars/plot.py6
-rwxr-xr-xbinoculars/space.py2
-rwxr-xr-xbinoculars/util.py11
-rwxr-xr-xscripts/binoculars (renamed from binoculars.py)17
-rwxr-xr-x[-rw-r--r--]scripts/binoculars-fitaid (renamed from binoculars-fitaid.py)31
-rwxr-xr-xscripts/binoculars-gui (renamed from binoculars-gui.py)28
-rwxr-xr-xscripts/binoculars-processgui (renamed from binoculars-processgui.py)28
-rwxr-xr-x[-rw-r--r--]scripts/binoculars-server (renamed from binoculars-server.py)34
-rw-r--r--setup.py29
10 files changed, 551 insertions, 38 deletions
diff --git a/binoculars/backends/sixs.py b/binoculars/backends/sixs.py
new file mode 100644
index 0000000..ae86bb7
--- /dev/null
+++ b/binoculars/backends/sixs.py
@@ -0,0 +1,403 @@
+import sys
+import os
+import itertools
+import numpy
+import tables
+import math
+
+from pyFAI.detectors import ALL_DETECTORS
+from math import cos, sin
+from collections import namedtuple
+from numpy.linalg import inv
+from networkx import DiGraph, dijkstra_path
+
+from .. import backend, errors, util
+
+
+class realspace(backend.ProjectionBase):
+ # scalars: mu, theta, [chi, phi, "omitted"] delta, gamR, gamT, ty, wavelength
+ # 3x3 matrix: UB
+ def project(self, index, dataframe, pixels):
+ return pixels[1], pixels[2]
+ #return numpy.meshgrid(numpy.arange(pixels[0].shape[1]), numpy.arange(pixels[0].shape[0]))
+
+ def get_axis_labels(self):
+ return 'x', 'y'
+
+class Pixels(backend.ProjectionBase):
+ # scalars: mu, theta, [chi, phi, "omitted"] delta, gamR, gamT, ty, wavelength
+ # 3x3 matrix: UB
+ def project(self, index, dataframe, pixels):
+ return numpy.meshgrid(numpy.arange(pixels[0].shape[1]), numpy.arange(pixels[0].shape[0]))
+
+ def get_axis_labels(self):
+ return 'x', 'y'
+
+
+
+class HKLProjection(backend.ProjectionBase):
+ # scalars: mu, theta, [chi, phi, "omitted"] delta, gamR, gamT, ty, wavelength
+ # 3x3 matrix: UB
+ def project(self, index, dataframe, pixels):
+ # put the detector at the right position
+
+ UB = dataframe.diffractometer.ub
+
+ s_axes = rotation_axes(dataframe.diffractometer.axes.graph,
+ dataframe.diffractometer.axes.sample)
+ d_axes = rotation_axes(dataframe.diffractometer.axes.graph,
+ dataframe.diffractometer.axes.detector)
+
+ # the ki vector should be in the NexusFile or easily extracted
+ # from the hkl library.
+ ki = [1, 0, 0]
+ k = 2 * math.pi / dataframe.source.wavelength
+ values = dataframe.mu[index], dataframe.omega[index], dataframe.delta[index], dataframe.gamma[index]
+ s_values = values[0], values[1]
+ d_values = values[0], values[2], values[3]
+ R = reduce(numpy.dot, (zip_with(M, numpy.radians(s_values), s_axes)))
+ P = reduce(numpy.dot, (zip_with(M, numpy.radians(d_values), d_axes)))
+ RUB_1 = inv(numpy.dot(R, UB))
+ RUB_1P = numpy.dot(RUB_1, P)
+ # rotate the detector around x of 90 degrees
+ RUB_1P = numpy.dot(RUB_1P, M(math.pi/2., [1, 0, 0]))
+ kf = normalized(pixels, axis=0)
+ hkl_f = numpy.tensordot(RUB_1P, kf, axes=1)
+ hkl_i = numpy.dot(RUB_1, ki)
+ hkl = hkl_f - hkl_i[:, numpy.newaxis, numpy.newaxis]
+
+ h,k,l = hkl * k
+
+ return (h, k, l)
+
+ def get_axis_labels(self):
+ return 'H', 'K', 'L'
+
+class HKProjection(HKLProjection):
+ def project(self, index, dataframe, pixels):
+ h,k,l = super(HKProjection, self).project(index, dataframe, pixels)
+ return h,k
+
+ def get_axis_labels(self):
+ return 'H', 'K'
+
+
+
+def get_nxclass(hfile, nxclass, path="/"):
+ """
+ :param hfile: the hdf5 file.
+ :type hfile: tables.file.
+ :param nxclass: the nxclass to extract
+ :type nxclass: str
+ """
+ for node in hfile.walk_nodes(path):
+ try:
+ if nxclass == node._v_attrs['NX_class']:
+ return node
+ except KeyError:
+ pass
+ return None
+
+Axes = namedtuple("Axes", ["sample", "detector", "graph"])
+
+Rotation = namedtuple("Rotation", ["axis", "value"])
+
+
+def get_axes(name):
+ """
+ :param name: the diffractometer name
+ :type name: str
+ """
+ sample = []
+ detector = []
+ graph = DiGraph()
+ if name == 'ZAXIS':
+ # axis
+ graph.add_node("mu", transformation=Rotation([0, 0, 1], 0))
+ graph.add_node("omega", transformation=Rotation([0, -1, 0], 0))
+ graph.add_node("delta", transformation=Rotation([0, -1, 0], 0))
+ graph.add_node("gamma", transformation=Rotation([0, 0, 1], 0))
+
+ # topology
+ graph.add_edges_from([("mu", "omega"),
+ ("mu", "delta"), ("delta", "gamma")])
+
+ sample = dijkstra_path(graph, "mu", "omega")
+ detector = dijkstra_path(graph, "mu", "gamma")
+
+ return Axes(sample, detector, graph)
+
+
+Diffractometer = namedtuple('Diffractometer',
+ ['name', # name of the hkl diffractometer
+ 'ub', # the UB matrix
+ 'axes']) # the Axes namedtuple
+
+
+def get_diffractometer(hfile):
+ """ Construct a Diffractometer from a NeXus file """
+ node = get_nxclass(hfile, 'NXdiffractometer')
+
+ name = node.type[0][:-1]
+ ub = node.UB[:]
+ axes = get_axes(name)
+
+ return Diffractometer(name, ub, axes)
+
+
+Sample = namedtuple("Sample", ["a", "b", "c",
+ "alpha", "beta", "gamma",
+ "ux", "uy", "uz", "graph"])
+
+
+def get_sample(hfile):
+ graph = DiGraph()
+ graph.add_node("ux", transformation=Rotation([1, 0, 0], 0))
+ graph.add_node("uy", transformation=Rotation([0, 1, 0], 0))
+ graph.add_node("uz", transformation=Rotation([0, 0, 1], 0))
+ graph.add_edges_from([("ux", "uy"),
+ ("uy", "uz")])
+
+ return Sample(1.54, 1.54, 1.54, 90, 90, 90, 0, 0, 0, graph)
+
+
+Detector = namedtuple("Detector", ["name"])
+
+
+def get_detector(hfile):
+ return Detector("imxpads140")
+
+Source = namedtuple("Source", ["wavelength"])
+
+
+def get_source(hfile):
+ wavelength = get_nxclass(hfile, 'NXmonochromator').wavelength[0]
+ return Source(wavelength)
+
+
+DataFrame = namedtuple("DataFrame", ["diffractometer",
+ "sample", "detector", "source",
+ "mu", "omega", "delta", "gamma",
+ "image", "graph"])
+
+
+def dataframes(hfile, data_path=None):
+ diffractometer = get_diffractometer(hfile)
+ sample = get_sample(hfile)
+ detector = get_detector(hfile)
+ source = get_source(hfile)
+ graph = DiGraph()
+ # this should be generalized
+ for g in [diffractometer.axes.graph, sample.graph]:
+ graph.add_nodes_from(g)
+ graph.add_edges_from(g.edges())
+ # connect the sample with the right axis.
+ graph.add_edge("omega", "ux")
+
+ for group in hfile.get_node('/'):
+ scan_data = group._f_get_child("scan_data")
+ dataframe = {
+ "diffractometer": diffractometer,
+ "sample": sample,
+ "detector": detector,
+ "source": source,
+ "graph": graph,
+ }
+
+ # now instantiate the pytables objects
+ for key, value in data_path.iteritems():
+ child = scan_data._f_get_child(value)
+ dataframe[key] = child
+
+ yield DataFrame(**dataframe)
+
+
+def M(theta, u):
+ """
+ :param theta: the axis value in radian
+ :type theta: float
+ :param u: the axis vector [x, y, z]
+ :type u: [float, float, float]
+ :return: the rotation matrix
+ :rtype: numpy.ndarray (3, 3)
+ """
+ c = cos(theta)
+ one_minus_c = 1 - c
+ s = sin(theta)
+ return numpy.array([[c + u[0]**2 * one_minus_c,
+ u[0] * u[1] * one_minus_c - u[2] * s,
+ u[0] * u[2] * one_minus_c + u[1] * s],
+ [u[0] * u[1] * one_minus_c + u[2] * s,
+ c + u[1]**2 * one_minus_c,
+ u[1] * u[2] * one_minus_c - u[0] * s],
+ [u[0] * u[2] * one_minus_c - u[1] * s,
+ u[1] * u[2] * one_minus_c + u[0] * s,
+ c + u[2]**2 * one_minus_c]])
+
+
+def rotation_axes(graph, nodes):
+ """
+ :param graph: descrition of the diffractometer geometry
+ :type graph: DiGraph
+ :param nodes: list of the nodes to use
+ :type nodes: list(str)
+ :return: the list of the rotation axes expected by zip_with
+ """
+ return [graph.node[idx]["transformation"].axis for idx in nodes]
+
+
+def zip_with(f, *coll):
+ return itertools.starmap(f, itertools.izip(*coll))
+
+
+def rotation_matrix(values, axes):
+ """
+ :param values: the rotation axes values in radian
+ :type values: list(float)
+ :param axes: the rotation axes
+ :type axes: list of [x, y, z]
+ :return: the rotation matrix
+ :rtype: numpy.ndarray (3, 3)
+ """
+ return reduce(numpy.dot, (zip_with(M, values, axes)))
+
+def get_ki(wavelength):
+ """
+ for now the direction is always along x
+ """
+ TAU = 2 * math.pi
+ return numpy.array([TAU / wavelength, 0, 0])
+
+def normalized(a, axis=-1, order=2):
+ l2 = numpy.atleast_1d(numpy.linalg.norm(a, order, axis))
+ l2[l2 == 0] = 1
+ return a / numpy.expand_dims(l2, axis)
+
+class SIXS(backend.InputBase):
+ # OFFICIAL API
+
+ dbg_scanno = None
+ dbg_pointno = None
+
+ def generate_jobs(self, command):
+ scans = util.parse_multi_range(','.join(command).replace(' ', ','))
+ if not len(scans):
+ sys.stderr.write('error: no scans selected, nothing to do\n')
+ for scanno in scans:
+ util.status('processing scan {0}...'.format(scanno))
+ if self.config.pr:
+ pointcount = self.config.pr[1] - self.config.pr[0] + 1
+ start = self.config.pr[0]
+ else:
+ # just open the file in order to extract the number of step.
+ with tables.open_file(self.get_filename(scanno), 'r') as scan:
+ start = 0
+ pointcount = get_nxclass(scan, "NXdata").UHV_MU.shape[0]
+ if pointcount > self.config.target_weight * 1.4:
+ for s in util.chunk_slicer(pointcount, self.config.target_weight):
+ yield backend.Job(scan=scanno, firstpoint=start+s.start, lastpoint=start+s.stop-1, weight=s.stop-s.start)
+ else:
+ yield backend.Job(scan=scanno, firstpoint=start, lastpoint=start+pointcount-1, weight=pointcount)
+
+ def process_job(self, job):
+ super(SIXS, self).process_job(job)
+ with tables.open_file(self.get_filename(job.scan), 'r') as scan:
+ self.metadict = dict()
+ try:
+ for dataframe in dataframes(scan, self.HPATH):
+ pixels = self.get_pixels(dataframe.detector)
+ for index in range(job.firstpoint, job.lastpoint + 1):
+ yield self.process_image(index, dataframe, pixels)
+ util.statuseol()
+ except Exception as exc:
+ exc.args = errors.addmessage(exc.args, ', An error occured for scan {0} at point {1}. See above for more information'.format(self.dbg_scanno, self.dbg_pointno))
+ raise
+ self.metadata.add_section('sixs_backend', self.metadict)
+
+ def parse_config(self, config):
+ super(SIXS, self).parse_config(config)
+ self.config.xmask = util.parse_multi_range(config.pop('xmask', None))#Optional, select a subset of the image range in the x direction. all by default
+ self.config.ymask = util.parse_multi_range(config.pop('ymask', None))#Optional, select a subset of the image range in the y direction. all by default
+ self.config.nexusfile = config.pop('nexusfile')#Location of the specfile
+ self.config.pr = config.pop('pr', None) #Optional, all range by default
+ if self.config.xmask is None:
+ self.config.xmask = slice(None)
+ if self.config.ymask is None:
+ self.config.ymask = slice(None)
+ if self.config.pr:
+ self.config.pr = util.parse_tuple(self.config.pr, length=2, type=int)
+ self.config.sdd = float(config.pop('sdd'))# sample to detector distance (mm)
+ self.config.centralpixel = util.parse_tuple(config.pop('centralpixel'), length=2, type=int) #x,y
+ self.config.maskmatrix = config.pop('maskmatrix', None)#Optional, if supplied pixels where the mask is 0 will be removed
+ def get_destination_options(self, command):
+ if not command:
+ return False
+ command = ','.join(command).replace(' ', ',')
+ scans = util.parse_multi_range(command)
+ return dict(first=min(scans), last=max(scans), range=','.join(str(scan) for scan in scans))
+
+ # CONVENIENCE FUNCTIONS
+ def get_filename(self, scanno):
+ filename = self.config.nexusfile.format(scanno = str(scanno).zfill(5))
+ if not os.path.exists(filename):
+ raise errors.ConfigError('nexus filename does not exist: {0}'.format(filename))
+ return filename
+
+
+ @staticmethod
+ def apply_mask(data, xmask, ymask):
+ roi = data[ymask, :]
+ return roi[:, xmask]
+
+class FlyScanUHV(SIXS):
+ HPATH = {
+ "image": "xpad_image",
+ "mu": "UHV_MU",
+ "omega": "UHV_OMEGA",
+ "delta": "UHV_DELTA",
+ "gamma": "UHV_GAMMA",
+ }
+
+ def process_image(self, index, dataframe, pixels):
+ util.status(str(index))
+ detector = ALL_DETECTORS[dataframe.detector.name]()
+ maskmatrix = load_matrix(self.config.maskmatrix)
+ if maskmatrix is not None:
+ mask = numpy.bitwise_or(detector.mask, maskmatrix)
+ print mask
+ else:
+ mask = detector.mask
+
+ intensity = numpy.ma.array(data = dataframe.image[index, ...], mask = mask)
+ #util.status('{4}| gamma: {0}, delta: {1}, theta: {2}, mu: {3}'.format(gamma, delta, theta, mu, time.ctime(time.time())))
+
+ return intensity, (index, dataframe, pixels)
+
+ def get_pixels(self, detector):
+ detector = ALL_DETECTORS[detector.name]()
+ y, x, _ = detector.calc_cartesian_positions()
+ y0 = y[self.config.centralpixel[1], self.config.centralpixel[0]]
+ x0 = x[self.config.centralpixel[1], self.config.centralpixel[0]]
+ z = numpy.ones(x.shape) * -1 * self.config.sdd
+ # return converted to the hkl library coordinates
+ # x -> -y
+ # y -> z
+ # z -> -x
+ return numpy.array([-z, -(x - x0), (y - y0)])
+
+
+def load_matrix(filename):
+ if filename == None:
+ return None
+ if os.path.exists(filename):
+ ext = os.path.splitext(filename)[-1]
+ if ext == '.txt':
+ return numpy.array(numpy.loadtxt(filename), dtype = numpy.bool)
+ elif ext == '.npy':
+ return numpy.array(numpy.load(filename), dtype = numpy.bool)
+ else:
+ raise ValueError('unknown extension {0}, unable to load matrix!\n'.format(ext))
+ else:
+ raise IOError('filename: {0} does not exist. Can not load matrix'.format(filename))
+
+
diff --git a/binoculars/plot.py b/binoculars/plot.py
index a25a21c..78afd3a 100644
--- a/binoculars/plot.py
+++ b/binoculars/plot.py
@@ -101,7 +101,7 @@ def get_clipped_norm(data, clipping=0.0, log=True):
return matplotlib.colors.Normalize(vmin, vmax)
-def plot(space, fig, ax, log=True, loglog = False, clipping=0.0, fit=None, norm=None, colorbar=True, labels=True, **plotopts):
+def plot(space, fig, ax, log=True, loglog = False, clipping=0.0, fit=None, norm=None, colorbar=True, labels=True, interpolation='nearest', **plotopts):
if space.dimension == 1:
data = space.get_masked()
xrange = numpy.ma.array(space.axes[0][:], mask=data.mask)
@@ -142,9 +142,9 @@ def plot(space, fig, ax, log=True, loglog = False, clipping=0.0, fit=None, norm=
norm = get_clipped_norm(data, clipping, log)
if fit is not None:
- im = ax.imshow(fit.transpose(), origin='lower', extent=(xmin, xmax, ymin, ymax), aspect='auto', norm = norm, **plotopts)
+ im = ax.imshow(fit.transpose(), origin='lower', extent=(xmin, xmax, ymin, ymax), aspect='auto', norm = norm, interpolation=interpolation, **plotopts)
else:
- im = ax.imshow(data.transpose(), origin='lower', extent=(xmin, xmax, ymin, ymax), aspect='auto', norm = norm, **plotopts)
+ im = ax.imshow(data.transpose(), origin='lower', extent=(xmin, xmax, ymin, ymax), aspect='auto', norm = norm, interpolation=interpolation, **plotopts)
if labels:
ax.set_xlabel(space.axes[0].label)
diff --git a/binoculars/space.py b/binoculars/space.py
index eb87dfb..da19417 100755
--- a/binoculars/space.py
+++ b/binoculars/space.py
@@ -645,7 +645,7 @@ class Space(object):
contributions = numpy.bincount(indices)
self.photons.ravel()[:photons.size] += photons
- self.contributions.ravel()[:contributions.size] += contributions
+ self.contributions.ravel()[:contributions.size] += contributions.astype(self.contributions.dtype)
@classmethod
def from_image(cls, resolutions, labels, coordinates, intensity, limits = None):
diff --git a/binoculars/util.py b/binoculars/util.py
index 007c2b6..a98926d 100755
--- a/binoculars/util.py
+++ b/binoculars/util.py
@@ -651,14 +651,13 @@ def space_to_txt(space, filename):
numpy.savetxt(fp, data, fmt='%.6g', delimiter='\t')
@contextlib.contextmanager
-def open_h5py(file, mode):
- if isinstance(file, h5py._hl.group.Group):
- yield file
+def open_h5py(fn, mode):
+ if isinstance(fn, h5py._hl.group.Group):
+ yield fn
else:
- with h5py.File(file, mode) as fp:
+ with h5py.File(fn, mode) as fp:
if mode == 'w':
- if not 'binoculars' in fp:
- fp.create_group('binoculars')
+ fp.create_group('binoculars')
yield fp['binoculars']
if mode == 'r':
if 'binoculars' in fp:
diff --git a/binoculars.py b/scripts/binoculars
index 986e439..cc9a830 100755
--- a/binoculars.py
+++ b/scripts/binoculars
@@ -5,7 +5,22 @@ import os
import argparse
import numpy
-import binoculars.space, binoculars.util
+
+def set_src():
+ import sys
+ import os.path as osp
+ dirpath = osp.join(osp.dirname(osp.abspath(__file__)), osp.pardir)
+ sys.path.insert(0, osp.abspath(dirpath))
+
+try:
+ import binoculars.space
+ import binoculars.util
+except ImportError:
+ # try to use code from src distribution
+ set_src()
+ import binoculars.space
+ import binoculars.util
+
### INFO
def command_info(args):
diff --git a/binoculars-fitaid.py b/scripts/binoculars-fitaid
index af65ba0..5cc56d9 100644..100755
--- a/binoculars-fitaid.py
+++ b/scripts/binoculars-fitaid
@@ -1,17 +1,40 @@
+#!/usr/bin/env python
+
import h5py
import sys
import numpy
import os.path
+import itertools
+import matplotlib.figure, matplotlib.image
+
from PyQt4 import QtGui, QtCore, Qt
-import binoculars.main, binoculars.space, binoculars.plot, binoculars.fit, binoculars.util
from scipy.interpolate import griddata
-
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg, NavigationToolbar2QTAgg
-import matplotlib.figure, matplotlib.image
from matplotlib.pyplot import Rectangle
-import itertools
from scipy.spatial import qhull
+def set_src():
+ import sys
+ import os.path as osp
+ dirpath = osp.join(osp.dirname(osp.abspath(__file__)), osp.pardir)
+ sys.path.insert(0, osp.abspath(dirpath))
+
+try:
+ import binoculars.main
+ import binoculars.space
+ import binoculars.plot
+ import binoculars.fit
+ import binoculars.util
+except ImportError:
+ # try to use code from src distribution
+ set_src()
+ import binoculars.main
+ import binoculars.space
+ import binoculars.plot
+ import binoculars.fit
+ import binoculars.util
+
+
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
diff --git a/binoculars-gui.py b/scripts/binoculars-gui
index 15143a6..df11bb3 100755
--- a/binoculars-gui.py
+++ b/scripts/binoculars-gui
@@ -3,23 +3,39 @@
import sys
import os
import glob
-from PyQt4 import QtGui, QtCore, Qt
-import binoculars.main, binoculars.space, binoculars.plot, binoculars.util
import numpy
import json
import itertools
-from mpl_toolkits.mplot3d import Axes3D
-
import signal
import subprocess
-
import Queue
import socket
import SocketServer
import threading
+import matplotlib.figure, matplotlib.image
+from mpl_toolkits.mplot3d import Axes3D
+from PyQt4 import QtGui, QtCore, Qt
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg, NavigationToolbar2QTAgg
-import matplotlib.figure, matplotlib.image
+
+def set_src():
+ import sys
+ import os.path as osp
+ dirpath = osp.join(osp.dirname(osp.abspath(__file__)), osp.pardir)
+ sys.path.insert(0, osp.abspath(dirpath))
+
+try:
+ import binoculars.main
+ import binoculars.space
+ import binoculars.plot
+ import binoculars.util
+except ImportError:
+ # try to use code from src distribution
+ set_src()
+ import binoculars.main
+ import binoculars.space
+ import binoculars.plot
+ import binoculars.util
#RangeSlider is taken from https://www.mail-archive.com/pyqt@riverbankcomputing.com/msg22889.html
class RangeSlider(QtGui.QSlider):
diff --git a/binoculars-processgui.py b/scripts/binoculars-processgui
index 865d83e..5895995 100755
--- a/binoculars-processgui.py
+++ b/scripts/binoculars-processgui
@@ -7,16 +7,26 @@ author: Remy Nencib (remy.nencib@esrf.r)
import sys
import os
-import glob
-import traceback
-from PyQt4 import QtGui, QtCore, Qt
-import sys,os
-import itertools
-import inspect
-import glob
-import binoculars.util, binoculars.main
import time
+from PyQt4 import QtGui, QtCore
+
+
+def set_src():
+ import sys
+ import os.path as osp
+ dirpath = osp.join(osp.dirname(osp.abspath(__file__)), osp.pardir)
+ sys.path.insert(0, osp.abspath(dirpath))
+
+try:
+ import binoculars.main
+ import binoculars.util
+except ImportError:
+ # try to use code from src distribution
+ set_src()
+ import binoculars.main
+ import binoculars.util
+
#--------------------------------------------CREATE MAIN WINDOW----------------------------------------
class Window(QtGui.QMainWindow):
@@ -25,7 +35,7 @@ class Window(QtGui.QMainWindow):
self.initUI()
self.tab_widget = QtGui.QTabWidget(self)
self.setCentralWidget(self.tab_widget)
- #add the close button for tabs
+ # add the close button for tabs
close = self.tab_widget.setTabsClosable(True)
self.tab_widget.tabCloseRequested.connect(self.close_tab)
diff --git a/binoculars-server.py b/scripts/binoculars-server
index 23b61c7..3ede8c8 100644..100755
--- a/binoculars-server.py
+++ b/scripts/binoculars-server
@@ -1,9 +1,12 @@
-'''
-Serverqueue where jobs can be submitted. Jobs will be calculated on the spot or passed on to the OAR
-cluster if so specified in the configfile. Jobs can be submitted in a json dictionary.
-The keyword 'command' and 'configfilename' supply a string with the command and the path to the configfile.
-Everything else is assumed to be an override in the configfile. If an override cannot be parsed the job
-will start anyway without the override. The processingqueue cannot be interrupted.
+#!/usr/bin/env python
+'''Serverqueue where jobs can be submitted. Jobs will be calculated on
+the spot or passed on to the OAR cluster if so specified in the
+configfile. Jobs can be submitted in a json dictionary. The keyword
+'command' and 'configfilename' supply a string with the command and
+the path to the configfile. Everything else is assumed to be an
+override in the configfile. If an override cannot be parsed the job
+will start anyway without the override. The processingqueue cannot be
+interrupted.
'''
import socket
@@ -11,13 +14,28 @@ import threading
import SocketServer
import time
import sys
-import binoculars.util, binoculars.main
import traceback
-import re
import json
import os
import Queue
+
+def set_src():
+ import sys
+ import os.path as osp
+ dirpath = osp.join(osp.dirname(osp.abspath(__file__)), osp.pardir)
+ sys.path.insert(0, osp.abspath(dirpath))
+
+try:
+ import binoculars.main
+ import binoculars.util
+except ImportError:
+ # try to use code from src distribution
+ set_src()
+ import binoculars.main
+ import binoculars.util
+
+
class ProcessTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
input = self.request.recv(1024)
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..42b504e
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,29 @@
+import os
+
+from distutils.core import setup
+
+packages = ["binoculars",
+ "binoculars.backends"]
+
+scripts = [os.path.join("scripts", d)
+ for d in ["binoculars-fitaid",
+ "binoculars-gui",
+ "binoculars-processgui",
+ "binoculars"]]
+
+setup(name='binoculars', version='0.0.1',
+ description='FIXME',
+ long_description='FIXME',
+ packages=packages,
+ scripts=scripts,
+ author="Willem Onderwaater, Sander Roobol",
+ author_email="onderwaa@esrf.fr",
+ url='FIXME',
+ license='GPL-3',
+ classifiers=[
+ 'Topic :: Scientific/Engineering',
+ 'Development Status :: 3 - Alpha',
+ 'Operating System :: POSIX',
+ 'Operating System :: Unix',
+ 'Programming Language :: Python :: 2.7']
+ )