diff --git a/frappy_psi/razorbill.py b/frappy_psi/razorbill.py new file mode 100644 index 0000000..7ee8c01 --- /dev/null +++ b/frappy_psi/razorbill.py @@ -0,0 +1,142 @@ +# ***************************************************************************** +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Module authors: +# Paul M. Neves +# ***************************************************************************** + +from frappy.core import Readable, Parameter, FloatRange, HasIO, StringIO, Property, IntRange,\ + IDLE, BUSY, WARN, ERROR, Drivable, BoolType, Attached, Writable, StructOf + + +class Temp(Writable): + """stores sample temperature""" + + target = Parameter('target voltage', FloatRange(0, 325, unit='K'), + readonly=False) + + def write_target(self, target): + self.value = target + + def read_value(self): + return self.value + + +class Displacement(Readable): + + # attached classes for capacitance and temperature + cap = Attached() + temp = Attached() + + # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) + value = Parameter('displacement', FloatRange(None, None, unit='um'), readonly=True) + alpha290K = Parameter('capacitor constant at 290 K', FloatRange(None, None, unit='um pF'), readonly=False) + d0 = Parameter('offset displacement', FloatRange(None, None, unit='um'), readonly=False) + Cp = Parameter('parallel capacitance', FloatRange(None, None, unit='pF'), readonly=False) + d0_curve = Parameter('calibration curve for offset displacement', + StructOf(a=FloatRange(None, None, unit='um'), + b=FloatRange(None, None, unit='um/K'), + c=FloatRange(None, None, unit='um/K^2'), + d=FloatRange(None, None, unit='um/K^3'), + e=FloatRange(None, None, unit='um/K^4'),), + readonly=False) + + def read_value(self): + # get temperature and capacitance + temp = self.temp.target + cap = self.cap.value + + # calculate displacement from temperature and capacitance + d0_T = self.d0_curve['a'] + self.d0_curve['b']*temp + self.d0_curve['c']*temp**2 + self.d0_curve['d']*temp**3 + self.d0_curve['e']*temp**4 + + disp = self.alpha290K / (cap - self.Cp) - self.d0 + d0_T + + return disp + + +class Force(Readable): + + # attached classes for capacitance and temperature + cap = Attached() + temp = Attached() + + # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) + value = Parameter('force', FloatRange(None, None, unit='N'), readonly=True) + alpha290K = Parameter('capacitor constant at 290 K', FloatRange(None, None, unit='N pF'), readonly=False) + f0 = Parameter('offset force', FloatRange(None, None, unit='N'), readonly=False) + Cp = Parameter('parallel capacitance', FloatRange(None, None, unit='pF'), readonly=False) + f0_curve = Parameter('calibration curve for offset force', + StructOf(a=FloatRange(None, None, unit='N'), + b=FloatRange(None, None, unit='N/K'), + c=FloatRange(None, None, unit='N/K^2'), + d=FloatRange(None, None, unit='N/K^3'), + e=FloatRange(None, None, unit='N/K^4'),), + readonly=False) + + def read_value(self): + # get temperature and capacitance + temp = self.temp.target + cap = self.cap.value + + # calculate force from temperature and capacitance + alpha = self.alpha290K * (0.91 + 5e-5*temp + 9e-7*temp**2) + f0_T = self.f0_curve['a'] + self.f0_curve['b']*temp + self.f0_curve['c']*temp**2 + self.f0_curve['d']*temp**3 + self.f0_curve['e']*temp**4 + + force = alpha / (cap - self.Cp) - self.f0 + f0_T + + return force + + +class Stress(Readable): + + # attached classes for displacement + force = Attached() + + # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) + value = Parameter('stress', FloatRange(None, None, unit='GPa'), readonly=True) + area = Parameter('cross sectional area of sample in mm^2', FloatRange(None, None, unit='mm^2'), readonly=False) + + def read_value(self): + return self.force.value / self.area / 1000 + + +class Strain(Readable): + + # attached classes for displacement + displacement = Attached() + + # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) + value = Parameter('strain', FloatRange(None, None, unit='m/m'), readonly=True) + L = Parameter('length of sample in mm', FloatRange(None, None, unit='mm'), readonly=False) + + def read_value(self): + return self.displacement.value / (1000*self.L) + + +class YoungsModulus(Readable): + + # attached classes for displacement + stress = Attached() + strain = Attached() + + # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) + value = Parameter('Young\'s modulus', FloatRange(None, None, unit='GPa'), readonly=True) + + def read_value(self): + if self.strain.value: + return self.stress.value / self.strain.value + else: + return 0 +