def _testspherical_harmonic_translation_and_rotation(BW=6): from pprint import pprint from KGeometry import Vector harmonics=[[(1,1),(0.0,-1.0)],[(5,1),(0.0,0.1)]] #pprint(harmonics) new_zvect=Vector((0,0,1)) # The direction of the new z-axis. new_xvect=Vector((1,0,0)) # The direction of the new x-axis. new_origin=Vector((0.0,0,0.5)) # The new origin forward=spherical_harmonic_translation_and_rotation(harmonics, new_zvect=new_zvect, new_xvect=new_xvect, new_origin=new_origin, BW=BW) #pprint(forward) new_zvect=Vector((0,0,1)) # The direction of the new z-axis. new_xvect=Vector((0,0,0)) # The direction of the new x-axis. new_origin=Vector((0.0,0,-0.5)) # The new origin backagain=spherical_harmonic_translation_and_rotation(forward, new_zvect=new_zvect, new_xvect=new_xvect, new_origin=new_origin, BW=BW) #pprint(backagain) # Let's plot the results as a bar graph # First we need to fill in the zero values in the # list called 'harmonics' indicies=SHT_Points.genindicies_top(BW) filledHarmonics=[] for n,m in indicies: tmp=[(n,m),(0,0)] for (N,M),(BA,BB) in harmonics: if N==n and M==m: tmp=[(N,M),(BA,BB)] break filledHarmonics.append(tmp) import matplotlib.pyplot as plt # Now we make some lists we can give to the # bar graph routines. BaOriginals=[] BbOriginals=[] for (n,m),(Ba,Bb) in filledHarmonics: BaOriginals.append(Ba) BbOriginals.append(Bb) BaForwards=[] BbForwards=[] for (n,m),(Ba,Bb) in forward: BaForwards.append(Ba) BbForwards.append(Bb) BaBackAgain=[] BbBackAgain=[] for (n,m),(Ba,Bb) in backagain: BaBackAgain.append(Ba) BbBackAgain.append(Bb) #pprint(BbOriginals) #pprint(BbBackAgain) # Now we do the bar graph. N = len(filledHarmonics) ind = np.arange(N) # the x locations for the groups width = 0.1 # the width of the bars fig = plt.figure() ax = fig.add_subplot(111) rects1 = ax.bar(ind, BaOriginals, width, color='r')#, yerr=menStd) rects2 = ax.bar(ind+width, BbOriginals, width, color='b') rects3 = ax.bar(ind+width*2, BaForwards, width, color='y')#, yerr=menStd) rects4 = ax.bar(ind+width*3, BbForwards, width, color='g') rects5 = ax.bar(ind+width*4, BaBackAgain, width, color='r')#, yerr=menStd) rects6 = ax.bar(ind+width*5, BbBackAgain, width, color='b') # add some labels ax.set_ylabel('Harmonic') ax.set_title('Harmonic Order and Degree') ax.set_xticks(ind+width) labels=[] for n,m in indicies: labels.append(str(n)+","+str(m)) ax.set_xticklabels( labels ) ax.legend( (rects1[0], rects2[0],rects3[0],rects4[0],rects5[0],rects6[0]), ('Ba Original', 'Bb Original','Ba Forward', 'Bb Forward','Ba backagain','Bb backagain') ) def autolabel(rects): # attach some text labels for rect in rects: height = rect.get_height() print height ax.text(rect.get_x()+rect.get_width()/2., 1.05*height, '%d'%int(height), ha='center', va='bottom') #autolabel(rects1) #autolabel(rects2) plt.show()
def spherical_harmonic_translation_and_rotation(harmonics, new_zvect=Vector((0,0,1)), # The direction of the new z-axis. new_xvect=Vector((1,0,0)), new_origin=Vector((0,0,0)), # The location of the new coordinate origin. phirot=0, # We can numerically rotate about phi or do so in a closed form # with the azimuthal rotation functions below. BW=6, # Harmonic bandwidth harmtype='_{n,m}', # Choose a spherical harmonic definition convention. verbose=True, show_points=False # Graphical Representation of measurement points. ): """ In this function we assume that we have a harmonic description around the z-vector (0,0,z) and we want a new description about a new vector. We also rotate the description azimuthally about this new vector by the amount phirot in radians. The principle is entirely numerical. We start by producing a single function of (x,y,z) from the given spherical harmonics. Then we define some measurement points about the new origin and oriented about the new direction. The function is then evaluated at these measurement points and -- provided we have chosen the points correctly -- the spherical harmonic transform of the computed values is used to produce a set of spherical harmonic coefficients valid for the new frame of reference. This problem can also be solved in closed form but I have not yet succeeded in doing so. See SphericalHarmonics.lyx for my attempts at the closed form solution. """ from KGeometry import find_vector_zx_rotation_transform rotationTransformation=find_vector_zx_rotation_transform(new_zvect,new_xvect) # Setup something to evaluate the total contribution of the harmonics. sharms=[] for (n,m),(ccoeff,scoeff) in harmonics: sharms.append(SphereHarmonic(n,m,ccoeff,scoeff,mode="COS_SIN",harmtype=harmtype)) # First we make some measurement points for computing the spherical harmonic transform measpoints=[Vector((1.0,theta,phi),vtype="SPHERICAL") for theta,phi in SHT_Points.measurement_points(BW)] # Then we rotate and shift them appropriately for the new frame. newmeaspoints=[m.rotate(rotationTransformation)+new_origin for m in measpoints] if show_points: from KGeomVisualization import Sphere,Colours,Visualization from KGeomVisualization import CoordinateAxes objs=[] objs.extend([Sphere(Vector(m.xyz()), 0.04, color=Colours["red"]) for m in measpoints]) objs.extend([Sphere(Vector(m.xyz()), 0.04, color=Colours["blue"]) for m in newmeaspoints]) coordsOrig=CoordinateAxes(colors=[Colours["red"] for i in range(4)]) rotmat=KGeometry.find_vector_zx_rotation_transform(new_zvect, new_xvect) coordsNew=CoordinateAxes(origin=new_origin, rot_matrix=rotmat, colors=[Colours["blue"] for i in range(4)]) objs.append(coordsOrig) objs.append(coordsNew) Visualization(objs) # Now we compute the contribution of the harmonics on the new data points. newdata=[] for m in newmeaspoints: tmp=0 for sh in sharms: tmp=tmp+sh.val_point(m) # Just find the contribution of the harmonic to the field point. newdata.append(tmp) # Now we find the Spherical Harmonic Transform of the newdata result=SHT(BW,realdata=newdata,mode="COS_SIN",harmtype=harmtype,Rref=1.0) # The result is a list of spherical harmonics in the new coordinate frame. return result
def ShimAnalysis(fname,options): # First we load all the data fin=file(fname,"rb") [patchlocations, resultVector, ShimMatrix, DesiredHarmonics, ProducedHarmonicsFromDesign, numZ, numPhi, Z, R, magLimitPerPixel, totalMagnetization]=cPickle.load(fin) if options.verbose: inkShimMatrix=resultVector.reshape(numZ,numPhi) pyplot.matshow(inkShimMatrix) pyplot.show() print "Z:",Z," numZ:",numZ," R:",R," numPhi:",numPhi pprint(DesiredHarmonics) pprint(ProducedHarmonicsFromDesign) patchHeight=Z/float(numZ) patchWidth =R*(2*pi)/float(numPhi) print "patchHeight:",patchHeight print "patchWidth:",patchWidth # Now we need to break the design into very small bits for # analysis. Forget that for now. Let's just use the patches # as they are print "Computing Scalar Potential" harmR=R*options.rSphereFact ThetaPhis=SHT_Points.measurement_points(options.HarmBW) ScalarPotVals=[] for theta,phi in ThetaPhis: fieldpoint=Vector((harmR,theta,phi),vtype="SPHERICAL") scpotval=0 # Probably should use KFarm here to split the computation # load across many cores for sourcepoint,pixelmag in zip(patchlocations,resultVector): if(pixelmag<-magLimitPerPixel*0.01 or pixelmag>magLimitPerPixel*1.01): print "pixelmag:",pixelmag print "magLimitPerPixel:",magLimitPerPixel raise Exception magnetization=Vector((0,0,1)).scale(pixelmag) scpotval=scpotval+ScalarPotential(magnetization,sourcepoint,fieldpoint) ScalarPotVals.append(scpotval) ScalarPotHarms=SHT(options.HarmBW,harmtype="_{n,m}",mode="COS_SIN", realdata=ScalarPotVals, Rref=harmR) # Now we need to convert this into harmonics of Bz. BzHarms={} for (n,m),(A,B) in ScalarPotHarms: (n,m),(A,B)=ScalarPot2BzField(n,m,A,B) if (n!=None): BzHarms[(n,m)]=(A,B) # print the result print "Here are the Harmonics of the Bz field" pprint(BzHarms) # and write it to a file fnameout=fname.split(".")[0]+"Analysis.cPickle" fout=file(fnameout,"wb+") cPickle.dump([BzHarms,fname],fout) fout.close()