Source code for Analyser

import sys
sys.path.append('.')
sys.path.append('..')
sys.path.append('../..')
import math,numpy as np
from MJOLNIR.Geometry import GeometryConcept
from MJOLNIR import _tools
import warnings
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

[docs]class Analyser(GeometryConcept.GeometryObject): """Generic analyser object. Base class from which all analysers must inherit."""
[docs] @_tools.KwargChecker() def __init__(self,position,direction,d_spacing=3.35,mosaicity=60): """ Args: - position (float 3): Position of analyser in meters - direction (float 3): Direction of analyser - d_spacing (float): The d spacing in Angstrom (default 3.35) - mosaicity (float): The standard deviation of mosaicity in arcminutes (default 60) """ super(Analyser,self).__init__(position,direction) self.d_spacing = d_spacing self.mosaicity = mosaicity
@property def type(self): return self._type @type.getter def type(self): return self._type @type.setter def type(self,type): self._type = type @property def d_spacing(self): return self._d_spacing @d_spacing.getter def d_spacing(self): return self._d_spacing @d_spacing.setter def d_spacing(self,d_spacing): if d_spacing<0.0: raise AttributeError if d_spacing>10.0: warnings.warn('The unit of d spacing is Angstrom') self._d_spacing = d_spacing @property def mosaicity(self): return self._mosaicity @mosaicity.getter def mosaicity(self): return self._mosaicity @mosaicity.setter def mosaicity(self,mosaicity): if mosaicity<0.0: raise AttributeError('The mosaicity should be non-negative') if mosaicity<1.0: warnings.warn('The unit of mosaicity is arcminutes') self._mosaicity = mosaicity
[docs] def plot(self,ax,offset=(0.0,0.0,0.0)): """ Args: - ax (matplotlib.pyplot 3d axis): Axis object into which the analyser is plotted Kwargs: - offset (3vector): Offset of analuser due to bank position (default [0,0,0]) >>> GenericAnalyser = Analyser(position=(0.0,1.0,0.0),direction=(1.0,0,0)) >>> GenericAnalyser.plot(ax) """ raise NotImplementedError
def __str__(self): returnString=('{} located at {}'.format(str(self.__class__).split('.')[-1][:-2],self.position)) return returnString
[docs]class FlatAnalyser(Analyser): """Simple flat analyser. """
[docs] @_tools.KwargChecker() def __init__(self,position,direction,d_spacing=3.35,mosaicity=60,width=0.05,height=0.1): """ Args: - Position (3vector): Position of object (default [0,0,0]) - Direction (3vector): Direction along which the object points (default [0,0,1]) Kwargs: - d_spacing (float): D spacing of analyser in Angstrom - mosaicity (float): Mosaicity in arcminutes - length (float): Length of detector tube in meters (default 0.25) - pixels (int): Number of pixels (default 456) - diameter (float): Diameter of tube in meters (default 0.02) Raises: - AttributeError - NotImplementedError """ super(FlatAnalyser,self).__init__(position,direction,d_spacing,mosaicity) self.width = width self.height = height
@property def width(self): return self._width @width.getter def width(self): return self._width @width.setter def width(self,width): if(width<0): raise AttributeError('The width of the analyser cannot be negative.') self._width = width @property def height(self): return self._height @height.getter def height(self): return self._height @height.setter def height(self,height): if(height<0.0): raise AttributeError('The height of the analyser must be grater than 0.') self._height = height
[docs] @_tools.KwargChecker() def plot(self,ax,offset=np.array([0,0,0]),n=100): """ Args: - ax (matplotlib.pyplot 3d axis): Axis object into which the analyser is plotted Kwargs: - offset (3vector): Offset of detector due to bank position (default [0,0,0]) - n (int): Number of points on the surface to be plotted (default 100) >>> Analyser = FlatAnalyser(position=(0.0,1.0,0.0),direction=(1.0,0,0)) >>> Analyser.plot(ax,offset=(0.0,0.0,0.0),n=100) """ pos = self.position.copy() pos+=offset Width = self.width / 2.0 Height =self.height / 2.0 angle = np.arctan2(self.position[1],self.position[0]) # angle relative to x-axis if self.direction.shape!=(): angleZ = self.direction[0] else: angleZ = self.direction # Energy-determining angle x=np.linspace(-Width, Width, n) y=np.linspace(-Height, Height, n) Xc, Yc=np.meshgrid(x, y) Zcrot = np.sin(angleZ)*Xc Xcrot = Xc*np.cos(angle)-Yc*np.sin(angle) Ycrot = Xc*np.sin(angle)+Yc*np.cos(angle) ## Draw parameters rstride = 20 cstride = 20 ax.plot_surface(Xcrot+pos[0], Ycrot+pos[1], Zcrot+pos[2], alpha=1, rstride=rstride, cstride=cstride)