###################################################################################################
# Orientation Commands
###################################################################################################


# State

def newub(name):
    """
    start a new ub calculation name
    """
    return ub.newub(name)

def loadub(name_or_num):
    """
    load an existing ub calculation
    """
    return ub.loadub(name_or_num)

def lastub(name):
    """
    load the last used ub calculation
    """
    return ub.lastub()
    
def listub(name):
    """
    list the ub calculations available to load
    """
    return ub.listub()

def rmub(name_or_num):
    """
    remove existing ub calculation
    """
    return ub.rmub(name_or_num)    

def saveubas(name):
    """
    save the ub calculation with a new name
    """
    return ub.saveubas(name)


# Lattice

def setlat(name=None, *args):
    """
    set lattice parameters (Angstroms and Deg)
    setlat  -- interactively enter lattice parameters (Angstroms and Deg)
    setlat name a -- assumes cubic
    setlat name a b -- assumes tetragonal
    setlat name a b c -- assumes ortho
    setlat name a b c gamma -- assumes mon/hex with gam not equal to 90
    setlat name a b c alpha beta gamma -- arbitrary
    """
    return ub.setlat(name args)

def c2th(hkl, en=None):
    """
    calculate two-theta angle for reflection
    """
    return ub.c2th(hkl, en)

def hklangle(hkl1, hkl2):
    """
    calculate angle between [h1 k1 l1] and [h2 k2 l2] crystal planes
    """
    return ub.hklangle(hkl1, hkl2)


# Reference (surface)

def setnphi(xyz = None):
    """
    sets or displays (xyz=None) n_phi reference
    """
    return ub.setnphi(xyz)    
 

def setnhkl(hkl = None):
    """
    sets or displays (hkl=None)  n_hkl reference
    """
    return ub.setnhkl(hkl)    

# Reflections
        
def showref():
    """
    shows full reflection list
    """
    return ub.showref()   

def addref(*args):
    """
    Add reflection
    addref	--  add reflection interactively
    addref [h k l] {'tag'}	--  add reflection with current position and energy
    addref [h k l] (p1, .., pN) energy {'tag'}	--  add arbitrary reflection
    """
    return ub.addref(*args)       

def editref(idx):
    """
    interactively edit a reflection (idx is tag or index numbered from 1)
    """
    return ub.showref(idx)   

def delref(idx):
    """
    deletes a reflection (idx is tag or index numbered from 1)
    """
    return ub.delref(idx)   


def clearref():
    """
    deletes all the reflections
    """
    return ub.clearref()   

def swapref(idx1=None, idx2=None):
    """
    swaps two reflections
    swapref -- swaps first two reflections used for calculating U matrix
    swapref {num1 | 'tag1'} {num2 | 'tag2'} -- swaps two reflections
    """
    return ub.swapref(idx1, idx2)

        
# Crystal Orientations

def showorient():
    """
    shows full list of crystal orientations
    """
    return ub.showorient()  

def addorient(*args):
    """
    addorient -- add crystal orientation interactively
    addorient [h k l] [x y z] {'tag'}	-- add crystal orientation in laboratory frame
    """
    return ub.addorient(*args)  

def editorient(idx):
    """
    interactively edit a crystal orientation (idx is tag or index numbered from 1)
    """
    return ub.editorient(tag_or_num)  

def delorient(idx):
    """
    deletes a crystal orientation (idx is tag or index numbered from 1)
    """
    return ub.delorient(tag_or_num)  

def clearorient():
    """
    deletes all the crystal orientations
    """
    return ub.clearorient()  
    
def swaporient(idx1=None, idx2=None):
    """
    swaps two swaporient
    swaporient -- swaps first two crystal orientations used for calculating U matrix
    swaporient {num1 | 'tag1'} {num2 | 'tag2'} -- swaps two crystal orientations
    """
    return ub.swaporient(idx1, idx2)


# UB Matrix

def checkub():
    """
    show calculated and entered hkl values for reflections
    """
    return ub.checkub()  

def setu(U=None):
    """
    manually set U matrix
    setu -- set U matrix interactively
    setu [[..][..][..]] -- manually set U matrix
    """
    return ub.setu()  

def setub(U=None):
    """
    manually set UB matrix
    setub -- set UB matrix interactively
    setub [[..][..][..]] -- manually set UB matrix
    """
    return ub.setub()      

def getub():
    """
    returns current UB matrix
    NOT A DIFFCALC COMMAND
    """    
    return ub.ubcalc._UB.tolist()  

def calcub(idx1=None, idx1=None):
    """
    (re)calculate u matrix 
    calcub -- (re)calculate U matrix from the first two reflections and/or orientations.
    calcub idx1 idx2 -- (re)calculate U matrix from reflections and/or orientations referred by indices and/or tags idx1 and idx2.
    """
    return ub.calcub(idx1, idx1)  

def trialub(idx=1):
    """
    (re)calculate u matrix using one reflection only
    Use indice or tags idx1. Default: use first reflection.
    """
    return ub.trialub(idx)      

def refineub(*args):
    """
    refine unit cell dimensions and U matrix to match diffractometer angles for a given hkl value
    refineub -- interactively
    refineub [h k l] {pos}  
    """
    return ub.refineub(idx)      

def addmiscut(angle, xyz=None):
    """
    apply miscut to U matrix using a specified miscut angle in degrees and a rotation axis (default: [0 1 0])
    """
    return ub.addmiscut(angle, xyz)     
        
def setmiscut(angle, xyz=None):
    """
    manually set U matrix using a specified miscut angle in degrees and a rotation axis (default: [0 1 0])
    """
    return ub.setmiscut(angle, xyz)  



###################################################################################################
# Motion Commands
###################################################################################################


#Constraints

def con(*args):
    """
    list or set available constraints and values
    con -- list available constraints and values
    con <name> {val} -- constrains and optionally sets one constraint
    con <name> {val} <name> {val} <name> {val} -- clears and then fully constrains    
    """
    return hkl.con(*args)

def uncon(name):
    """
    remove constraint
    """
    return hkl.uncon(name)


# HKL
def allhkl(hkl, wavelength=None):
    """
    print all hkl solutions ignoring limits
    """
    return hkl.allhkl(wavelength)   


#Hardware

def setmin(axis, val=None):
    """
    set lower limits used by auto sector code (None to clear)
    """
    name = _difcalc_names[motor]
    return hardware.setmin(name, val)

def setmax(axis, val=None):
    """
    set upper limits used by auto sector code (None to clear)
    """
    name = _difcalc_names[motor]
    return hardware.setmax(name, val)

def setcut(axis, val):
    """
    sets cut angle
    """
    name = _difcalc_names[motor]
    return hardware.setcut(name, val)        

###################################################################################################
# Motion commands: not standard Diffcalc names
###################################################################################################
   

def hklci(positions, energy=None):
    """
    converts positions of motors to reciprocal space coordinates (H K L)
    """ 
    return dc.angles_to_hkl(positions, energy)

def hklca(hkl, energy=None):
    """
    converts reciprocal space coordinates (H K L) to positions of motors.
    """ 
    return dc.hkl_to_angles(hkl[0], hkl[1], hkl[3], energy)

def hklwh():
    """
    prints the current reciprocal space coordinates (H K L) and positions of motors.
    """ 
    hkl = hklget()
    print "HKL: " + str(hkl) + "\n"
    for m in _difcalc_names.keys(): 
        print _difcalc_names[m] + " [" + m.name + "] :" + m.take() 
    
def hklget():       
    """
    get current hkl position
    """           
    return hkl_group.read()  
    
def hklmv(hkl):  
    """
    move to hkl position
    """             
    hkl_group.write(hkl)

def hklsim(hkl):
    """
    simulates moving diffractometer
    """
    return hkl_group.sim(hkl) 
