diff options
author | Onderwaater <onderwaa@esrf.fr> | 2015-11-25 14:19:56 +0100 |
---|---|---|
committer | Onderwaater <onderwaa@esrf.fr> | 2015-11-25 14:19:56 +0100 |
commit | 2e072ce50ecffd6faebf4a597da7795409543228 (patch) | |
tree | 92186a3ca4f88c73be66cd7a0fc72b922a8631bf | |
parent | c8c1c339e6ccd330ba7c7e5e1e5c0423e6ff32de (diff) |
sixs backend commit
-rw-r--r-- | binoculars/backends/sixs.py | 403 | ||||
-rw-r--r-- | binoculars/plot.py | 6 | ||||
-rwxr-xr-x | binoculars/space.py | 2 | ||||
-rwxr-xr-x | binoculars/util.py | 11 | ||||
-rwxr-xr-x | scripts/binoculars (renamed from binoculars.py) | 17 | ||||
-rwxr-xr-x[-rw-r--r--] | scripts/binoculars-fitaid (renamed from binoculars-fitaid.py) | 31 | ||||
-rwxr-xr-x | scripts/binoculars-gui (renamed from binoculars-gui.py) | 28 | ||||
-rwxr-xr-x | scripts/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.py | 29 |
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'] + ) |