from __future__ import division
import os, sys
import olx
import olex_hkl
import OlexVFS
import time
import math
from cStringIO import StringIO
import ntpath
import cProfile
import pstats
#import cProfile, pstats, StringIO
#pr = cProfile.Profile()
#pr.enable()
#pr.disable()
#s = StringIO.StringIO()
#sortby = 'cumulative'
#ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
#ps.print_stats()
#print s.getvalue()
from PeriodicTable import PeriodicTable
try:
olx.current_hklsrc
except:
olx.current_hklsrc = None
olx.current_hklsrc_mtime = None
olx.current_reflections = None
olx.current_mask = None
olx.current_space_group = None
olx.current_observations = None
import olex
import olex_core
import time
import cctbx_controller as cctbx_controller
from cctbx import maptbx, miller, uctbx, crystal
import iotbx
from libtbx import easy_pickle, utils
from olexFunctions import OlexFunctions
OV = OlexFunctions()
from scitbx.math import distributions
from History import hist
global twin_laws_d
twin_laws_d = {}
from scitbx.math import continued_fraction
from boost import rational
from cctbx import sgtbx, xray
from cctbx.array_family import flex
import smtbx.utils
import numpy
import itertools
import operator
import fractions
from cctbx_olex_adapter import OlexCctbxAdapter
class twin_rules:
def __init__(self,space,twin_axis,hkl_rotation,angle,fom,rbasf=[0,0.5,0]): #changed default to bad rbasf
self.space=space
self.twin_axis=twin_axis
self.hkl_rotation=hkl_rotation
self.angle=angle
self.fom=fom
self.rbasf=rbasf
class OlexCctbxTwinLaws(OlexCctbxAdapter):
def __init__(self):
#super(OlexCctbxTwinLaws, self).__init__()
OV.registerFunction(self.run,False,'twin')
OV.registerFunction(self.run_from_gui,False,'twin')
def run_from_gui(self, personal=0):
print "Searching for Twin laws..."
OV.Cursor("busy", "Searching for Twin laws...")
personal=int(personal)
self.run(personal) #personal
OV.Cursor()
def run(self, personal=0):
global twin_laws_d
OlexCctbxAdapter.__init__(self)
if OV.GetParam('snum.refinement.use_solvent_mask'):
txt = "Sorry, using solvent masking and twinning is not supported yet."
print(txt)
html = "
%s
" %txt
write_twinning_result_to_disk(html)
OV.UpdateHtml()
return
if "_twin" in OV.HKLSrc():
print("It looks like your hklf file is already an hklf 5 format file") #this just checks for _twin and not for it actually being hklf5
return
print(">> Searching for Twin Laws <<")
use_image = ""
self.twin_laws_d = {}
law_txt = ""
l = 0
self.twin_law_gui_txt = ""
r_list=[]
self.filename = olx.FileName()
#class-wide variable initialisation
self.hklfile=OV.HKLSrc().rsplit('\\',1)[-1].rstrip(".hkl")
self.model=self.xray_structure()
hkl_sel_num=50
hkl,f_calc,f_obs,f_uncertainty,leastSquare=self.get_differences()
self.all_hkl=hkl
self.all_f_calc=f_calc
self.all_f_obs=f_obs
self.all_sigma=f_uncertainty
self.all_leastSquare=leastSquare
self.metrical=self.getMetrical()
self.metrical_inv=numpy.linalg.inv(self.metrical)
self.orthogonalization=numpy.reshape(numpy.array(self.model.unit_cell().orthogonalization_matrix()),(3,3))
self.orthogonalization_inv=numpy.linalg.inv(self.orthogonalization)
self.recip_orth=self.orthogonalization_inv.T
self.recip_orth_inv=numpy.linalg.inv(self.recip_orth)
self.overlap_threshold=OV.GetParam('snum.twinning.olex2.overlap_threshold')
self.number_laws=OV.GetParam('snum.twinning.olex2.number_laws')
rank=numpy.argsort(leastSquare)[::-1]
hkl_sel = numpy.copy(hkl[rank[:hkl_sel_num],:])
self.bad_fc=numpy.copy(f_calc[rank[:hkl_sel_num]])
self.bad_fo=numpy.copy(f_obs[rank[:hkl_sel_num]])
self.bad_hkl=hkl_sel
if personal==0:
twin_laws=self.find_twin_laws()
elif personal==1: #Angle-Axis
twin_laws=self.find_AA_twin_laws()
elif personal==2: #Sphere Search
twin_laws=self.find_SS_twin_laws()
else:
print ("Invalid parameter passed, personal=", personal)
ordered_twins=sorted(twin_laws,key=lambda x: x.rbasf[1], reverse=False)
ordered_twins=self.purge_duplicates(ordered_twins)
top_twins=ordered_twins[:10]
lawcount=0
for i, twin_law in enumerate(top_twins):
basf=twin_law.rbasf[0]
r=twin_law.rbasf[1]
r_diff=twin_law.rbasf[2]
lawcount += 1
filename="%s_twin%02d.hkl"%(self.hklfile, lawcount)
#self.make_hklf5(filename, twin_law, hkl, f_obs,f_uncertainty)
self.make_hklf5_from_file(twin_law,new_file=filename) #ZZZZ
self.twin_laws_d.setdefault(lawcount, {})
r_no, basf_no, f_data, history = self.run_twin_ref_shelx(twin_law.hkl_rotation.flatten(), basf)
try:
float(r)
except:
r = 0.99
r_list.append((r, lawcount, basf))
self.twin_laws_d[lawcount]['BASF'] = basf
self.twin_laws_d[lawcount]['r'] = r
self.twin_laws_d[lawcount]['r_diff'] = r_diff
self.twin_laws_d[lawcount]['matrix'] = twin_law.hkl_rotation.flatten()
make_twinning_gui(self.twin_laws_d)
def run_twin_ref_shelx(self, law, basf):
#law_ins = ' '.join(str(i) for i in law[:9])
#print "Testing: %s" %law_ins
#file_path = olx.FilePath()
#olx.Atreap("%s/notwin.ins" %file_path, b=True)
#OV.AddIns("TWIN " + law_ins+" 2")
#OV.AddIns("BASF %f"%basf)
#curr_prg = OV.GetParam('snum.refinement.program')
#curr_method = OV.GetParam('snum.refinement.method')
#curr_cycles = OV.GetParam('snum.refinement.max_cycles')
#OV.SetMaxCycles(5)
#if curr_prg != 'olex2.refine':
# OV.set_refinement_program(curr_prg, 'CGLS')
#OV.File("%s.ins" %self.filename)
rFile = open(olx.FileFull(), 'r')
f_data = rFile.readlines()
rFile.close()
#OV.SetParam('snum.init.skip_routine','True')
#OV.SetParam('snum.refinement.program','olex2.refine')
#OV.SetParam('snum.refinement.method','Gauss-Newton')
# try:
# from RunPrg import RunRefinementPrg
# a = RunRefinementPrg()
# self.R1 = a.R1
# self.wR2 = a.wR2
# his_file = a.his_file
#
# OV.SetMaxCycles(curr_cycles)
# OV.set_refinement_program(curr_prg, curr_method)
# finally:
# OV.SetParam('snum.init.skip_routine','False')
#r = olx.Lst("R1")
#olex_refinement_model = OV.GetRefinementModel(False)
#if olex_refinement_model.has_key('twin'):
# basf = olex_refinement_model['twin']['BASF'][0]
#else:
# basf = "n/a"
return None, None, f_data, None
def twinning_gui_def(self):
if not self.twin_law_gui_txt:
lines = ['search_for_twin_laws']
tools = ['search_for_twin_laws_t1']
else:
lines = ['search_for_twin_laws', 'twin_laws']
tools = ['search_for_twin_laws_t1', 'twin_laws']
tbx = {"twinning":
{"category":'tools',
'tbx_li':lines
}
}
tbx_li = {'search_for_twin_laws':{"category":'analysis',
'image':'cctbx',
'tools':['search_for_twin_laws_t1']
},
'twin_laws':{"category":'analysis',
'image':'cctbx',
'tools':['twin_laws']
}
}
tools = {'search_for_twin_laws_t1':{'category':'analysis',
'display':"%Search for Twin Laws%",
'colspan':1,
'hrefs':['spy.OlexCctbxTwinLaws()']
},
'twin_laws':
{'category':'analysis',
'colspan':1,
'before':self.twin_law_gui_txt,
}
}
return {"tbx":tbx,"tbx_li":tbx_li,"tools":tools}
def make_gui(self):
"""
works out the figure of merit
"""
q = numpy.zeros((15))
dcopy = numpy.zeros((numpy.shape(mdisag)[0]))
fom = 0.0
bc = 0
#bad = numpy.rint(hkl)+numpy.rint(v) - hkl
neighbours = list(itertools.combinations_with_replacement(numpy.arange(-1,2,dtype=numpy.float64),3))
bad = numpy.zeros((len(neighbours), numpy.shape(mdisag)[0], 3))
d1s = numpy.zeros((len(neighbours), numpy.shape(mdisag)[0]))
mdisag_rint = numpy.rint(mdisag)
for i, neighbour in enumerate(neighbours):
bad[i,:,:] = numpy.dot(mdisag_rint+neighbour - mdisag, GS.T)
d1s[i,:] = numpy.sqrt(numpy.sum(bad[i,:,:]*bad[i,:,:], axis=1))
neighbours_min = numpy.zeros((numpy.shape(mdisag)[0], 3), dtype=numpy.float64)
for i in range(numpy.shape(mdisag)[0]):
neighbours_min[i,:] = bad[numpy.argmin(d1s[:,i]),i,:]
bad_min = numpy.dot(mdisag_rint+neighbours_min - mdisag, GS.T)
d_min = numpy.sqrt(numpy.sum(bad_min*bad_min, axis=1))
dcopy = numpy.copy(d_min)
dsum = numpy.sum(dcopy)
for i, q_i in enumerate(q):
q[i]=dsum/(float(numpy.shape(mdisag)[0])-float(bc))
fom=q[i]
if (fom<.002):
break
else:
bc+=1
jp = numpy.argmax(dcopy)
dsum = dsum - dcopy[jp]
dcopy[jp] = 0.
fom=1000.*fom
q=1000.0*q
return fom
def get_differences(self):
""";
Returns the hkl, fcalc, fobs, uncertainty and the signed difference
"""
fot,fct=self.get_fo_sq_fc()
weights = self.compute_weights(fot, fct)
scale_factor = fot.scale_factor(fct, weights=weights)
fot = fot.apply_scaling(factor=1/(scale_factor))
leastSquare = (fot.data()-fct.norm().data())/fot.sigmas()
hkl=numpy.array(fot.indices())
fobs=numpy.array(fot.data())
fcalc=numpy.array(fct.norm().data())
funcertainty=numpy.array(fot.sigmas())
leastSquare=numpy.array(leastSquare)
return hkl,fcalc,fobs,funcertainty,leastSquare
def getMetrical(self):
model = self.model
gl=model.unit_cell().metrical_matrix()
g = numpy.zeros((3,3))
for i in range(3):
g[i,i] = gl[i]
g[0,1] = gl[3]
g[0,2] = gl[4]
g[1,2] = gl[5]
g[1,0] = gl[3]
g[2,0] = gl[4]
g[2,1] = gl[5]
return g
def get_integral_twin_laws(self):
twin_laws=[]
with HiddenPrints():
cctbx_twin_laws = cctbx_controller.twin_laws(self.reflections)
for twin_law in cctbx_twin_laws:
law = twin_law.as_double_array()[0:9]
law=numpy.around(numpy.reshape(numpy.array(law),(3,3)),decimals=3)
[basf, r,r_diff]=self.basf_estimate(law)
if(basf<0.02):
continue
twin_laws+=[twin_rules("Integral",[],law,0,0,[basf,r,r_diff])]
return twin_laws
def find_twin_laws(self):
hkl_all=self.all_hkl
f_calc=self.all_f_calc
f_obs=self.all_f_obs
hkl=self.bad_hkl
number_laws=OV.GetParam('snum.twinning.olex2.number_laws', 4)
twin_laws=[]
model=self.model
found_early=False
tests=False
if tests==True:
#This is a test function which replaces the lower ones
twin_laws+=self.find_twin_laws_tests()
threshold=0.01
size=5
if twin_laws:
found_early=True
else:
twin_laws+=self.get_integral_twin_laws()
if twin_laws:
twin_laws=self.purge_duplicates(twin_laws)
print ("Found Integral Twins")
if len(twin_laws)> new_methods: PART 1")
threshold=0.002
twin_laws+=self.find_twin_axes_sphere(hkl, threshold)
if twin_laws:
print("Twin laws found through new method")
twin_laws=self.purge_duplicates(twin_laws)
if len(twin_laws)> new_methods: PART 2")
threshold=0.01
twin_laws+=self.find_twin_axes_sphere(hkl, threshold)
if twin_laws:
print("Twin laws found through extended new method")
twin_laws=self.purge_duplicates(twin_laws)
if twin_laws:
found_early=True
if len(twin_laws)0.1)):
# skip non-integers
# This does not take into account the possible threshold variation, and should.
continue
hkl_new_i=numpy.rint(hkl_new_i)
loc=numpy.where((hkl[:,0]==hkl_new_i[0]) & (hkl[:,1]==hkl_new_i[1]) & (hkl[:,2]==hkl_new_i[2]))[0]
if loc:
twin_component[i]=Fc_sq[loc]
else:
index=flex.miller_index()
index.append(hkl_new_i.astype(int))
#this is a botch to get the symmetry/anomaly correct as I don't understand them
miller_set=miller.set(crystal_symmetry=fo2.crystal_symmetry(),
indices=index,
anomalous_flag=fo2.anomalous_flag())
#new_thing=miller.set(crystal_symmetry, index)
miller_set=miller_set.map_to_asu()
index=miller_set.indices()
hkl_symmetric=numpy.array(index)[0]
loc=numpy.where((hkl[:,0]==hkl_symmetric[0]) & (hkl[:,1]==hkl_symmetric[1]) & (hkl[:,2]==hkl_symmetric[2]))[0]
if loc:
twin_component[i]=Fc_sq[loc]
if numpy.max(twin_component)==0:
return [0,0.5,0] #basf 0, rmin=0.5, rdiff=0 - this mostly just indicates a bad twin law, although it should never reach here as laws without overlap should be ignored earlier.
basf_r=self.find_basf_r(twin_component)
return basf_r
def basf_estimate_short(self,twin_law):
hkl=self.bad_hkl
hkl_new=numpy.dot(twin_law, hkl.T).T
num_data=numpy.shape(hkl)[0]
twin_component=numpy.zeros(num_data)
hkl_all=self.all_hkl
fc_all=self.all_f_calc
fo2,fc = self.get_fo_sq_fc()
for i, hkl_new_i in enumerate(hkl_new): #no real way to bypass this for non-integer hkl due to needing to ignore non-integral hkl
if(numpy.any(numpy.abs(numpy.rint(hkl_new_i)-hkl_new_i)>0.1)):
# skip non-integers
# This does not take into account the possible threshold variation, and should.
continue
hkl_new_i=numpy.rint(hkl_new_i)
loc=numpy.where((hkl_all[:,0]==hkl_new_i[0]) & (hkl_all[:,1]==hkl_new_i[1]) & (hkl_all[:,2]==hkl_new_i[2]))[0]
if loc:
twin_component[i]=fc_all[loc]
else:
index=flex.miller_index()
index.append(hkl_new_i.astype(int))
#this is a botch to get the symmetry/anomaly correct as I don't understand them
miller_set=miller.set(crystal_symmetry=fo2.crystal_symmetry(),
indices=index,
anomalous_flag=fo2.anomalous_flag())
#new_thing=miller.set(crystal_symmetry, index)
miller_set=miller_set.map_to_asu()
index=miller_set.indices()
hkl_symmetric=numpy.array(index)[0]
loc=numpy.where((hkl_all[:,0]==hkl_symmetric[0]) & (hkl_all[:,1]==hkl_symmetric[1]) & (hkl_all[:,2]==hkl_symmetric[2]))[0]
if loc:
twin_component[i]=fc_all[loc]
if numpy.max(twin_component)==0:
return [0,0.5,0] #basf 0, rmin=0.5, rdiff=0 - this mostly just indicates a bad twin law, although it should never reach here as laws without overlap should be ignored earlier.
basf_r=self.find_basf_r(twin_component,short=True)
return basf_r
def find_basf_r(self,twin_component,short=False):
basf_lower=0
basf_upper=1
trials=0
max_trials=100
accuracy=0.01
r_lower=self.r_from_basf(basf_lower,twin_component,short)
r_upper=self.r_from_basf(basf_upper,twin_component,short)
r_0=r_lower
if r_upper>r_lower:
#prioritise lower over upper basf value
basf_minimum=basf_lower
r_minimum=r_lower
else:
basf_minimum=basf_upper
r_minimum=r_upper
#need to establish a minimum, which could be at 0, before we can employ the golden section search
while trialsaccuracy:
basf_new=basf_lower+2/(3+math.sqrt(5))*(basf_upper-basf_lower)
r_new=self.r_from_basf(basf_new,twin_component,short)
if r_newaccuracy:
basf_new=basf_lower+basf_upper-basf_minimum
r_new=self.r_from_basf(basf_new,twin_component,short)
if r_new<=r_minimum:
if basf_minimumbasf_new:
basf_upper=basf_minimum
r_upper=r_minimum
basf_minimum=basf_new
r_minimum=r_new
else:
print "basf equivalent, breaking"
break
else: #r_new>r_minimum
if basf_minimumbasf_new:
basf_lower=basf_new
r_lower=r_new
else:
print "basf equivalent, breaking"
break
trials +=1
r_difference=r_0-r_minimum
if r_difference<0.001:
return [0,r_0,0]
return [basf_minimum, r_minimum, r_difference]
def r_from_basf(self,basf,twin_component,short=False):
if short:
Fc_sq=self.bad_fc
Fo_sq=self.bad_fo
else:
Fc_sq=self.all_f_calc
Fo_sq=self.all_f_obs
fcalc=(1-basf)*Fc_sq+basf*twin_component
scale = numpy.sum(Fo_sq)/numpy.sum(fcalc)
fcalc = scale * fcalc
R = numpy.sum(numpy.abs(numpy.sqrt(numpy.maximum(Fo_sq,0))-numpy.sqrt(fcalc)))/numpy.sum(numpy.sqrt(numpy.maximum(Fo_sq,0)))
return R
def find_twin_axes(self, threshold,size,rotation_fraction):
hkl=self.all_hkl
model=self.model
metrical_matrix=self.metrical
metrical_inverse=self.metrical_inv
orthogonalization_matrix=self.orthogonalization
orthogonalization_inverse=self.orthogonalization_inv
reciprocal_orthogonalization_matrix=self.recip_orth
reciprocal_orthogonalization_inverse=self.recip_orth_inv
perfect_reflection_number=math.exp(-13)
possible_twin_laws=[]
#angle and the sine and cosine of that, for use in the rotation formula
base_rotation_angle=2.*math.pi/rotation_fraction
for twin_axis in self.all_axes(size): #itertools.product(numpy.arange(-size,size+1),numpy.arange(-size,size+1),range(size+1)):
reciprocal_law=False
##skip inverse axes
#if(twin_axis[2]==0):
#if(twin_axis[1]<0):
#continue
#if(twin_axis[1]==0):
#if(twin_axis[0]<=0):
#continue
#if(fractions.gcd(fractions.gcd(twin_axis[0],twin_axis[1]),twin_axis[2])!=1):
#continue
#using the rodrigues formula to generate the matrices, the O^-1RO for that in lattice coordinates
rotation_matrix_lattice_base=self.make_lattice_rotation(twin_axis,base_rotation_angle,orthogonalization_matrix,reciprocal_orthogonalization_matrix)
recip_rot_lat_base=self.make_lattice_rotation(twin_axis,base_rotation_angle,reciprocal_orthogonalization_matrix,reciprocal_orthogonalization_matrix)
new_hkl=hkl.copy()
rec_hkl=hkl.copy()
#this is the rotation matrix in the lattice coordinates! due to quirks and transforming a vector into cartesian space, rotating and
#transforming back being a O^-1 R O type, we can square and more for 'bigger' angles.
for r in numpy.arange(1,rotation_fraction): #every part of this loop relies on the previous completing the hkl rotations - this is for efficiency (about 10%)
#reciprocal axis
rec_hkl=numpy.dot(rec_hkl,recip_rot_lat_base.T)
rec_hkl_displacement=self.find_fom(rec_hkl)
#real axis
new_hkl=numpy.dot(rotation_matrix_lattice_base,new_hkl.T).T #correct
if not self.sufficient_overlaps(new_hkl, threshold) and not self.sufficient_overlaps(rec_hkl, threshold) :
continue
hkl_displacement=self.find_fom(new_hkl)
if (rec_hkl_displacementperfect_reflection_number):
reciprocal_rotation_lattice=numpy.linalg.matrix_power(recip_rot_lat_base,r)
rbasf=self.basf_estimate(reciprocal_rotation_lattice)
if rbasf[0]>1e-5:
possible_twin_laws+=[twin_rules("Reciprocal",twin_axis,numpy.around(reciprocal_rotation_lattice,decimals=3),r*base_rotation_angle,rec_hkl_displacement,rbasf=rbasf)]
reciprocal_law=True
if (hkl_displacementperfect_reflection_number):
rotation_matrix_lattice=numpy.linalg.matrix_power(rotation_matrix_lattice_base,r)
rbasf=self.basf_estimate(rotation_matrix_lattice)
if rbasf[0]>1e-5:
possible_twin_laws+=[twin_rules("Direct",twin_axis,numpy.around(rotation_matrix_lattice,decimals=3),r*base_rotation_angle,hkl_displacement,rbasf=rbasf)]
return possible_twin_laws
def make_lattice_rotation(self, axis, angle,axis_orthog, reciprocal_orthogonalization_matrix):
cosine_value=math.cos(angle)
sine_value=math.sin(angle)
reciprocal_orthogonalization_inverse=numpy.linalg.inv(reciprocal_orthogonalization_matrix)
axis_cartesian=numpy.dot(axis_orthog,axis)
axis_unit_cartesian=axis_cartesian/self.size_of_3d_vector(axis_cartesian)
cross_product_matrix=numpy.array([[0,-axis_unit_cartesian[2],axis_unit_cartesian[1]],[axis_unit_cartesian[2],0,-axis_unit_cartesian[0]],[-axis_unit_cartesian[1],axis_unit_cartesian[0],0]],dtype=float)
matrix=numpy.eye(3)+sine_value*cross_product_matrix+(1-cosine_value)*numpy.linalg.matrix_power(cross_product_matrix,2)
matrix_lattice=numpy.dot(reciprocal_orthogonalization_inverse,numpy.dot(matrix,reciprocal_orthogonalization_matrix))
return matrix_lattice
def make_real_lattice_rotation(self, axis, angle): #believe this is actually the euclidean rotation - thus why I called it 'real'
cosine_value=math.cos(angle)
sine_value=math.sin(angle)
cross_product_matrix=numpy.array([[0,-axis[2],axis[1]],[axis[2],0,-axis[0]],[-axis[1],axis[0],0]],dtype=float)
matrix=numpy.eye(3)+sine_value*cross_product_matrix+(1-cosine_value)*numpy.linalg.matrix_power(cross_product_matrix,2)
return matrix
def find_fom(self, falsehkl):
metrical=self.metrical_inv
if all(numpy.sum(metrical, axis=1)>=0): #this is the condition which dictates rounding to the nearest integer will also give the closest reciprocal lattice point.
displacement = (falsehkl+0.5)%1-0.5
distances=numpy.sqrt(numpy.multiply(displacement,numpy.dot(metrical,displacement.T).T).sum(1)) # distances=numpy.linalg.norm(numpy.dot(orthogonalization.T,displacement.T),axis=0) is alternative but slower
else:
hkl_dropped=numpy.floor(falsehkl)
hkl_remainder=falsehkl%1-1
adjacents=numpy.array([[0,0,0],[1,0,0],[0,1,0],[1,1,0],[0,0,1],[1,0,1],[0,1,1],[1,1,1]])
distances=numpy.full(numpy.shape(falsehkl)[0],1000)
for i in numpy.arange(0,8):
displacement=hkl_remainder+adjacents[i]
#hkl_adjacent=hkl_dropped+adjacents[i]
#displacement=falsehkl-hkl_adjacent
size=numpy.sqrt(numpy.multiply(displacement,numpy.dot(metrical,displacement.T).T).sum(1))
distances=numpy.minimum(distances,size)
sortedDist=numpy.sort(distances)
filtered=sortedDist[:-15]
return numpy.average(filtered)
def find_number_overlaps(self, falsehkl, orthogonalization, threshold):
metrical=self.metrical_inv
displacement = (falsehkl+0.5)%1-0.5
threshold2=threshold**2
overlaps=0
for line in displacement:
size=numpy.dot(line,numpy.dot(metrical,line))
if sizethreshold2:
overlaps-=1
if overlaps<35:
return 0
return overlaps
def make_hklf5(self, filename, twin_law_full, hkl, fo,sigmas):
"""
convert hklf4 file to hklf5 file
"""
#Pulled directly from Pascal's, then edited to generate its own second component hkl, as some files don't have avlues for all
twin_law=twin_law_full.hkl_rotation
basf=twin_law_full.rbasf[0]
cell=self.cell
hklf = open(filename,'w')
hkl_new = numpy.dot(twin_law, hkl.T).T
rounded_hkl_new=numpy.rint(hkl_new).astype(int)
scale = 99999/numpy.max(fo) # keep Fo in the scale of F8
check1=True
for i, hkl_new_i in enumerate(hkl_new):
if(numpy.any(numpy.abs(numpy.rint(hkl_new_i)-hkl_new_i)>0.1)):
hklf.write("%4d%4d%4d%8d%8d%4d\n"%(hkl[i,0],hkl[i,1], hkl[i,2], fo[i]*scale, sigmas[i]*scale, 1))
continue
# looking where is the overlap
diff = numpy.sum(numpy.abs(hkl_new[i] - rounded_hkl_new[i]))
if(diff<0.1): #threshold prior default is 0.1
# adding contribution from overlap
hklf.write("%4d%4d%4d%8d%8d%4d\n"%(rounded_hkl_new[i,0],rounded_hkl_new[i,1], rounded_hkl_new[i,2], fo[i]*scale, sigmas[i]*scale, -2))
hklf.write("%4d%4d%4d%8d%8d%4d\n"%(hkl[i,0],hkl[i,1], hkl[i,2], fo[i]*scale, sigmas[i]*scale, 1))
else:
hklf.write("%4d%4d%4d%8d%8d%4d\n"%(hkl[i,0],hkl[i,1], hkl[i,2], fo[i]*scale, sigmas[i]*scale, 1))
hklf.write("%4d%4d%4d\n"%(0,0,0))
hklf.write("CELL %s %s %s %s %s %s\n"%(cell[0],cell[1],cell[2],cell[3],cell[4],cell[5]))
hklf.write("REM TWIN %s\n"%format_twin_string_from_law(twin_law))
hklf.write("BASF %6.4f\n"%basf)
hklf.write("HKLF 5")
hklf.close()
def make_hklf5_from_file(self, twin_law_full, filename=None,new_file=None, threshold=0.002):
"""
convert hklf4 file to hklf5 file using the file as a base
"""
if not filename:
filename=self.hklfile+'.hkl' #OV.HKLSrc().rsplit('\\',1)[-1]
if not new_file:
new_file=self.hklfile+'twinX.hkl'
metrical=self.getMetrical()
metrical_inv=numpy.linalg.inv(metrical)
twin_law=twin_law_full.hkl_rotation
hkl_file_old=list(olex_hkl.Read(filename))
hkl_file_new=[]
for line in hkl_file_old:
line_as_list=list(line)
[h,k,l,fo,sig,batch,nul2]=line_as_list
hkl=[h,k,l]
hkl_new = numpy.dot(twin_law, hkl)
hkl_new_rounded=numpy.rint(hkl_new).astype(int)
#difference=hkl_new_rounded-hkl_new
#distance=numpy.sqrt(numpy.dot(difference,numpy.dot(metrical_inv,difference)))
#if distance0.1)):
diff = numpy.sum(numpy.abs(numpy.rint(hkl_new)-hkl_new))
if diff<0.1:
hkl_file_new+=[(hkl_new_rounded[0],hkl_new_rounded[1],hkl_new_rounded[2],fo,sig,-2)]
hkl_file_new+=[(h,k,l,fo,sig,1)]
try:
olex_hkl.Write(new_file,hkl_file_new)
except Exception:
pass
basf=twin_law_full.rbasf[0]
cell=self.cell
hklf = open(new_file,'a')
hklf.write("%4d%4d%4d\n"%(0,0,0))
hklf.write("CELL %s %s %s %s %s %s\n"%(cell[0],cell[1],cell[2],cell[3],cell[4],cell[5]))
hklf.write("REM TWIN %s\n"%format_twin_string_from_law(twin_law))
hklf.write("BASF %6.4f\n"%basf)
hklf.write("HKLF 5")
hklf.close()
def extend_hklf5(self, twin_law_full,new_component, filename=None,new_file=None, threshold=0.002, component_base=1):
"""
adds an extra twin law to a hklf 5 or 4 file. The twin_law_full rotates the component_base component, and will be checked against that component only. The new component has integer new_component, which should differ from any other batch numbers
"""
if not filename:
filename=self.hklfile+'.hkl'
if not new_file:
new_file=self.hklfile+'twinX.hkl'
metrical=self.getMetrical()
metrical_inv=numpy.linalg.inv(metrical)
twin_law=twin_law_full.hkl_rotation
hkl_file_old=list(olex_hkl.Read(filename))
hkl_file_new=[]
for line in hkl_file_old:
line_as_list=list(line)
[h,k,l,fo,sig,batch,nul2]=line_as_list
hkl=[h,k,l]
hkl_new = numpy.dot(twin_law, hkl)
hkl_new_rounded=numpy.rint(hkl_new).astype(int)
#difference=hkl_new_rounded-hkl_new
#distance=numpy.sqrt(numpy.dot(difference,numpy.dot(metrical_inv,difference)))
#if distance0.1)):
diff = numpy.sum(numpy.abs(numpy.rint(hkl_new)-hkl_new))
if diff<0.1:
hkl_file_new+=[(hkl_new_rounded[0],hkl_new_rounded[1],hkl_new_rounded[2],fo,sig,-new_component)]
hkl_file_new+=[(h,k,l,fo,sig,1)]
try:
olex_hkl.Write(new_file,hkl_file_new)
except Exception:
pass
basf=twin_law_full.rbasf[0]
cell=self.cell
hklf = open(new_file,'a')
hklf.write("%4d%4d%4d\n"%(0,0,0))
hklf.write("CELL %s %s %s %s %s %s\n"%(cell[0],cell[1],cell[2],cell[3],cell[4],cell[5]))
hklf.write("REM TWIN %s\n"%format_twin_string_from_law(twin_law))
hklf.write("BASF %6.4f\n"%basf)
hklf.write("HKLF 5")
hklf.close()
def do_rounding(self,twin_laws):
for twin_law in twin_laws:
matrix=twin_law.hkl_rotation
for i in numpy.arange(0,3):
for j in numpy.arange(0,3):
item=matrix[i,j]
if (abs(1.0-item)<0.01):
matrix[i,j]=1.0
elif (abs(-1.0-item)<0.01):
matrix[i,j]=-1.0
elif (abs(0.0-item)<0.01):
matrix[i,j]=0.0
elif (abs(0.5-item)<0.01):
matrix[i,j]=0.5
twin_law.hkl_rotation=matrix
return twin_laws
def purge_duplicates(self, twin_laws):
twin_laws=self.check_basf(twin_laws)
twin_laws=sorted(twin_laws,key=lambda x: x.rbasf[1], reverse=False)
non_duplicate_twin_laws=[]
fo2 = self.reflections.f_sq_obs_filtered
symmetry_ops=fo2.crystal_symmetry().space_group().all_ops()#list of symmetries to be retrieved with .as_double_array() and mapped to actual 3x3 matrices.
#However, they have 3 more numbers than expected - the last 3 are the +- for translations I think. Sadly, due to inversion symmetry, there are twice as many matrices as actual symmetry equivalents we need to care about.
symmetry_matrices=[]
for matrix in symmetry_ops:
symmetry_matrices+=[numpy.reshape(matrix.as_double_array()[0:9], (3,3))]
#assumption - only the first half are unique, the rest represent inversion symmetries, which are inherantly discarded by only taking positive axes.
#additionally, the first is the identity, so is also discarded
#num_matrix=len(symmetry_matrices)
#symmetry_matrices=symmetry_matrices[0:int(num_matrix/2)] #changed from 1 to 0 so it purges pure duplicates
#I have now removed the removal of inversion, seeing as I'm using a different method it does not apply
for i, twin_law in enumerate(twin_laws):
if i==0:
non_duplicate_twin_laws+=[twin_law]
continue
duplicate=False
for matrix in symmetry_matrices:
rotated_twin=numpy.dot(matrix,twin_law.hkl_rotation)
for j in range(0,i):
if numpy.allclose(rotated_twin, twin_laws[j].hkl_rotation,atol=5e-3): #same up to 2dp.
duplicate=True
if duplicate:
break;
if duplicate:
break;
if not duplicate:
non_duplicate_twin_laws+=[twin_law]
return non_duplicate_twin_laws
def all_axes(self, max_index):
fo2 = self.reflections.f_sq_obs_filtered
indexes=flex.miller_index()
for twin_axis in itertools.product(numpy.arange(-max_index,max_index+1),numpy.arange(-max_index,max_index+1),range(max_index+1)):
indexes.append(twin_axis)
miller_set=miller.set(crystal_symmetry=fo2.crystal_symmetry(),
indices=indexes,
anomalous_flag=fo2.anomalous_flag())
miller_set=miller_set.map_to_asu()
asu_indexes=numpy.array(miller_set.indices())
asu_unique=numpy.unique(asu_indexes,axis=0)
for i in range(asu_unique.shape[0]):
if all(asu_unique[i]==[0,0,0]) or fractions.gcd(asu_unique[i][0],fractions.gcd(asu_unique[i][1],asu_unique[i][2]))!=1:
continue
yield asu_unique[i]
def find_twin_laws_tests(self):
filename=OV.FileName()+'_test_records.txt'
open(filename,'w').close()
threshold_finding=0.002
threshold_using=0.1
size_limit=5
RF=2
twin_laws=[]
import cProfile, pstats, StringIO
sortby = 'cumulative'
pr = cProfile.Profile()
pr.enable()
laws=self.get_integral_twin_laws()
pr.disable()
s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats(10)
testFile=open(filename,'a')
testFile.write("CCtbx Integral Twins\n")
testFile.write("Laws found: "+str(len(laws))+"\n")
self.tests_writer(laws,testFile)
testFile.write(s.getvalue())
testFile.close()
twin_laws+=laws
pr = cProfile.Profile()
pr.enable()
laws=self.find_twofold_axes_sphere(hkl, 0.01)
pr.disable()
s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats(10)
testFile=open(filename,'a')
testFile.write("Sphere Search\n")
testFile.write("threshold: "+str(threshold_finding)+"\n")
testFile.write("Laws found: "+str(len(laws))+"\n")
self.tests_writer(laws,testFile)
testFile.write(s.getvalue())
testFile.close()
twin_laws+=laws
pr = cProfile.Profile()
pr.enable()
laws=self.find_twin_axes(threshold_finding, size_limit, RF)
pr.disable()
s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats(10)
testFile=open(filename,'a')
testFile.write("Angle-Axis Search\n")
testFile.write("Threshold: "+str(threshold_finding)+", size: "+str(size_limit)+", Rotation Fraction: "+str(RF)+"\n")
testFile.write("Laws found: "+str(len(laws))+"\n")
self.tests_writer(laws,testFile)
testFile.write(s.getvalue())
testFile.close()
#print s.getvalue()
twin_laws+=laws
threshold_finding=0.1
size_limit=1
pr = cProfile.Profile()
pr.enable()
laws=self.find_twin_axes(threshold_finding, size_limit, RF)
pr.disable()
s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats(10)
testFile=open(filename,'a')
testFile.write("Angle-Axis Search\n")
testFile.write("Threshold: "+str(threshold_finding)+", size: "+str(size_limit)+", Rotation Fraction: "+str(RF)+"\n")
testFile.write("Laws found: "+str(len(laws))+"\n")
self.tests_writer(laws,testFile)
testFile.write(s.getvalue())
testFile.close()
#print s.getvalue()
twin_laws+=laws
threshold_finding=0.002
hkl=self.bad_hkl
pr = cProfile.Profile()
pr.enable()
laws=self.find_twin_axes_sphere(hkl, threshold_finding)
pr.disable()
s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats(10)
testFile=open(filename,'a')
testFile.write("Sphere Search\n")
testFile.write("threshold: "+str(threshold_finding)+"\n")
testFile.write("Laws found: "+str(len(laws))+"\n")
self.tests_writer(laws,testFile)
testFile.write(s.getvalue())
testFile.close()
twin_laws+=laws
threshold_finding=0.01
pr = cProfile.Profile()
pr.enable()
laws=self.find_twin_axes_sphere(hkl, threshold_finding)
pr.disable()
s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats(10)
testFile=open(filename,'a')
testFile.write("Sphere Search\n")
testFile.write("threshold: "+str(threshold_finding)+"\n")
testFile.write("Laws found: "+str(len(laws))+"\n")
self.tests_writer(laws,testFile)
testFile.write(s.getvalue())
testFile.close()
twin_laws+=laws
RF=24
pr = cProfile.Profile()
pr.enable()
laws=self.find_twin_axes(threshold_finding, size_limit, RF)
pr.disable()
s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats(10)
testFile=open(filename,'a')
testFile.write("Angle-Axis Search\n")
testFile.write("Threshold: "+str(threshold_finding)+", size: "+str(size_limit)+", Rotation Fraction: "+str(RF)+"\n")
testFile.write("Laws found: "+str(len(laws))+"\n")
self.tests_writer(laws,testFile)
testFile.write(s.getvalue())
testFile.close()
twin_laws+=laws
threshold_finding=0.1
pr = cProfile.Profile()
pr.enable()
laws=self.find_twin_axes_sphere(hkl, threshold_finding)
pr.disable()
s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats(10)
testFile=open(filename,'a')
testFile.write("Sphere Search\n")
testFile.write("threshold: "+str(threshold_finding)+"\n")
testFile.write("Laws found: "+str(len(laws))+"\n")
self.tests_writer(laws,testFile)
testFile.write(s.getvalue())
testFile.close()
twin_laws+=laws
RF=24
size_limit=12
threshold_finding=0.01
pr = cProfile.Profile()
pr.enable()
laws=self.find_twin_axes(threshold_finding, size_limit, RF)
pr.disable()
s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats(10)
testFile=open(filename,'a')
testFile.write("Angle-Axis Search\n")
testFile.write("Threshold: "+str(threshold_finding)+", size: "+str(size_limit)+", Rotation Fraction: "+str(RF)+"\n")
testFile.write("Laws found: "+str(len(laws))+"\n")
self.tests_writer(laws,testFile)
testFile.write(s.getvalue())
testFile.close()
twin_laws+=laws
return twin_laws
def tests_writer(self,laws,testFile):
laws=self.purge_duplicates(laws)
for law in laws:
matrix=law.hkl_rotation
basf=law.rbasf[0]
r_red=law.rbasf[1:]
testFile.write(str(matrix)+"\n")
testFile.write("Basf: "+str(basf)+"\n")
testFile.write("R-reductions: "+str(r_red)+"\n")
def find_twin_axes_sphere(self, hkl, threshold,size=10):
model=self.model
twin_laws=[]
recip_orth=self.recip_orth
metrical_matrix=self.metrical
metrical_inverse=self.metrical_inv
orthogonalization_inverse=self.recip_orth_inv
a_star=recip_orth.T[0]
b_star=recip_orth.T[1]
c_star=recip_orth.T[2]
b_star_cross_c_star=numpy.array(self.cross_product(b_star,c_star))
c_star_cross_a_star=numpy.array(self.cross_product(c_star,a_star))
a_star_cross_b_star=numpy.array(self.cross_product(a_star,b_star))
hkl_choice=hkl[:size]
viable_rotation_points=[]
for i,vec0 in enumerate(hkl_choice):
if len(twin_laws)>3:
print ("Twin laws found on try " + str(i))
break
viable_rotation_points+=[self.find_same_distance_points(vec0,threshold)]
viable_rotation_points_0=viable_rotation_points[i]
v=vec0
#all_v_minus_w=v-viable_rotation_points_0
v_euclid=numpy.dot(recip_orth,v)
j=-1
while j1 or abs(cospq_angle)>1:
continue
vw_angle=numpy.arccos(cosvw_angle)
pq_angle=numpy.arccos(cospq_angle)
#take positive as anticlockwise and negative as clockwise
if abs(vw_angle-pq_angle)<0.0175: #needs to be larger than 0.012 so put at 1 degree for now
v_w_dir=self.cross_product(v_per,w_per)
p_q_dir=self.cross_product(p_per,q_per)
if numpy.dot(v_w_dir,p_q_dir)<0:
#they rotate in opposite directions
continue
elif numpy.dot(v_w_dir,unit_axis)<0:
vw_angle*=-1
pq_angle*=-1
#the above should work but takes waaaay too long
average_angle=(vw_angle+pq_angle)/2
rotation=self.make_real_lattice_rotation(unit_axis, average_angle)
rotation_lattice=numpy.dot(orthogonalization_inverse,numpy.dot(rotation,recip_orth))
prot=numpy.dot(rotation_lattice,p)
vrot=numpy.dot(rotation_lattice,v)
if any(prot-q>0.1) or any(vrot-w>0.1):
rotation_lattice=numpy.linalg.inv(rotation_lattice)
prot=numpy.dot(rotation_lattice,p)
vrot=numpy.dot(rotation_lattice,v)
if any(prot-q>0.1) or any(vrot-w>0.1):
continue
duplicate=False
for twin_law in twin_laws:
if numpy.allclose(twin_law.hkl_rotation,rotation_lattice):
duplicate=True
if duplicate:
continue
#reciprocal axis
rotated_hkl=numpy.dot(hkl,rotation_lattice.T)
if not self.sufficient_overlaps(rotated_hkl, threshold):
continue
hkl_displacement=self.find_fom(rotated_hkl)
if (hkl_displacement1e-10:
twin_laws+=[twin_rules("Alt",numpy.dot(orthogonalization_inverse,unit_axis),rotation_lattice,average_angle,hkl_displacement,rbasf)]
twin_laws=self.do_rounding(twin_laws)
twin_laws=self.purge_duplicates(twin_laws)
return twin_laws
def find_twofold_axes_sphere(self,hkl,threshold,size=10):
model=self.model
twin_laws=[]
recip_orth=self.recip_orth
metrical_matrix=self.metrical
metrical_inverse=self.metrical_inv
recip_orth_inv=self.recip_orth_inv
number_laws=self.number_laws
a_star=recip_orth.T[0]
b_star=recip_orth.T[1]
c_star=recip_orth.T[2]
b_star_cross_c_star=numpy.array(self.cross_product(b_star,c_star))
c_star_cross_a_star=numpy.array(self.cross_product(c_star,a_star))
a_star_cross_b_star=numpy.array(self.cross_product(a_star,b_star))
maxRdrop=0
hkl_choice=hkl[:size]
viable_rotation_points=[]
#for vec in hkl_choice:
#viable_rotation_points+=[self.find_same_distance_points(vec,threshold)]
#R=I+sintheta K+(1-costheta )K^2
#R=I+2K^2
for i,v in enumerate(hkl_choice):
if len(twin_laws)>number_laws:
print ("Twin laws found on try " + str(i))
break
viable_rotation_points+=[self.find_same_distance_points(v,threshold)]
viable_rotation_points_0=viable_rotation_points[i]
for w in viable_rotation_points_0:
if all(w==-v):
continue
axis=v+w
axis_euclid=numpy.dot(recip_orth,axis)
axis_unit=axis_euclid/self.size_of_3d_vector(axis_euclid)
k=numpy.array([[0,-axis_unit[2],axis_unit[1]],[axis_unit[2],0,-axis_unit[0]],[-axis_unit[1],axis_unit[0],0]])
k2=numpy.dot(k,k)
rot_mat_euclid=numpy.eye(3)+2*k2
rotation_lattice=numpy.dot(recip_orth_inv,numpy.dot(rot_mat_euclid,recip_orth))
duplicate=False
for twin_law in twin_laws:
if numpy.allclose(twin_law.hkl_rotation,rotation_lattice):
duplicate=True
if duplicate:
continue
rotated_hkl=numpy.dot(hkl,rotation_lattice.T)
if not self.sufficient_overlaps(rotated_hkl, threshold):
continue
hkl_displacement=self.find_fom(rotated_hkl)
if (hkl_displacement1e-10 and rbasf[2]>maxRdrop/2:
twin_laws+=[twin_rules("Alt",v+w,rotation_lattice,numpy.pi,hkl_displacement,rbasf)]
maxRdrop=max(maxRdrop,rbasf[2])
twin_laws=self.do_rounding(twin_laws)
twin_laws=self.purge_duplicates(twin_laws)
return twin_laws
def find_same_distance_points(self, hkl, threshold):
#finds points with the same d-spacing as a reciprocal lattice point hkl
model=self.model
rec_metrical=model.unit_cell().reciprocal_metrical_matrix()
metrical=model.unit_cell().metrical_matrix()
orthogonalization=numpy.linalg.inv(numpy.reshape(numpy.array(model.unit_cell().orthogonalization_matrix()),(3,3)))
a_star=orthogonalization[0]
b_star=orthogonalization[1]
c_star=orthogonalization[2]
mod_a_star=numpy.sqrt(rec_metrical[0])
mod_b_star=numpy.sqrt(rec_metrical[1])
mod_c_star=numpy.sqrt(rec_metrical[2])
a_star_dot_b_star=rec_metrical[3]
a_star_dot_c_star=rec_metrical[4]
b_star_dot_c_star=rec_metrical[5]
mod_a_square=metrical[0]
mod_b_square=metrical[1]
mod_c_square=metrical[2]
a_dot_b=metrical[3]
a_dot_c=metrical[4]
b_dot_c=metrical[5]
size_hkl=self.size_of_3d_vector(numpy.dot(orthogonalization.T,hkl))
max_distance=size_hkl+threshold
same_distance_points=[]
#The initial method to find the ranges was underestimating. Trying a new one.
h_lambda=[mod_a_square,a_dot_b,a_dot_c]
k_lambda=[a_dot_b,mod_b_square,b_dot_c]
l_lambda=[a_dot_c,b_dot_c,mod_c_square]
lambda_h=1/max_distance*(self.size_of_3d_vector(numpy.dot(orthogonalization.T,h_lambda)))
lambda_k=1/max_distance*(self.size_of_3d_vector(numpy.dot(orthogonalization.T,k_lambda)))
lambda_l=1/max_distance*(self.size_of_3d_vector(numpy.dot(orthogonalization.T,l_lambda)))
#try to get the maximum h-value
max_h=numpy.floor(h_lambda[0]/lambda_h)
max_k=numpy.floor(k_lambda[1]/lambda_k)
max_l=numpy.floor(l_lambda[2]/lambda_l)
for h in range(0,int(max_h)+1):
for k in range(-int(max_k),int(max_k)+1):
discriminant_addition=-(h**2*mod_a_star**2+k**2*mod_b_star**2+2*h*k*a_star_dot_b_star)*mod_c_star**2+(h*a_star_dot_c_star+k*b_star_dot_c_star)**2
upper_discriminant=max_distance**2*mod_c_star**2+discriminant_addition
lower_discriminant=(max_distance-2*threshold)**2*mod_c_star**2+discriminant_addition
#still sometimes has upper <0 even when a twin laws is there. Needs work
if upper_discriminant<0:
continue
l_max=numpy.trunc((-h*a_star_dot_c_star-k*b_star_dot_c_star+math.sqrt(upper_discriminant))/mod_c_star**2)
l_min=numpy.trunc((-h*a_star_dot_c_star-k*b_star_dot_c_star-math.sqrt(upper_discriminant))/mod_c_star**2)
if lower_discriminant<0:
possible_l=range(int(l_min),int(l_max+1))
else:
l_max_lower=numpy.trunc((-h*a_star_dot_c_star-k*b_star_dot_c_star+math.sqrt(lower_discriminant))/mod_c_star**2)
l_min_upper=numpy.trunc((-h*a_star_dot_c_star-k*b_star_dot_c_star-math.sqrt(lower_discriminant))/mod_c_star**2)
possible_l=range(int(l_min),int(l_min_upper)+1)+range(int(l_max_lower),int(l_max+1))
for l in possible_l:
size_h=self.size_of_3d_vector(numpy.dot(orthogonalization.T,[h,k,l]))
if hkl[0]==h and hkl[1]==k and hkl[2]==l:
continue
if abs(size_hkl-size_h)1e-15:
twin_laws_2+=[twin_law]
continue
rbasf=self.basf_estimate(twin_law.hkl_rotation)
twin_law.rbasf=rbasf
if rbasf[0]>1e-15:
twin_laws_2+=[twin_law]
return twin_laws_2
def cross_product(self,x,y):
z=[0,0,0]
z[0]=x[1]*y[2]-x[2]*y[1]
z[1]=x[2]*y[0]-x[0]*y[2]
z[2]=x[0]*y[1]-x[1]*y[0]
return z
def size_of_3d_vector(self,x):
z=0
z+=x[0]*x[0]
z+=x[1]*x[1]
z+=x[2]*x[2]
z=z**0.5
return z
def test_law(self,twin_law,threshold):
new_hkl=numpy.dot(twin_law,self.bad_hkl)
if self.sufficient_overlaps(new_hkl,threshold)==0:
return None
fom=self.find_fom()
if fom0.05)):
print ("Using twin law: %s" %twin_law_disp)
print ("This is a non-integral twin law, and a corresponding hklf 5 fomrat file has been made.")
# non integral twin law, need hklf5
OV.DelIns("TWIN")
olx.HKLF(2)
OV.DelIns("BASF")
OV.AddIns("BASF %f"%basf)
hklname="%s_twin%02d.hkl"%(OV.HKLSrc().rsplit('\\',1)[-1].rstrip(".hkl"), int(run_number))
OV.HKLSrc(hklname)
else:
print ("Using twin law: %s" %twin_law_disp)
print ("This is an integral twin law, and twinning will be handled by the refinement program.")
OV.DelIns("TWIN")
olx.HKLF(0)
OV.DelIns("BASF")
OV.AddIns("BASF %f"%basf)
OV.AddIns("TWIN %s"%twin_law_disp)
OV.UpdateHtml()
OV.registerFunction(on_twin_image_click)
def write_twin_images_to_disk(name, fn_base):
l = ['on', 'off']
for state in l:
n = '%s%s.png'%(name,state)
im_data = OlexVFS.read_from_olex(n)
image_name = fn_base+n
with open (image_name, 'wb') as wFile:
wFile.write(im_data)
return image_name
def reset_twin_law_img():
global twin_laws_d
olex_refinement_model = OV.GetRefinementModel(False)
if 'twin' in olex_refinement_model:
c = olex_refinement_model['twin']['matrix']
curr_law = []
for row in c:
for el in row:
curr_law.append(el)
for i in xrange(3):
curr_law.append(0.0)
curr_law = tuple(curr_law)
else:
curr_law = (1, 0, 0, 0, 1, 0, 0, 0, 1)
for law in twin_laws_d:
name = twin_laws_d[law]['name']
matrix = twin_laws_d[law]['law']
if curr_law == matrix:
OV.CopyVFSFile("%son.png" %name, "%s.png" %name,2)
else:
OV.CopyVFSFile("%soff.png" %name, "%s.png" %name,2)
OV.UpdateHtml()
OV.registerFunction(reset_twin_law_img)
OlexCctbxTwinLaws_instance = OlexCctbxTwinLaws()
#taken from stackoverflow 8391411
class HiddenPrints:
def __enter__(self):
self._original_stdout = sys.stdout
sys.stdout = open(os.devnull, 'w')
def __exit__(self, exc_type, exc_val, exc_tb):
try:
sys.stdout.close()
sys.stdout = self._original_stdout
except:
pass
def round_matrix_elements(matrix):
round_tol = 0.01
round_val_l = [0,0.25,0.5,0.75,1,0.333,0.666]
round_disp_l = ['0','1/4','1/2','3/4','1','1/3','2/3']
round_l = zip(round_val_l, round_disp_l)
new_matrix = []
for item in matrix:
try:
item = round(item,3)
except:
m.append(item)
continue
sign = ""
if abs(item) != item:
sign = "-"
if str(item) == "0.0":
item = "0"
elif str(item) == "1.0":
item = "1"
elif str(item) == "-1.0":
item = "-1"
else:
for val,disp in round_l:
if val-round_tol < abs(item) < val+round_tol:
item = sign+disp
break
new_matrix.append(item)
return new_matrix
def find_2_fold_olex2():
import gui.tools
cmd = "TestR"
res = filter(None, gui.tools.scrub(cmd))
if "batch" not in " ".join(res).lower():
return
matrix = res[-3:]
i = 0
for line in res:
if line.startswith('wR2'):
basf = res[i+1].split()[2].strip()
i += 1
basf = 0.2
r = 0.05
r_diff = -0.03
d = {}
d.setdefault(1, {})
matrix = [float(i) for i in " ".join(matrix).split()]
d[1]['matrix'] = matrix
d[1]['BASF'] = basf
d[1]['r'] = r
d[1]['r_diff'] = r_diff
make_twinning_gui(d)
OV.registerFunction(find_2_fold_olex2)
def make_law_images(twin_law, lawcount):
global twin_laws_d
from ImageTools import *
IT = ImageTools()
from PilTools import MatrixMaker
MM = MatrixMaker()
bg_col = OV.GetParam('gui.html.table_bg_colour')
bg_col_img = IT.RGBToHTMLColor(IT.adjust_colour(bg_col.rgb,luminosity=1.3))
font_col = "#444444"
font_col_basf = "#447744"
basf = twin_law['BASF']
r = twin_law['r']
r_diff = twin_law['r_diff']
matrix = twin_law['matrix']
name = "law%s" %lawcount
if basf == "n/a":
font_col_basf = OV.GetParam('gui.blue').rgb
elif float(basf) < 0.1:
font_col_basf = OV.GetParam('gui.red').rgb
basf = "%.2f" %float(basf)
else:
font_col_basf = OV.GetParam('gui.green_text').rgb
basf = "%.2f" %float(basf)
txt = [{'txt':"R=%.2f%%, -%.2f%%" %((float(r)*100),(float(r_diff)*100)),
'font_colour':font_col},
{'txt':"basf=%s" %str(basf),
'font_colour':font_col_basf}]
states = ['on', 'off', 'hover', 'down']
rounded_matrix = round_matrix_elements(matrix)
for state in states:
image_name, img = MM.make_3x3_matrix_image(name, rounded_matrix, txt, state, bar_col=font_col_basf, bgcolor=bg_col_img)
twin_laws_d[lawcount].setdefault('law_image_name', image_name)
def make_twinning_gui(laws):
font_col = "#444444"
font_col_basf = "#447744"
bg_col = OV.GetParam('gui.html.table_bg_colour')
global twin_laws_d
twin_laws_d = laws
r_list = []
for count in laws:
twin_law_d = laws[count]
make_law_images(twin_law_d, count)
r_list.append((twin_law_d['r'], count, twin_law_d['BASF']))
history = ""
ins_file = ""
law_txt = ""
i = 0
html = "