import wx
from plottables import Theory1D
import math
import numpy
import fittings
import transform
import sys
#Linear fit panel size
if sys.platform.count("win32") > 0:
FONT_VARIANT = 0
PNL_WIDTH = 450
PNL_HEIGHT = 500
else:
FONT_VARIANT = 1
PNL_WIDTH = 500
PNL_HEIGHT = 500
RG_ON = True
[docs]class LinearFit(wx.Dialog):
def __init__(self, parent, plottable, push_data, transform, title):
"""
Dialog window pops- up when select Linear fit on Context menu
Displays fitting parameters
"""
wx.Dialog.__init__(self, parent, title=title,
size=(PNL_WIDTH, 350))
self.parent = parent
self.transform = transform
#Font
self.SetWindowVariant(variant=FONT_VARIANT)
# Registered owner for close event
self._registered_close = None
#dialog panel self call function to plot the fitting function
self.push_data = push_data
#dialog self plottable
self.plottable = plottable
self.rg_on = False
# Receive transformations of x and y
self.xLabel, self.yLabel, self.Avalue, self.Bvalue,\
self.ErrAvalue, self.ErrBvalue, self.Chivalue = self.transform()
#Dialog interface
vbox = wx.BoxSizer(wx.VERTICAL)
sizer = wx.GridBagSizer(5, 5)
_BOX_WIDTH = 100
self.tcA = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
self.tcA.SetToolTipString("Fit value for the slope parameter.")
self.tcErrA = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
self.tcErrA.SetToolTipString("Error on the slope parameter.")
self.tcB = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
self.tcA.SetToolTipString("Fit value for the constant parameter.")
self.tcErrB = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
self.tcErrB.SetToolTipString("Error on the constant parameter.")
self.tcChi = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
self.tcChi.SetToolTipString("Chi^2 over degrees of freedom.")
self.xminFit = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
msg = "Enter the minimum value on "
msg += "the x-axis to be included in the fit."
self.xminFit.SetToolTipString(msg)
self.xmaxFit = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
msg = "Enter the maximum value on "
msg += " the x-axis to be included in the fit."
self.xmaxFit.SetToolTipString(msg)
self.initXmin = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
msg = "Minimum value on the x-axis for the plotted data."
self.initXmin.SetToolTipString(msg)
self.initXmax = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
msg = "Maximum value on the x-axis for the plotted data."
self.initXmax.SetToolTipString(msg)
# Make the info box not editable
#_BACKGROUND_COLOR = '#ffdf85'
_BACKGROUND_COLOR = self.GetBackgroundColour()
self.initXmin.SetEditable(False)
self.initXmin.SetBackgroundColour(_BACKGROUND_COLOR)
self.initXmax.SetEditable(False)
self.initXmax.SetBackgroundColour(_BACKGROUND_COLOR)
# Buttons on the bottom
self.bg_on = False
self.static_line_1 = wx.StaticLine(self, -1)
self.btFit = wx.Button(self, -1, 'Fit')
self.btFit.Bind(wx.EVT_BUTTON, self._onFit)
self.btFit.SetToolTipString("Perform fit.")
self.btClose =wx.Button(self, wx.ID_CANCEL, 'Close')
self.btClose.Bind(wx.EVT_BUTTON, self._on_close)
if RG_ON:
if (self.yLabel == "ln(y)" or self.yLabel == "ln(y*x)") and \
(self.xLabel == "x^(2)"):
self.rg_on = True
if (self.xLabel == "x^(4)") and (self.yLabel == "y*x^(4)"):
self.bg_on = True
# Intro
explanation = "Perform fit for y(x) = ax + b"
if self.bg_on:
param_a = 'Background (= Parameter a)'
else:
param_a = 'Parameter a'
vbox.Add(sizer)
ix = 0
iy = 1
sizer.Add(wx.StaticText(self, -1, explanation), (iy, ix),
(1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
iy += 2
sizer.Add(wx.StaticText(self, -1, param_a), (iy, ix),
(1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer.Add(self.tcA,(iy, ix),(1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer.Add(wx.StaticText(self, -1, '+/-'),
(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer.Add(self.tcErrA, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer.Add(wx.StaticText(self, -1, 'Parameter b'), (iy, ix),(1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer.Add(self.tcB, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer.Add(wx.StaticText(self, -1, '+/-'), (iy, ix),
(1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer.Add(self.tcErrB, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer.Add(wx.StaticText(self, -1, 'Chi2/dof'), (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer.Add(self.tcChi, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
#sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
iy += 2
ix = 1
sizer.Add(wx.StaticText(self, -1, 'Min'), (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 2
sizer.Add(wx.StaticText(self, -1, 'Max'), (iy, ix),
(1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer.Add(wx.StaticText(self, -1, 'Maximum range (linear scale)'),
(iy, ix),(1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer.Add(self.initXmin, (iy, ix), (1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 2
sizer.Add(self.initXmax, (iy, ix), (1,1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer.Add(wx.StaticText(self, -1, 'Fit range of ' + self.xLabel),
(iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer.Add(self.xminFit, (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 2
sizer.Add(self.xmaxFit, (iy, ix), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
if self.rg_on:
self.SetSize((PNL_WIDTH, PNL_HEIGHT))
I0_stxt = wx.StaticText(self, -1, 'I(q=0)')
self.I0_tctr = wx.TextCtrl(self, -1, '')
self.I0_tctr.SetEditable(False)
self.I0_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
self.I0err_tctr = wx.TextCtrl(self, -1, '')
self.I0err_tctr.SetEditable(False)
self.I0err_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
Rg_stxt = wx.StaticText(self, -1, 'Rg [A]')
Rg_stxt.Show(self.yLabel == "ln(y)" )
self.Rg_tctr = wx.TextCtrl(self, -1, '')
self.Rg_tctr.SetEditable(False)
self.Rg_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
self.Rg_tctr.Show(self.yLabel == "ln(y)" )
self.Rgerr_tctr = wx.TextCtrl(self, -1, '')
self.Rgerr_tctr.SetEditable(False)
self.Rgerr_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
self.Rgerr_tctr.Show(self.yLabel == "ln(y)" )
self.Rgerr_pm = wx.StaticText(self, -1, '+/-')
self.Rgerr_pm.Show(self.yLabel == "ln(y)" )
Diameter_stxt = wx.StaticText(self, -1, 'Rod Diameter [A]')
Diameter_stxt.Show(self.yLabel == "ln(y*x)")
self.Diameter_tctr = wx.TextCtrl(self, -1, '')
self.Diameter_tctr.SetEditable(False)
self.Diameter_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
self.Diameter_tctr.Show(self.yLabel == "ln(y*x)")
self.Diameter_pm = wx.StaticText(self, -1, '+/-')
self.Diameter_pm.Show(self.yLabel == "ln(y*x)")
self.Diametererr_tctr = wx.TextCtrl(self, -1, '')
self.Diametererr_tctr.SetEditable(False)
self.Diametererr_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
self.Diametererr_tctr.Show(self.yLabel == "ln(y*x)")
RgQmin_stxt = wx.StaticText(self, -1, 'Rg*Qmin')
self.RgQmin_tctr = wx.TextCtrl(self, -1, '')
self.RgQmin_tctr.SetEditable(False)
self.RgQmin_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
RgQmax_stxt = wx.StaticText(self, -1, 'Rg*Qmax')
self.RgQmax_tctr = wx.TextCtrl(self, -1, '')
self.RgQmax_tctr.SetEditable(False)
self.RgQmax_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
iy += 2
ix = 0
sizer.Add(I0_stxt, (iy, ix), (1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer.Add(self.I0_tctr, (iy, ix), (1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer.Add(wx.StaticText(self, -1, '+/-'), (iy, ix),
(1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer.Add(self.I0err_tctr, (iy, ix), (1,1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer.Add(Rg_stxt, (iy, ix),(1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer.Add(self.Rg_tctr, (iy, ix), (1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer.Add(self.Rgerr_pm, (iy, ix),
(1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer.Add(self.Rgerr_tctr, (iy, ix), (1,1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer.Add(Diameter_stxt, (iy, ix),(1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer.Add(self.Diameter_tctr, (iy, ix), (1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer.Add(self.Diameter_pm, (iy, ix),
(1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer.Add(self.Diametererr_tctr, (iy, ix), (1,1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer.Add(RgQmin_stxt, (iy, ix),(1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer.Add(self.RgQmin_tctr, (iy, ix), (1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer.Add(RgQmax_stxt, (iy, ix),(1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer.Add(self.RgQmax_tctr, (iy, ix), (1,1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 1
vbox.Add(self.static_line_1, 0, wx.EXPAND, 0)
sizer_button = wx.BoxSizer(wx.HORIZONTAL)
sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
sizer_button.Add(self.btFit, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
sizer_button.Add(self.btClose, 0,
wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
vbox.Add(sizer_button, 0, wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
sizer.Add(self.btFit, (iy, ix), (1,1), wx.LEFT|wx.ADJUST_MINSIZE, 0)
#panel.SetSizer(sizer)
self.SetSizer(vbox)
self.Centre()
# Receives the type of model for the fitting
from LineModel import LineModel
self.model = LineModel()
#Display the fittings values
self.default_A = self.model.getParam('A')
self.default_B = self.model.getParam('B')
self.cstA = fittings.Parameter(self.model, 'A', self.default_A)
self.cstB = fittings.Parameter(self.model, 'B', self.default_B)
# Set default value of parameter in fit dialog
if self.Avalue == None:
self.tcA.SetValue(format_number(self.default_A))
else:
self.tcA.SetLabel(format_number(self.Avalue))
if self.Bvalue == None:
self.tcB.SetValue(format_number(self.default_B))
else:
self.tcB.SetLabel(format_number(self.Bvalue))
if self.ErrAvalue == None:
self.tcErrA.SetLabel(format_number(0.0))
else:
self.tcErrA.SetLabel(format_number(self.ErrAvalue))
if self.ErrBvalue == None:
self.tcErrB.SetLabel(format_number(0.0))
else:
self.tcErrB.SetLabel(format_number(self.ErrBvalue))
if self.Chivalue == None:
self.tcChi.SetLabel(format_number(0.0))
else:
self.tcChi.SetLabel(format_number(self.Chivalue))
if self.plottable.x != []:
#store the values of View in self.x,self.y,self.dx,self.dy
self.x, self.y, self.dx, \
self.dy = self.plottable.returnValuesOfView()
try:
self.mini = self.floatForwardTransform(min(self.x))
except:
self.mini = "Invalid"
try:
self.maxi = self.floatForwardTransform(max(self.x))
except:
self.maxi = "Invalid"
self.initXmin.SetValue(format_number(min(self.plottable.x)))
self.initXmax.SetValue(format_number(max(self.plottable.x)))
self.mini = min(self.x)
self.maxi = max(self.x)
self.xminFit.SetValue(format_number(self.mini))
self.xmaxFit.SetValue(format_number(self.maxi))
[docs] def register_close(self, owner):
"""
Method to register the close event to a parent
window that needs notification when the dialog
is closed
:param owner: parent window
"""
self._registered_close = owner
def _on_close(self, event):
"""
Close event.
Notify registered owner if available.
"""
event.Skip()
if self._registered_close is not None:
self._registered_close()
def _onFit(self, event):
"""
Performs the fit. Receive an event when clicking on
the button Fit.Computes chisqr ,
A and B parameters of the best linear fit y=Ax +B
Push a plottable to
"""
tempx = []
tempy = []
tempdy = []
# Check if View contains a x array .we online fit when x exits
# makes transformation for y as a line to fit
if self.x != []:
if(self.checkFitValues(self.xminFit) == True):
#Check if the field of Fit Dialog contain values
# and use the x max and min of the user
#xminView,xmaxView = self._checkVal(self.xminFit.GetValue(),
#self.xmaxFit.GetValue())
if not self._checkVal(self.xminFit, self.xmaxFit):
return
xminView = float(self.xminFit.GetValue())
xmaxView = float(self.xmaxFit.GetValue())
#xmin = self.floatInvTransform(xminView)
#xmax = self.floatInvTransform(xmaxView)
xmin = xminView
xmax = xmaxView
# Store the transformed values of view x, y,dy
# in variables before the fit
if self.yLabel.lower() == "log10(y)":
if (self.xLabel.lower() == "log10(x)"):
for i in range(len(self.x)):
if self.x[i] >= math.log10(xmin):
tempy.append(math.log10(self.y[i]))
tempdy.append(transform.errToLogX(self.y[i],
0, self.dy[i], 0))
else:
for i in range(len(self.y)):
tempy.append(math.log10(self.y[i]))
tempdy.append(transform.errToLogX(self.y[i],
0, self.dy[i], 0))
else:
tempy = self.y
tempdy = self.dy
if (self.xLabel.lower() == "log10(x)"):
for x_i in self.x:
if x_i >= math.log10(xmin):
tempx.append(math.log10(x_i))
else:
tempx = self.x
#Find the fitting parameters
# Always use the same defaults, so that fit history
#doesn't play a role!
self.cstA = fittings.Parameter(self.model, 'A', self.default_A)
self.cstB = fittings.Parameter(self.model, 'B', self.default_B)
if (self.xLabel.lower() == "log10(x)"):
tempdy = numpy.asarray(tempdy)
tempdy[tempdy == 0] = 1
chisqr, out, cov = fittings.sasfit(self.model,
[self.cstA, self.cstB],
tempx, tempy,
tempdy,
math.log10(xmin),
math.log10(xmax))
else:
tempdy = numpy.asarray(tempdy)
tempdy[tempdy == 0] = 1
chisqr, out, cov = fittings.sasfit(self.model,
[self.cstA, self.cstB],
tempx, tempy, tempdy,
xminView, xmaxView)
# Use chi2/dof
if len(tempx) > 0:
chisqr = chisqr/len(tempx)
#Check that cov and out are iterable before displaying them
if cov == None:
errA = 0.0
errB = 0.0
else:
errA = math.sqrt(cov[0][0])
errB = math.sqrt(cov[1][1])
if out == None:
cstA = 0.0
cstB = 0.0
else:
cstA = out[0]
cstB = out[1]
# Reset model with the right values of A and B
self.model.setParam('A', float(cstA))
self.model.setParam('B', float(cstB))
tempx = []
tempy = []
y_model = 0.0
# load tempy with the minimum transformation
if self.xLabel == "log10(x)":
y_model = self.model.run(math.log10(xmin))
tempx.append(xmin)
else:
y_model = self.model.run(xminView)
tempx.append(xminView)
if self.yLabel == "log10(y)":
tempy.append(math.pow(10, y_model))
else:
tempy.append(y_model)
# load tempy with the maximum transformation
if self.xLabel == "log10(x)":
y_model = self.model.run(math.log10(xmax))
tempx.append(xmax)
else:
y_model = self.model.run(xmaxView)
tempx.append(xmaxView)
if self.yLabel == "log10(y)":
tempy.append(math.pow(10, y_model))
else:
tempy.append(y_model)
#Set the fit parameter display when FitDialog is opened again
self.Avalue = cstB
self.Bvalue = cstA
self.ErrAvalue = errA
self.ErrBvalue = errB
self.Chivalue = chisqr
self.push_data(tempx, tempy, xminView, xmaxView,
xmin, xmax, self._ongetValues())
# Display the fitting value on the Fit Dialog
self._onsetValues(cstB, cstA, errA, errB, chisqr)
def _onsetValues(self, cstA, cstB, errA, errB, Chi):
"""
Display the value on fit Dialog
"""
rg = None
self.tcA.SetValue(format_number(cstA))
self.tcB.SetValue(format_number(cstB))
self.tcErrA.SetValue(format_number(errA))
self.tcErrB.SetValue(format_number(errB))
self.tcChi.SetValue(format_number(Chi))
if self.rg_on:
if self.Rg_tctr.IsShown():
rg = numpy.sqrt(-3 * float(cstA))
value = format_number(rg)
self.Rg_tctr.SetValue(value)
if self.I0_tctr.IsShown():
val = numpy.exp(cstB)
self.I0_tctr.SetValue(format_number(val))
if self.Rgerr_tctr.IsShown():
if rg != None and rg != 0:
value = format_number(3 * float(cstA) / (2 * rg))
else:
value =''
self.Rgerr_tctr.SetValue(value)
if self.I0err_tctr.IsShown():
val = numpy.abs(numpy.exp(cstB) - numpy.exp(cstB + errB))
self.I0err_tctr.SetValue(format_number(val))
if self.Diameter_tctr.IsShown():
rg = 4 * numpy.sqrt(-float(cstA))
value = format_number(rg)
self.Diameter_tctr.SetValue(value)
if self.Diametererr_tctr.IsShown():
if rg != None and rg != 0:
value = format_number(8 * float(cstA) / rg)
else:
value =''
self.Diametererr_tctr.SetValue(value)
if self.RgQmin_tctr.IsShown():
value = format_number(rg * self.mini)
self.RgQmin_tctr.SetValue(value)
if self.RgQmax_tctr.IsShown():
value = format_number(rg * self.maxi)
self.RgQmax_tctr.SetValue(value)
def _ongetValues(self):
"""
Display the value on fit Dialog
"""
return self.Avalue, self.Bvalue, self.ErrAvalue, \
self.ErrBvalue, self.Chivalue
def _checkVal(self, usermin, usermax):
"""
Ensure that fields parameter contains a min and a max value
within x min and x max range
"""
self.mini = float(self.xminFit.GetValue())
self.maxi = float(self.xmaxFit.GetValue())
flag = True
try:
mini = float(usermin.GetValue())
maxi = float(usermax.GetValue())
if mini < maxi:
usermin.SetBackgroundColour(wx.WHITE)
usermin.Refresh()
else:
flag = False
usermin.SetBackgroundColour("pink")
usermin.Refresh()
except:
# Check for possible values entered
flag = False
usermin.SetBackgroundColour("pink")
usermin.Refresh()
return flag
[docs] def checkFitValues(self, item):
"""
Check the validity of input values
"""
flag = True
value = item.GetValue()
# Check for possible values entered
if (self.xLabel == "log10(x)"): #or self.xLabel=="ln(x)"):
if(float(value) > 0):
item.SetBackgroundColour(wx.WHITE)
item.Refresh()
else:
flag = False
item.SetBackgroundColour("pink")
item.Refresh()
return flag
[docs] def setFitRange(self, xmin, xmax, xminTrans, xmaxTrans):
"""
Set fit parameters
"""
self.xminFit.SetValue(format_number(xmin))
self.xmaxFit.SetValue(format_number(xmax))
[docs] def set_fit_region(self, xmin, xmax):
"""
Set the fit region
:param xmin: minimum x-value to be included in fit
:param xmax: maximum x-value to be included in fit
"""
# Check values
try:
float(xmin)
float(xmax)
except:
msg = "LinearFit.set_fit_region: fit range must be floats"
raise ValueError, msg
self.xminFit.SetValue(format_number(xmin))
self.xmaxFit.SetValue(format_number(xmax))
[docs]class MyApp(wx.App):
"""
"""
[docs] def OnInit(self):
"""
"""
wx.InitAllImageHandlers()
plot = Theory1D([], [])
dialog = LinearFit(parent=None, plottable=plot,
push_data=self.onFitDisplay,
transform=self.returnTrans,
title='Linear Fit')
if dialog.ShowModal() == wx.ID_OK:
pass
dialog.Destroy()
return 1
[docs] def onFitDisplay(self, tempx, tempy, xminView, xmaxView, xmin, xmax, func):
"""
"""
pass
[docs] def returnTrans(self):
"""
"""
return '', '', 0, 0, 0, 0, 0