import wx
import order

class MyFrame(wx.Frame):
    def __init__(self,superior):
        wx.Frame.__init__(self,parent=superior,title='一个简单的订餐系统 by WSG',size=(480,600))

        #创建面板
        panel=wx.Panel(self)

        sizer=wx.GridBagSizer(5,5)

        self.customer=order.Customer('None')
        self.employee=order.Employee('0000')

        #标题
        maintitle=wx.StaticText(panel,label='一个简单的订餐系统')
        sizer.Add(maintitle,pos=(0,0),span=(0,3),flag=wx.TOP|wx.LEFT|wx.BOTTOM,border=15)
        font=wx.Font(18,wx.DEFAULT,wx.NORMAL,wx.BOLD)
        maintitle.SetFont(font)
        maintitle.SetForegroundColour('blue')

        #图片
        img=wx.Image("icon.png",wx.BITMAP_TYPE_ANY)
        w=img.GetWidth()*0.25
        h=img.GetHeight()*0.25
        img.Rescale(w,h)
        imgicon=img.ConvertToBitmap()
        icon=wx.StaticBitmap(panel,bitmap=imgicon)
        sizer.Add(icon,pos=(0,4),flag=wx.EXPAND)

        #食物图标
        foodimg=[]
        for i in range(6):
            imgg=wx.Image("{n}.png".format(n=i+1),wx.BITMAP_TYPE_ANY)
            imgg.Rescale(30,30)
            imggg=imgg.ConvertToBitmap()
            foodimg.append(imggg)

        #加图标
        imgadd=wx.Image("add.png",wx.BITMAP_TYPE_ANY)
        imgadd.Rescale(20,20)
        imgaddicon=imgadd.ConvertToBitmap()

        #减图标
        imgsub=wx.Image("sub.png",wx.BITMAP_TYPE_ANY)
        imgsub.Rescale(20,20)
        imgsubicon=imgsub.ConvertToBitmap()

        #线
        line=wx.StaticLine(panel)
        sizer.Add(line,pos=(1,0),span=(1,5),flag=wx.EXPAND|wx.BOTTOM,border=10)

        #顾客姓名
        font1=wx.Font(12,wx.DEFAULT,wx.NORMAL,wx.NORMAL)
        text1=wx.StaticText(parent=panel,label='输入您的姓名：')
        text1.SetFont(font1)
        sizer.Add(text1,pos=(2,0),flag=wx.LEFT,border=10)
        self.input1=wx.TextCtrl(parent=panel)
        sizer.Add(self.input1,pos=(2,1),span=(1,4),flag=wx.EXPAND|wx.RIGHT,border=10)

        #选择服务员
        text2=wx.StaticText(parent=panel,label='请选择服务员：')
        text2.SetFont(font1)
        sizer.Add(text2,pos=(3,0),flag=wx.LEFT|wx.TOP, border=10)
        self.empnum=['1000','1001','1002','1003']
        self.combo=wx.ComboBox(panel,value='请选择',choices=self.empnum)
        sizer.Add(self.combo,pos=(3,1),span=(1,4),flag=wx.TOP|wx.EXPAND|wx.RIGHT, border=10)

        #菜单复选框
        font2=wx.Font(15,wx.DEFAULT,wx.ITALIC,wx.NORMAL)
        title=wx.StaticBox(panel,label='今日菜单')
        title.SetFont(font2)
        title.SetForegroundColour('red')
        foodname=['可乐','汉堡','牛排','面条','包子','牛奶']
        foodprice=[12,14,34,23,23,11]
        self.menulen=len(foodname)
        self.foodlist=[]
        for i in range(self.menulen):
            food=order.Food(foodname[i],foodprice[i])
            self.foodlist.append(food)

        boxsizer=wx.StaticBoxSizer(title,wx.VERTICAL)
        self.menuCheckBox=[]
        self.CheckedFood=[]
        self.foodnumText=[]
        self.foodnumlist=[]
        self.addbuttonlist=[]
        self.subbuttonlist=[]

        for i in range(self.menulen):
            foodbox=wx.BoxSizer(wx.HORIZONTAL)
            img1=wx.StaticBitmap(panel,bitmap=foodimg[i]) #食物图片
            foodbox.Add(img1,flag=wx.ALL|wx.CENTER,border=5)

            checkbox=wx.CheckBox(panel,id=i,label=self.foodlist[i].showfd())
            checkbox.SetFont(font1)
            self.menuCheckBox.append(checkbox)
            self.CheckedFood.append(False)
            #self.Bind(wx.EVT_CHECKBOX,self.OnCheckBox,self.menuCheckBox[i])
            foodbox.Add(self.menuCheckBox[i],flag=wx.ALL|wx.CENTER,border=5) #食物名称

            subbutton=wx.BitmapButton(panel,id=i+100,bitmap=imgsubicon,style=10)
            self.subbuttonlist.append(subbutton)
            self.Bind(wx.EVT_BUTTON,self.OnSubButton,self.subbuttonlist[i])
            foodbox.Add(subbutton,flag=wx.LEFT|wx.CENTER,border=20) #减

            foodnum=wx.StaticText(panel,id=i,label="0")
            foodnum.SetFont(font2)
            self.foodnumText.append(foodnum)
            self.foodnumlist.append(0)
            foodbox.Add(foodnum,flag=wx.LEFT|wx.CENTER,border=10) #数量

            addbutton=wx.BitmapButton(panel,id=i+10,bitmap=imgaddicon)
            self.addbuttonlist.append(addbutton)
            self.Bind(wx.EVT_BUTTON,self.OnAddButton,self.addbuttonlist[i])
            foodbox.Add(addbutton,flag=wx.ALL|wx.CENTER,border=10) #加

            boxsizer.Add(foodbox,flag=wx.CENTER)

        sizer.Add(boxsizer,pos=(4,0),span=(1,5),flag=wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT,border=10)

        font3=wx.Font(15,wx.DEFAULT,wx.NORMAL,wx.BOLD)
        button1 = wx.Button(panel, size=(100,40),label='重置')
        button1.SetFont(font3)
        button1.SetForegroundColour('white')
        button1.SetBackgroundColour('slate blue')
        sizer.Add(button1, pos=(6, 0),flag=wx.LEFT, border=10)

        button2 = wx.Button(panel, size=(100,40),label="下单")
        button2.SetFont(font3)
        button2.SetForegroundColour('white')
        button2.SetBackgroundColour('slate blue')
        sizer.Add(button2, pos=(6, 3))

        button3 = wx.Button(panel,size=(100,40), label="退出",style=0)
        button3.SetFont(font3)
        button3.SetForegroundColour('black')
        button3.SetBackgroundColour('white')
        sizer.Add(button3, pos=(6, 4), span=(1, 1), flag=wx.BOTTOM|wx.RIGHT, border=10)

        sizer.AddGrowableCol(2)
        panel.SetSizer(sizer)

        #绑定事件
        self.Bind(wx.EVT_BUTTON,self.OnButtonReset,button1)
        self.Bind(wx.EVT_BUTTON,self.OnButtonCheck,button2)
        self.Bind(wx.EVT_BUTTON,self.OnButtonQuit,button3)

    def resizeBitmap(image,width=50,height=50):
        bmp=image.Scale(width,height).ConvertToBitmap()
        return bmp

    def OnButtonReset(self,event):#重置
        self.input1.Clear()
        self.combo.SetValue('请选择')
        for i in range(self.menulen):
            self.menuCheckBox[i].SetValue(False)
            self.foodnumText[i].SetLabel('0')
            self.foodnumlist[i]=0

    def OnButtonCheck(self,event):#确定
        try:
            cusname=self.input1.GetValue()
            empnum=self.combo.GetValue()
            flag=False
            for i in range(self.menulen):
                if not self.foodnumlist[i]==0:
                    flag=True
            if not cusname or empnum=='请选择' or flag==False:
                raise EOFError
            else:
                dlg=wx.MessageDialog(self,'确定下单？','注意',wx.CANCEL|wx.OK|wx.ICON_QUESTION)
                if dlg.ShowModal()==wx.ID_CANCEL:
                    return
        except EOFError:
            wx.MessageBox("信息填写不完整！",'注意',wx.OK|wx.ICON_EXCLAMATION)
            return
        self.customer.SetName(cusname)
        self.customer.delfoodordered()
        self.employee.SetNum(empnum)
        self.lunch=order.Lunch(self.customer,self.employee)
        for i in range(self.menulen):
            if not self.foodnumlist[i]==0:
                self.lunch.order(self.foodlist[i],self.foodnumlist[i])
        result=self.lunch.result()

        wx.MessageBox(result,'订餐结果',wx.OK|wx.ICON_EXCLAMATION)

    def OnCheckBox(self,event):
        cb=event.GetEventObject()
        self.CheckedFood[cb.GetId()]=cb.GetValue()

    def OnButtonQuit(self,event):#退出
        dlg=wx.MessageDialog(self,'确定退出订餐系统？','注意',wx.CANCEL|wx.OK|wx.ICON_QUESTION)
        if dlg.ShowModal()==wx.ID_OK:
            self.Destroy()

    def OnAddButton(self,event):#加
        ad=event.GetEventObject()
        fn=self.foodnumText[ad.GetId()-10]
        fn.SetLabel(str(int(fn.GetLabel())+1))
        self.foodnumlist[ad.GetId()-10]+=1

    def OnSubButton(self,event):#减
        sb=event.GetEventObject()
        fn=self.foodnumText[sb.GetId()-100]
        num=int(fn.GetLabel())
        if num==0:
            return
        fn.SetLabel(str(int(num-1)))
        self.foodnumlist[sb.GetId()-100]-=1

if __name__=='__main__':
    app=wx.App()
    frame=MyFrame(None)
    frame.Show()
    app.MainLoop()


# -*- coding: utf-8 -*-
"""
Created on Thu Jun 28 16:26:23 2018

@author: Joseph
"""

import tensorflow as tf
import math
from six.moves import xrange
from tensorflow.python.ops import control_flow_ops
from tensorflow.python.training import moving_averages
def batch_normalization(logits, scale, offset, isTraining = False, name="bn"):
	mean, var = tf.nn.moments(logits, [0, 1, 2])
	moving_mean_shape = mean.get_shape()
	moving_var_shape = var.get_shape()
	moving_mean = tf.get_variable('moving_mean',moving_mean_shape,initializer=tf.zeros_initializer,trainable=False)
	moving_var = tf.get_variable('moving_var', moving_var_shape,initializer=tf.ones_initializer,trainable=False)
	moving_mean = moving_averages.assign_moving_average(moving_mean,mean,0.95)
	moving_var = moving_averages.assign_moving_average(moving_var,var,0.95)
	mean, var = control_flow_ops.cond(isTraining, lambda:(mean,var), lambda:(moving_mean, moving_var))
	output = tf.nn.batch_normalization(logits, mean, var, offset, scale, variance_epsilon=1e-5)
	return output

def get_conv_weights(weight_shape, sess, name="get_conv_weights"):
	#return math.sqrt(2 / (9.0 * 64)) * sess.run(tf.truncated_normal(weight_shape))
	return sess.run(tf.truncated_normal(weight_shape,stddev=0.1))

def get_bn_weights(weight_shape, clip_b, sess, name="get_bn_weights"):
	weights = get_conv_weights(weight_shape, sess)
	#return clipping(weights, clip_b)
	return  weights

def clipping(A, clip_b, name="clipping"):
	h, w = A.shape
	for i in xrange(h):
		for j in xrange(w):
			if A[i,j] >= 0 and A[i,j] < clip_b:
				A[i,j] = clip_b
			elif A[i,j] > -clip_b and A[i,j] < 0:
				A[i,j] = -clip_b
	return A


#!/usr/bin/env python3
from Bio import SeqIO
from Bio import AlignIO
from utils import *

sars = SeqIO.read("Sars_CoV_2","fasta") # get unaligned sars
sars_align = AlignIO.read("data/alignment","fasta")._records[0] # get aligned sars
proteome = get_proteome("proteome.csv") # get unaligned proteome

mapping = [0]*len(sars_align) # init container for mapping
j = 1
for i,nucl in enumerate(sars_align): # for each nucleotide in aligned sars
    if(nucl=="-"): # if indel
        mapping[i] = -1 # don't map
    else: # if not
        mapping[i] = j # map
        j += 1 # iterate
for protein in proteome: # for each protein in unaligned proteome
    start = proteome[protein]["Start"] # get start for this protein
    stop = proteome[protein]["Stop"] # get stop for this protein
    proteome[protein]["Start"] = mapping.index(start)
    proteome[protein]["Stop"] = mapping.index(stop)

file = open("askd.csv","w")
file.write("#Name,Start,Stop")
for protein in proteome:
    file.write(protein+","+str(proteome[protein]["Start"]+1)+","+str(proteome[protein]["Stop"]+1)+"\n")

file.close()


from django.urls import path
from django.urls import path, re_path
from . import views

app_name = "copier"
urlpatterns = [
    path('', view=views.copier_list, name='list'),
    path('upload/', view=views.copier_upload_files, name='upload'),
    path('update/<pk>/', view=views.copier_update, name='update'),
    path('scanner/<pk>/', view=views.company_update, name='scanner')
]


import numpy as np
import cv2
import pdb
import os
from ellipse_my import ellipse_my
from watershed import watershed

w_thr = 4
h_thr = 4
offset = 10
box_off =[[0, 0], [0, offset], [0, -offset], [offset, 0], [-offset, 0]]

def get_part_set(ellipse_info, part_num=128):
    '''
    Use ellipse_info to get part point set.
    '''
    part_label = ellipse_my(ellipse_info, part_num)

    return part_label

def get_single_old_box(cur_axis, next_axis):

    lx = np.min((cur_axis[1], next_axis[1]))
    rx = np.max((cur_axis[1], next_axis[1]))
    ly = np.min((cur_axis[0], next_axis[0]))
    ry = np.max((cur_axis[0], next_axis[0]))

    cx = (lx + rx) / 2
    cy = (ly + ry) / 2
    w = (rx - lx) / 2
    h = (ry - ly) / 2
    if w < w_thr:
        w = w_thr
    if h < h_thr:
        h = h_thr

    print('after (%d, %d)' % (w, h))

    print('cx: %d, cy: %d' % (cx, cy))

    box = [int(cx-w), int(cy-h), int(cx+w), int(cy+h)]
    #box = [int(lx), int(ly), int(rx), int(ry)]

    return box

def get_single_box(cur_axis, next_axis):

    cx = cur_axis[1]
    cy = cur_axis[0]
    w = w_thr
    h = h_thr

    #print('after (%d, %d)' % (w, h))

    #print('cx: %d, cy: %d' % (cx, cy))

    box = [int(cx-w), int(cy-h), int(cx+w), int(cy+h)]
    #box = [int(lx), int(ly), int(rx), int(ry)]

    return box

def get_diff_single_box(cur_axis, box_num=5):

    cx = cur_axis[1]
    cy = cur_axis[0]
    w = w_thr
    h = h_thr
    box_set = []

    for i in range(box_num):
        cx_n = cx + box_off[i][0]
        cy_n = cy + box_off[i][1]
        box = [int(cx_n-w), int(cy_n-h), int(cx_n+w), int(cy_n+h)]
        box_set.append(box)

    return box_set

def get_part_box(ellipse_info, part_num=64):

    box_list = []

    part_set = get_part_set(ellipse_info, part_num)

    for i in range(len(part_set)):

        cur_index = i
        next_index = (i+1) % len(part_set)
        box = get_single_box(part_set[cur_index], part_set[next_index])
        box_list.append(box)

    return box_list

def get_point_box(im, im_show):
    '''
    use every point which draw by cv2.ellipse as center to get box list.
    '''

    sz = im.shape
    pset = []
    box_list = []
    for i in range(sz[0]):
        for j in range(sz[1]):
            if im[i][j][0] == 0:
                pset.append([h_thr, w_thr])
                box = get_single_box([i, j], None)
                box_list.append(box)

                #cv2.rectangle(im_show, (box[0], box[1]), (box[2], box[3]),  (0,255,0), 1)
                #cv2.imwrite('0grad_dire.bmp', im_show)
                #pdb.set_trace()

    return box_list, pset

def get_adaptive_box(ellipse_info, part_num=128):

    box_list = []

    part_set = get_part_set(ellipse_info, part_num)

    for i in range(len(part_set)):

        cur_index = i
        box_set = get_diff_single_box(part_set[cur_index])
        box_list.append(box_set)

    return box_list

def threshold_(im):
    _, thresh = cv2.threshold(im, 80, 255, cv2.THRESH_BINARY_INV)

    return thresh

def otsu_threshold_(im):

    _,thresh = cv2.threshold(im, 0, 255, cv2.THRESH_BINARY+ cv2.THRESH_OTSU)

    return thresh

def canny_(im):
    cv2.GaussianBlur(im, ksize=(5,5), sigmaX=2)
    im = cv2.Canny(im, threshold1=127, threshold2=255)

    return im

def adaptiveThreshold_(im):

    #cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
    im = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 15, 2)

    return im

def grad_(im):

    solelx = cv2.Sobel(im, cv2.CV_64F, 1, 0, ksize=3)
    solely = cv2.Sobel(im, cv2.CV_64F, 0, 1, ksize=3)
    grad = cv2.magnitude(solelx, solely)

    return grad

def grad_direction(im):

    im = cv2.phase(cv2.Sobel(im, cv2.CV_64F, 1, 0, ksize=3), cv2.Sobel(im,cv2.CV_64F, 0, 1, ksize=3), angleInDegrees=True)

    return im

def watershed_im(im, im_gray, ellipse_info):

    box_list = get_part_box(ellipse_info)
    for i in range(len(box_list)):
        box = box_list[i]
        im_crop = im[box[1]:box[3], box[0]:box[2]]
        watered_crop = watershed(im_crop)
        #watered_crop = threshold_(im_crop)
        im_gray[box[1]:box[3], box[0]:box[2]] = watered_crop

    return im_gray

def adpThreshold_im(im, im_gray, ellipse_info):

    box_list = get_part_box(ellipse_info)
    #im_c = im_gray.copy()
    im_c = im.copy()
    sz = im_gray.shape

    for i in range(len(box_list)):
        box = box_list[i]

        if box[0]<0 or box[1]<0 or box[2]>= sz[1] or box[3]>=sz[0]:
            continue
        im_crop = im_gray[box[1]:box[3], box[0]:box[2]]
        crop = adaptiveThreshold_(im_crop)
        #crop = otsu_threshold_(im_crop)
        ii = 0
        jj = 0

        b_cx = int((box[2]-box[0])/2)
        b_cy = int((box[3]-box[1])/2)
        flag = crop[b_cy][b_cx]
        for i in range(box[1], box[3]):
            for j in range(box[0], box[2]):
                #print('ii: %d, jj: %d' % (ii, jj))
                #print('i: %d, j:%d' % (i, j))
                if crop[ii][jj] == flag:
                    im_c[i][j] = 255
                jj += 1
            ii += 1
            jj = 0
        '''
        crop3 = np.zeros((crop.shape[0], crop.shape[1], 3))
        crop3[:,:,0] = crop
        crop3[:,:,1] = crop
        crop3[:,:,2] = crop
        im_c[box[1]:box[3], box[0]:box[2]] = crop3
        '''
    return im_c

def main():
    filename = 'img00001'
    im = cv2.imread('%s.bmp' % filename)

    lx, ly, rx, ry = 856, 261, 1346, 730
    w=rx-lx
    h=ry-ly
    cx=(lx+rx)/2
    cy=(ly+ry)/2

    ellipse_info = ((cx, cy), (w, h), 0)
    print(ellipse_info)
    box_list = get_part_box(ellipse_info)
    cv2.ellipse(im, ellipse_info, (0,255,0),1)

    for i in range(len(box_list)):
        box = box_list[i]
        cv2.rectangle(im, (box[0], box[1]), (box[2], box[3]),  (0,255,0), 1)

    cv2.imwrite('%s_re_box.bmp' %  filename, im)

def main_watershed():

    filename = 'img00004'
    im = cv2.imread('%s.bmp' % filename)
    im_gray = cv2.imread('%s.bmp' % filename, 0)

    lx, ly, rx, ry = 856, 261, 1346, 730
    w=rx-lx
    h=ry-ly
    cx=(lx+rx)/2
    cy=(ly+ry)/2

    ellipse_info = ((cx, cy), (w, h), 0)
    after_watershed = watershed_im(im, im_gray, ellipse_info)

    cv2.imwrite('%s_watershed.bmp' % filename, after_watershed)

def main_adap():

    filename = 'img00004'
    im = cv2.imread('%s.bmp' % filename)
    im_gray = cv2.imread('%s.bmp' % filename, 0)

    lx, ly, rx, ry = 856, 261, 1346, 730
    w=rx-lx
    h=ry-ly
    cx=(lx+rx)/2
    cy=(ly+ry)/2

    ellipse_info = ((cx, cy), (w, h), 0)
    after_adap = adpThreshold_im(im, im_gray, ellipse_info)

    cv2.imwrite('%s_watershed.bmp' % filename, after_adap)

def main_test_adap():

    filename = 'img00004'
    im = cv2.imread('%s.bmp' % filename)
    im_gray = cv2.imread('%s.bmp' % filename, 0)

    #im = adaptiveThreshold_(im_gray)
    im = otsu_threshold_(im_gray)

    cv2.imwrite('adap_%s.bmp' % filename, im)

def main_test_grad():

    filename = 'img00003'
    im = cv2.imread('%s.bmp' % filename)
    im_gray = cv2.imread('%s.bmp' % filename, 0)

    im = grad_(im_gray)

    cv2.imwrite('grad_%s.bmp' % filename, im)

def main_test_grad_dire():

    filename = 'img00003'
    im = cv2.imread('%s.bmp' % filename)
    im_gray = cv2.imread('%s.bmp' % filename, 0)

    im = grad_direction(im_gray)

    cv2.imwrite('grad_dire%s.bmp' % filename, im)

if __name__ == '__main__':
    #main()
    #main_watershed()
    #main_adap()
    main_test_grad()
    #main_test_grad_dire()


import os
import h5py
import vigra
import numpy

class TPDError(RuntimeError):
    pass

class TrainPredictData(object):
    """
    The TrainPredictData class can be used to store and load .tpd files (data
    which is associated with a train / predict workflow).
    """

    # The paths that are used inside the .tpd file.
    _tpd_train_raw_path = "train_raw_path"
    _tpd_train_raw_key = "train_raw_key"
    _tpd_train_gt_path = "train_gt_path"
    _tpd_train_gt_key = "train_gt_key"
    _tpd_train_feat = "train_feat"
    _tpd_train_shape = "train_shape"
    _tpd_train_pred_path = "train_pred_path"
    _tpd_train_pred_key = "train_pred_key"
    _tpd_test_raw_path = "test_raw_path"
    _tpd_test_raw_key = "test_raw_key"
    _tpd_test_gt_path = "test_gt_path"
    _tpd_test_gt_key = "test_gt_key"
    _tpd_test_feat = "test_feat"
    _tpd_test_shape = "test_shape"
    _tpd_test_pred_path = "test_pred_path"
    _tpd_test_pred_key = "test_pred_key"

    @staticmethod
    def _check_file_exists(file_name):
        """Raise an exception if the given file does not exist.

        :param file_name: file name relative to the working directory
        """
        if not os.path.isfile(file_name):
            raise TPDError("_check_file_exists(): The given file does not exist.")

    @staticmethod
    def _get_count(shape):
        """Return the number of instances, given a shape.

        :param shape: shape
        :return: number of instances
        """
        from functools import reduce
        from operator import mul
        return reduce(mul, shape, 1)

    def __init__(self, file_name, use_abs_paths=False):
        """
        Create a TrainPredictData instance by loading the given file.
        If the given file does not exist, it will be created.

        :param file_name: file name
        :param use_abs_paths: when adding new data sets, the absolute path will be used instead of the relative path
        """
        self.file_name = file_name
        self.use_abs_paths = use_abs_paths
        dirname = os.path.dirname(self.file_name)
        if len(dirname) == 0:
            dirname = "."
        if not os.path.isdir(dirname):
            os.makedirs(dirname)
        self.base_path = os.path.relpath(dirname)

        # Check if the file can be opened with h5py.
        # If it does not exist, it will be created by h5py.
        f = h5py.File(file_name, "a")
        f.close()

    def _to_tpd_path(self, file_name):
        """
        Given a file name relative to the working directory, return the
        file path relative to the .tpd file considering the abs path setting.

        :param file_name: file name relative to working directory
        :return: file name relative to .tpd file considering abs path setting
        """
        if self.use_abs_paths:
            path = os.path.abspath(file_name)
        else:
            path = os.path.relpath(file_name, start=self.base_path)
        return path

    def _to_rel_path(self, file_name):
        """
        Given a file name relative to the .tpd file, return the
        file path relative to the current working directory.

        :param file_name: file name relative to the .tpd file or abs path
        :return: file name relative to the working directory
        """
        if os.path.isabs(file_name):
            path = os.path.relpath(file_name)
        else:
            path = os.path.join(self.base_path, file_name)
        return path

    def _set_data(self, file_name, h5_key, tpd_path, tpd_key, tpd_shape):
        """Set file name and h5 key of the data.

        :param file_name: file name
        :param h5_key: h5 key
        :param tpd_path: tpd key of the file
        :param tpd_key: tpd key of the h5 key
        :param tpd_shape: tpd key with the shape of the data
        """
        self._check_file_exists(file_name)

        # Read the shape of the new data set.
        with h5py.File(file_name, "r") as f:
            if h5_key not in f.keys():
                raise TPDError("_set_data(): The given h5 key does not exist in the given file.")
            new_shape = f[h5_key].shape
        new_count = self._get_count(new_shape)

        with h5py.File(self.file_name, "a") as f:
            # Check if the data shapes match.
            if tpd_shape in f.keys():
                shape = tuple(f[tpd_shape].value)
                count = self._get_count(shape)
                if new_count != count:
                    raise TPDError("_set_data(): The numbers of instances do not match.")
            else:
                f[tpd_shape] = new_shape

            if tpd_path in f.keys():
                del f[tpd_path]
            f[tpd_path] = self._to_tpd_path(file_name)
            if tpd_key in f.keys():
                del f[tpd_key]
            f[tpd_key] = h5_key

    def _get_data(self, tpd_path, tpd_key):
        """Return file name and h5 key of the data.

        :param tpd_path: tpd key of the file
        :param tpd_key: tpd key of the h5 key
        :return: file name, h5 key
        """
        with h5py.File(self.file_name, "r") as f:
            if tpd_path not in f.keys() or tpd_key not in f.keys():
                raise TPDError("_get_data(): The .tpd file does not contain the desired data.")
            file_name = f[tpd_path].value
            h5_key = f[tpd_key].value
        file_name = self._to_rel_path(file_name)
        return file_name, h5_key

    def set_train_raw(self, file_name, h5_key):
        """Set file name and h5 key of the training raw data.

        :param file_name: file name
        :param h5_key: h5 key
        """
        self._set_data(file_name, h5_key,
                       self._tpd_train_raw_path, self._tpd_train_raw_key,
                       self._tpd_train_shape)

    def get_train_raw(self):
        """Return file name and h5 key of the training raw data.

        :return: file name, h5 key
        """
        return self._get_data(self._tpd_train_raw_path, self._tpd_train_raw_key)

    def get_train_raw_data(self):
        """Return the training raw data.

        :return: training raw data
        """
        file_name, h5_key = self.get_train_raw()
        return vigra.readHDF5(file_name, h5_key)

    def set_train_gt(self, file_name, h5_key):
        """Set file name and h5 key of the training gt data.

        :param file_name: file name
        :param h5_key: h5 key
        """
        self._set_data(file_name, h5_key,
                       self._tpd_train_gt_path, self._tpd_train_gt_key,
                       self._tpd_train_shape)

    def get_train_gt(self):
        """Return file name and h5 key of the training raw data.

        :return: file name, h5 key
        """
        return self._get_data(self._tpd_train_gt_path, self._tpd_train_gt_key)

    def get_train_gt_data(self):
        """Return the training gt data.

        :return: training gt data
        """
        file_name, h5_key = self.get_train_gt()
        return vigra.readHDF5(file_name, h5_key)

    def set_test_raw(self, file_name, h5_key):
        """Set file name and h5 key of the test raw data.

        :param file_name: file name
        :param h5_key: h5 key
        """
        self._set_data(file_name, h5_key,
                       self._tpd_test_raw_path, self._tpd_test_raw_key,
                       self._tpd_test_shape)

    def get_test_raw(self):
        """Return file name and h5 key of the test raw data.

        :return: file name, h5 key
        """
        return self._get_data(self._tpd_test_raw_path, self._tpd_test_raw_key)

    def get_test_raw_data(self):
        """Return the test raw data.

        :return: test raw data
        """
        file_name, h5_key = self.get_test_raw()
        return vigra.readHDF5(file_name, h5_key)

    def set_test_gt(self, file_name, h5_key):
        """Set file name and h5 key of the test gt data.

        :param file_name: file name
        :param h5_key: h5 key
        """
        self._set_data(file_name, h5_key,
                       self._tpd_test_gt_path, self._tpd_test_gt_key,
                       self._tpd_test_shape)

    def get_test_gt(self):
        """Return file name and h5 key of the test gt data.

        :return: file name, h5 key
        """
        return self._get_data(self._tpd_test_gt_path, self._tpd_test_gt_key)

    def get_test_gt_data(self):
        """Return the test gt data.

        :return: test gt data
        """
        file_name, h5_key = self.get_test_gt()
        return vigra.readHDF5(file_name, h5_key)

    def _add_feature(self, file_name, h5_key, tpd_key, tpd_shape):
        """
        Add the given feature to the training or test data, depending on the tpd key.
        The feature will only be added, if it is not already in the feature list.

        :param file_name: file name
        :param h5_key: h5 key
        :param tpd_key: key in the .tpd file
        :param tpd_shape: key in the .tpd file with the shape of the data
        """
        self._check_file_exists(file_name)
        to_add = [self._to_tpd_path(file_name), h5_key]

        # Read the instance count from the given file.
        with h5py.File(file_name, "r") as f:
            if h5_key not in f.keys():
                raise TPDError("_add_feature(): The given h5 key does not exist in the given file.")
            new_shape = f[h5_key].shape
        new_shape_count = self._get_count(new_shape)
        new_count = new_shape[0]

        # Append the new feature to the feature list.
        with h5py.File(self.file_name, "a") as f:
            # Get the current feature list.
            if tpd_key in f.keys():
                feature_list = f[tpd_key].value.tolist()
            else:
                feature_list = []

            # Get the shape of the old data.
            if tpd_shape in f.keys():
                shape = tuple(f[tpd_shape].value)
                count = self._get_count(shape)
                if new_count != count and new_shape_count != count:
                    raise TPDError("_add_feature(): The numbers of instances do not match.")

            # Append the feature to the list.
            if to_add not in feature_list:
                feature_list.append(to_add)

            if tpd_key in f.keys():
                del f[tpd_key]
            f[tpd_key] = numpy.array(feature_list)

    def add_train_feature(self, file_name, h5_key):
        """Add the given training feature, but only if it is not already in the feature list.

        :param file_name: file name
        :param h5_key: h5 key
        """
        self._add_feature(file_name, h5_key, self._tpd_train_feat, self._tpd_train_shape)

    def add_test_feature(self, file_name, h5_key):
        """Add the given test feature, but only if it is not already in the feature list.

        :param file_name: file name
        :param h5_key: h5 key
        """
        self._add_feature(file_name, h5_key, self._tpd_test_feat, self._tpd_test_shape)

    def _get_feature_file(self, tpd_key, i):
        """Get file name and h5 key of the feature with index i.

        :param tpd_key: tpd key of the data
        :param i: feature index
        :return: file name, h5 key
        """
        with h5py.File(self.file_name, "r") as f:
            if tpd_key not in f.keys():
                raise TPDError("_get_feature_file(): There are no features in the .tpd file.")
            feature_list = f[tpd_key].value.tolist()

        if i < 0 or i >= len(feature_list):
            raise TPDError("_get_feature_file(): Index out of range.")
        return self._to_rel_path(feature_list[i][0]), feature_list[i][1]

    def get_train_feature_file(self, i):
        """Get file name and h5 key of the training feature with index i.

        :param i: feature index
        :return: file name, h5 key
        """
        return self._get_feature_file(self._tpd_train_feat, i)

    def get_test_feature_file(self, i):
        """Get file name and h5 key of the test feature with index i.

        :param i: feature index
        :return: file name, h5 key
        """
        return self._get_feature_file(self._tpd_test_feat, i)

    def _get_feature_data(self, tpd_key, tpd_shape):
        """Get the features of the desired data set.

        :param tpd_key: tpd key of the data
        :param tpd_shape: tpd key of the shape of the raw data
        :return: features of the desired data set
        """
        with h5py.File(self.file_name, "r") as f:
            if tpd_key not in f.keys():
                raise TPDError("_get_feature_data(): There are no features in the .tpd file.")
            feature_list = f[tpd_key].value.tolist()
            if tpd_shape in f.keys():
                shape = tuple(f[tpd_shape].value)
                count = self._get_count(shape)
            else:
                shape = None

        # Check that the number of instances in all feature files is correct and get the number of features.
        num_all_feats = []
        for file_path, h5_key in feature_list:
            # Read the shape of the feature data.
            file_path = self._to_rel_path(file_path)
            with h5py.File(file_path, "r") as f:
                if h5_key not in f.keys():
                    raise TPDError("_get_feature_data(): The h5 key does not exist in the given file.")
                new_shape = f[h5_key].shape
            new_count = self._get_count(new_shape)
            if shape is None:
                shape = new_shape
                count = self._get_count(shape)

            # Get the number of features that are inside the current data set.
            if new_count == count:
                num_all_feats.append(1)
            elif new_shape[0] == count:
                num_all_feats.append(self._get_count(new_shape[1:]))
            else:
                raise TPDError("_get_feature_data(): The numbers of instances do not match.")

        # Write all features into a single numpy array.
        feats = numpy.zeros((count, sum(num_all_feats)))
        current_feat = 0
        for i in xrange(len(num_all_feats)):
            file_path, h5_key = feature_list[i]
            file_path = self._to_rel_path(file_path)
            num_feats = num_all_feats[i]

            # Read the feature data.
            with h5py.File(file_path, "r") as f:
                feat = f[h5_key].value
            feat = feat.reshape((count, num_feats))

            # Write all features into the feature array.
            for k in xrange(num_feats):
                feats[:, current_feat] = feat[:, k]
                current_feat += 1

        return feats

    def get_train_features(self):
        """Return a (n, d) numpy array with the training features (n instances, d features).

        :return: training features
        """
        return self._get_feature_data(self._tpd_train_feat, self._tpd_train_shape)

    def get_test_features(self):
        """Return a (n, d) numpy array with the test features (n instances, d features).

        :return: test features
        """
        return self._get_feature_data(self._tpd_test_feat, self._tpd_test_shape)

    def _clear_features(self, tpd_key):
        """Clear the list with features.
        """
        with h5py.File(self.file_name) as f:
            if tpd_key in f.keys():
                del f[tpd_key]

    def clear_train_features(self):
        """Clear the list with training features.
        """
        self._clear_features(self._tpd_train_feat)

    def clear_test_features(self):
        """Clear the list with test features.
        """
        self._clear_features(self._tpd_test_feat)

    def set_train_pred(self, file_name, h5_key):
        """Set file name and h5 key of the training prediction data.

        :param file_name: file name
        :param h5_key: h5 key
        """
        self._set_data(file_name, h5_key,
                       self._tpd_train_pred_path, self._tpd_train_pred_key,
                       self._tpd_train_shape)

    def get_train_pred(self):
        """Return file name and h5 key of the training prediction data.

        :return: file name, h5 key
        """
        return self._get_data(self._tpd_train_pred_path, self._tpd_train_pred_key)

    def get_train_pred_data(self):
        """Return the training prediction data.

        :return: training prediction data
        """
        file_name, h5_key = self.get_train_pred()
        return vigra.readHDF5(file_name, h5_key)

    def set_test_pred(self, file_name, h5_key):
        """Set file name and h5 key of the test prediction data.

        :param file_name: file name
        :param h5_key: h5 key
        """
        self._set_data(file_name, h5_key,
                       self._tpd_test_pred_path, self._tpd_test_pred_key,
                       self._tpd_test_shape)

    def get_test_pred(self):
        """Return file name and h5 key of the test prediction data.

        :return: file name, h5 key
        """
        return self._get_data(self._tpd_test_pred_path, self._tpd_test_pred_key)

    def get_test_pred_data(self):
        """Return the test prediction data.

        :return: test prediction data
        """
        file_name, h5_key = self.get_test_pred()
        return vigra.readHDF5(file_name, h5_key)

    def show(self):
        """Show raw and ground truth data of training and test set.
        """
        from PyQt4.QtGui import QApplication
        from segmentation.labeling.faceLabeling import FaceLabeler
        app = QApplication([])
        v = FaceLabeler(numpy.array([0]), [0, 0, 0, 0])

        try:
            raw_train = self.get_train_raw_data()
            v.addGrayscaleLayer(raw_train, "raw train")
        except TPDError:
            pass

        try:
            gt_train = self.get_train_gt_data()
            v.addRandomColorsLayer(gt_train, "gt train")
        except TPDError:
            pass

        try:
            raw_test = self.get_test_raw_data()
            v.addGrayscaleLayer(raw_test, "raw test")
        except TPDError:
            pass

        try:
            gt_test = self.get_test_gt_data()
            v.addRandomColorsLayer(gt_test, "gt test")
        except TPDError:
            pass

        v.show()
        app.exec_()


from pathlib import Path
import shutil

import bluepymm
from bluepymm import prepare_combos, run_combos, select_combos
import pandas as pd
import pytest

test_dir = "tests"

@pytest.fixture(autouse=True)
def setup_tests():
    """Deletes the tmp directory used in prepare step."""
    tmp_path = Path(test_dir) / "tmp"
    if tmp_path.exists() and tmp_path.is_dir():
        shutil.rmtree(tmp_path)

def test_select_output():
    """Runs all 3 steps and checks the output of select step."""
    prepare_config = "prepare.json"
    with bluepymm.tools.cd(test_dir):
        prepare_combos.prepare_combos(conf_filename=prepare_config, continu=False)

    run_config = "run.json"
    with bluepymm.tools.cd(test_dir):
        run_combos.run_combos(conf_filename=run_config)

    select_config = "select.json"
    with bluepymm.tools.cd(test_dir):
        select_combos.select_combos(conf_filename=select_config, n_processes=None)

    gt_df = pd.read_csv("tests/ground_truth/mecombo_emodel.tsv", sep="\t")
    res_df = pd.read_csv("tests/output_select/mecombo_emodel.tsv", sep="\t")

    pd.testing.assert_frame_equal(res_df, gt_df)