def __init__(self, parent):
        """
        generated sscan_gui_autogenerated file use wxFormBuilder V3.4-Beta
        """
        sscan_gui_autogenerated.MainFrame.__init__(self, parent)

        # save e0 value
        self.e0 = 0.0
        self.eNow = 0.0
        self.e0EdgeEnergy = 7112.0

        self.xEnergy = []
        self.yTrans = []

        # for each panels to display spectra, generate a graphics canvas object
        self.make_canvas('canvasTrans', self.m_plotTrans)
        self.make_canvas('canvasFluo', self.m_plotFluo)

        self.scan2 = Scan('lww:scan2')                            # scan record
        self.scan2.add_callback('FAZE', self.scanUpdateCallBack)   # monitor scan status
        self.scan2.add_callback('PAUS', self.pauseCallBack)        # state change PAUSE/RESUME button
        self.scan2.add_callback('BUSY', self.scanBusyCallBack)     # scanning or stop status

        self.count = Scaler('BL10C:scaler1')                 # scaler record
        self.count.add_callback('CNT', self.UpdateCountCallBack)   # monitor current scan point

        # make sense now energy PV for monitor current Energy, direct access to the DCM Energy
        self.eNowPV = epics.PV(self.scan2.get('P1PV')+'.RBV', callback=self.eNowCallBack)
        self.scanAbortPV = epics.PV("lww:AbortScans.PROC")  # scan Abort PV
        self.scanPositionerPV = epics.PV("mobiis:m2")        # scan positioner(P1PV) PV

        # update display from IOC values to GUI-----------------------------------------------------
        self.m_totalScanPoint.SetLabel(str(self.scan2.NPTS))  # total scan point in IOC
        self.m_currentScanPoint.SetLabel(str(self.scan2.current_point))  # current scan point in IOC

        #-------------------- set Region names ---------------------
        # Region Start names
        self.m_PreEdgeStart.myName = "Pre-Edge"
        self.m_XanesStart.myName = "XANES"
        self.m_Xafs1Start.myName = "XAFS1"
        self.m_Xafs2Start.myName = "XAFS2"
        self.m_Xafs3Start.myName = "XAFS3"
        self.m_Xafs4Start.myName = "XAFS4"
        # Region Stop names
        self.m_PreEdgeStop.myName = "Pre-Edge"
        self.m_XanesStop.myName = "XANES"
        self.m_Xafs1Stop.myName = "XAFS1"
        self.m_Xafs2Stop.myName = "XAFS2"
        self.m_Xafs3Stop.myName = "XAFS3"
        self.m_Xafs4Stop.myName = "XAFS4"
        # Region Step names
        self.m_PreEdgeStep.myName = "Pre-Edge"
        self.m_XanesStep.myName = "XANES"
        self.m_Xafs1Step.myName = "XAFS1"
        self.m_Xafs2Step.myName = "XAFS2"
        self.m_Xafs3Step.myName = "XAFS3"
        self.m_Xafs4Step.myName = "XAFS4"
        # Region Npts names
        self.m_PreEdgeNpts.myName = "Pre-Edge"
        self.m_XanesNpts.myName = "XANES"
        self.m_Xafs1Npts.myName = "XAFS1"
        self.m_Xafs2Npts.myName = "XAFS2"
        self.m_Xafs3Npts.myName = "XAFS3"
        self.m_Xafs4Npts.myName = "XAFS4"
        # Region Unit names
        self.m_PreEdgeUnits.myName = "Pre-Edge"
        self.m_XanesUnits.myName = "XANES"
        self.m_Xafs1Units.myName = "XAFS1"
        self.m_Xafs2Units.myName = "XAFS2"
        self.m_Xafs3Units.myName = "XAFS3"
        self.m_Xafs4Units.myName = "XAFS4"

        # make region widgets
        self.reg_settings = []
        # append PreEdge Region items
        self.reg_settings.append((self.m_PreEdgeStart, self.m_PreEdgeStop,
                                  self.m_PreEdgeStep,  self.m_PreEdgeNpts,
                                  self.m_PreEdgeUnits))
        # Append XANES Region items
        self.reg_settings.append((self.m_XanesStart, self.m_XanesStop,
                                  self.m_XanesStep,  self.m_XanesNpts,
                                  self.m_XanesUnits))
        # Append XAFS1 Region items
        self.reg_settings.append((self.m_Xafs1Start, self.m_Xafs1Stop,
                                  self.m_Xafs1Step,  self.m_Xafs1Npts,
                                  self.m_Xafs1Units))
        # Append XAFS2 Region items
        self.reg_settings.append((self.m_Xafs2Start, self.m_Xafs2Stop,
                                  self.m_Xafs2Step,  self.m_Xafs2Npts,
                                  self.m_Xafs2Units))
        # Append XAFS3 Region items
        self.reg_settings.append((self.m_Xafs3Start, self.m_Xafs3Stop,
                                  self.m_Xafs3Step,  self.m_Xafs3Npts,
                                  self.m_Xafs3Units))
        '''
        # Append XAFS4 Region items
        self.reg_settings.append((self.m_Xafs4Start, self.m_Xafs4Stop,
                                  self.m_Xafs4Step,  self.m_Xafs4Npts,
                                  self.m_Xafs4Units))
        '''

        self.m_Xafs4Start.Disable()
        self.m_Xafs4Stop.Disable()
        self.m_Xafs4Step.Disable()
        self.m_Xafs4Npts.Disable()
        self.m_Xafs4Time.Disable()
        self.m_Xafs4Units.Disable()
class SscanBaseMainFrame(sscan_gui_autogenerated.MainFrame):
    def __init__(self, parent):
        """
        generated sscan_gui_autogenerated file use wxFormBuilder V3.4-Beta
        """
        sscan_gui_autogenerated.MainFrame.__init__(self, parent)

        # save e0 value
        self.e0 = 0.0
        self.eNow = 0.0
        self.e0EdgeEnergy = 7112.0

        self.xEnergy = []
        self.yTrans = []

        # for each panels to display spectra, generate a graphics canvas object
        self.make_canvas('canvasTrans', self.m_plotTrans)
        self.make_canvas('canvasFluo', self.m_plotFluo)

        self.scan2 = Scan('lww:scan2')                            # scan record
        self.scan2.add_callback('FAZE', self.scanUpdateCallBack)   # monitor scan status
        self.scan2.add_callback('PAUS', self.pauseCallBack)        # state change PAUSE/RESUME button
        self.scan2.add_callback('BUSY', self.scanBusyCallBack)     # scanning or stop status

        self.count = Scaler('BL10C:scaler1')                 # scaler record
        self.count.add_callback('CNT', self.UpdateCountCallBack)   # monitor current scan point

        # make sense now energy PV for monitor current Energy, direct access to the DCM Energy
        self.eNowPV = epics.PV(self.scan2.get('P1PV')+'.RBV', callback=self.eNowCallBack)
        self.scanAbortPV = epics.PV("lww:AbortScans.PROC")  # scan Abort PV
        self.scanPositionerPV = epics.PV("mobiis:m2")        # scan positioner(P1PV) PV

        # update display from IOC values to GUI-----------------------------------------------------
        self.m_totalScanPoint.SetLabel(str(self.scan2.NPTS))  # total scan point in IOC
        self.m_currentScanPoint.SetLabel(str(self.scan2.current_point))  # current scan point in IOC

        #-------------------- set Region names ---------------------
        # Region Start names
        self.m_PreEdgeStart.myName = "Pre-Edge"
        self.m_XanesStart.myName = "XANES"
        self.m_Xafs1Start.myName = "XAFS1"
        self.m_Xafs2Start.myName = "XAFS2"
        self.m_Xafs3Start.myName = "XAFS3"
        self.m_Xafs4Start.myName = "XAFS4"
        # Region Stop names
        self.m_PreEdgeStop.myName = "Pre-Edge"
        self.m_XanesStop.myName = "XANES"
        self.m_Xafs1Stop.myName = "XAFS1"
        self.m_Xafs2Stop.myName = "XAFS2"
        self.m_Xafs3Stop.myName = "XAFS3"
        self.m_Xafs4Stop.myName = "XAFS4"
        # Region Step names
        self.m_PreEdgeStep.myName = "Pre-Edge"
        self.m_XanesStep.myName = "XANES"
        self.m_Xafs1Step.myName = "XAFS1"
        self.m_Xafs2Step.myName = "XAFS2"
        self.m_Xafs3Step.myName = "XAFS3"
        self.m_Xafs4Step.myName = "XAFS4"
        # Region Npts names
        self.m_PreEdgeNpts.myName = "Pre-Edge"
        self.m_XanesNpts.myName = "XANES"
        self.m_Xafs1Npts.myName = "XAFS1"
        self.m_Xafs2Npts.myName = "XAFS2"
        self.m_Xafs3Npts.myName = "XAFS3"
        self.m_Xafs4Npts.myName = "XAFS4"
        # Region Unit names
        self.m_PreEdgeUnits.myName = "Pre-Edge"
        self.m_XanesUnits.myName = "XANES"
        self.m_Xafs1Units.myName = "XAFS1"
        self.m_Xafs2Units.myName = "XAFS2"
        self.m_Xafs3Units.myName = "XAFS3"
        self.m_Xafs4Units.myName = "XAFS4"

        # make region widgets
        self.reg_settings = []
        # append PreEdge Region items
        self.reg_settings.append((self.m_PreEdgeStart, self.m_PreEdgeStop,
                                  self.m_PreEdgeStep,  self.m_PreEdgeNpts,
                                  self.m_PreEdgeUnits))
        # Append XANES Region items
        self.reg_settings.append((self.m_XanesStart, self.m_XanesStop,
                                  self.m_XanesStep,  self.m_XanesNpts,
                                  self.m_XanesUnits))
        # Append XAFS1 Region items
        self.reg_settings.append((self.m_Xafs1Start, self.m_Xafs1Stop,
                                  self.m_Xafs1Step,  self.m_Xafs1Npts,
                                  self.m_Xafs1Units))
        # Append XAFS2 Region items
        self.reg_settings.append((self.m_Xafs2Start, self.m_Xafs2Stop,
                                  self.m_Xafs2Step,  self.m_Xafs2Npts,
                                  self.m_Xafs2Units))
        # Append XAFS3 Region items
        self.reg_settings.append((self.m_Xafs3Start, self.m_Xafs3Stop,
                                  self.m_Xafs3Step,  self.m_Xafs3Npts,
                                  self.m_Xafs3Units))
        '''
        # Append XAFS4 Region items
        self.reg_settings.append((self.m_Xafs4Start, self.m_Xafs4Stop,
                                  self.m_Xafs4Step,  self.m_Xafs4Npts,
                                  self.m_Xafs4Units))
        '''

        self.m_Xafs4Start.Disable()
        self.m_Xafs4Stop.Disable()
        self.m_Xafs4Step.Disable()
        self.m_Xafs4Npts.Disable()
        self.m_Xafs4Time.Disable()
        self.m_Xafs4Units.Disable()

    def StartScan(self, event):
        """
        Generate xafs step scan positions(P1PA) and START scan
        """
        self.e0EdgeEnergy = float(self.m_SetEdgeEnergy.Value)
        self.scanPosGen(self.e0EdgeEnergy, self.reg_settings)

        self.scan2._print()

        # we need DCM pre postion set to -200[eV] before scan start(e0-startE-200ev)
        prePosition = ((self.e0EdgeEnergy-abs(float(self.m_PreEdgeStart.Value))) / 1000.)-0.2
        self.scanPositionerPV.put(value=prePosition, use_complete=True)

        # set expouse time to scaler
        self.count.CountTime(float(self.m_setCountTime.Value))

        self.scan2.run(wait=True)

        self.m_totalScanPoint.SetLabel(str(self.scan2.NPTS))
        self.xEnergy = []
        self.yTrans = []
        return

    def PauseScan(self, event):
        self.scan2.PAUS = 1  # set PAUSE
        return

    def ResumeScan(self, event):
        self.scan2.PAUS = 0  # set RESUME
        return

    def AbortScan(self, event):
        self.scanAbortPV.put(1)
        return

    def OnChoiceElement(self, event):
        tempEdgeEnergy = ELEM_DICT[self.m_choiceElement.GetStringSelection()]
        self.m_SetEdgeEnergy.SetValue(str(tempEdgeEnergy))
        self.e0 = tempEdgeEnergy
        return

    def enterE0(self, event):
        self.e0 = float(self.m_SetEdgeEnergy.Value)

        for key, element in ELEM_DICT.items():
            if self.e0 == float(element):
                self.m_choiceElement.SetStringSelection(key)
        return

    #
    # Region of Interest event(Start/Stop/Step/Npts/Time/Units)
    #
    def onStart(self, event):
        rowKey = event.GetEventObject().myName
        self.onVal(self, index=ROW_FIND.get(rowKey), label='start',
                   value=unicode(event.GetEventObject().Value))
        return

    def onStop(self, event):
        rowKey = event.GetEventObject().myName
        self.onVal(self, index=ROW_FIND.get(rowKey), label='stop',
                   value=unicode(event.GetEventObject().Value))
        return

    def onStep(self, event):
        rowKey = event.GetEventObject().myName
        self.onVal(self, index=ROW_FIND.get(rowKey), label='step',
                   value=unicode(event.GetEventObject().Value))
        return

    def onNpts(self, event):
        rowKey = event.GetEventObject().myName
        self.onVal(self, index=ROW_FIND.get(rowKey), label='npts',
                   value=unicode(event.GetEventObject().Value))
        return

    def onUnits(self, event):
        rowKey = event.GetEventObject().myName

        index = ROW_FIND.get(rowKey)
        wids = self.reg_settings[index]
        self.setStepNpts(wids, label='units')
        return

    def OnSize_TransCanvas(self, event):
        size = self.m_plotTrans.GetSize()
        self.canvasTrans.SetSize(size)

    def pauseCallBack(self, **kwargs):
        if kwargs['char_value'] == 'PAUSE':
            self.pause_button.Disable()
            self.resume_button.Enable()
        else:
            self.pause_button.Enable()
            self.resume_button.Disable()

    def scanBusyCallBack(self, **kwargs):
        if kwargs['value'] == 1:
            self.pause_button.Enable()
            self.resume_button.Disable()
            self.scan_button.Disable()
        elif kwargs['value'] == 0:  # scan DONE! or Aborted!
            # Todo: we need DCM move to e0 position after scan DONE or IDLE
            # ddd = self.e0EdgeEnergy / 1000.0
            # self.scanPositionerPV.put(value=ddd, use_complete=True)
            self.pause_button.Disable()
            self.resume_button.Disable()
            self.scan_button.Enable()

    def scanUpdateCallBack(self, **kwargs):
        """
        callback method, monitor sscan status
        """
        mode = kwargs['char_value']    # current status of sscan record.
        self.m_staticText3.LabelText = mode

        if mode == "WAIT:DETCTRS":
            self.m_staticText3.ForegroundColour = 'blue'
            self.m_currentScanPoint.SetLabel(str(self.scan2.current_point))

        elif mode == 'WAIT:MOTORS':
            self.m_staticText3.ForegroundColour = 'red'

        # Todo: we need DCM move to e0 position after scan DONE or IDLE
        #if mode == "IDLE":
        #    ddd = self.e0EdgeEnergy / 1000.0
        #    self.scanPositionerPV.put(value=ddd) # , use_complete=True)

        #else:
        #    self.m_staticText3.ForegroundColour = 'black'

    def eNowCallBack(self, **kwargs):
        """
        callback for now energy display from DCM
        read current energy from DCM. display now energy [eV] unit to GUI
        """
        tempEnow = 1000.0 * float(kwargs['value'])
        self.eNow = tempEnow
        self.m_staticStatusGainE.LabelText = unicode("%5.2f") % tempEnow
        return

    def UpdateCountCallBack(self, **kwargs):
        """
        callback method, display counter values(scaler1_calc(s) value)
        :param kwargs:
        :return:
        """
        if kwargs['value'] == 0:
            temp = self.count.Read(use_calc=True)

            self.m_staticStatusCountIo.LabelText = str(temp[1])  # Io count
            self.m_staticStatusCountIf.LabelText = str(temp[2])  # If count
            self.m_staticStatusCountIt.LabelText = str(temp[3])  # It count
            #self.m_staticStatusCountIr.LabelText = str(temp[4])  # Ir count
            self.m_staticStatusCountIr.LabelText = str(round(temp[7], 5))  # Ir count

            energyTemp = self.eNow - self.e0EdgeEnergy
            self.xEnergy.append(energyTemp)

            TransTemp = round(temp[7], 4)
            self.yTrans.append(TransTemp)

            # transmittance plot
            canvasID=self.plotSpectrum(self.xEnergy, self.yTrans, 'E [eV]',
                                       'Transmittance', self.canvasTrans)
            self.canvasID_panelTrans = canvasID

    def etok(self, energy):
        return np.sqrt(energy/XAFS_K2E)

    def ktoe(self, k):
        return k*k*XAFS_K2E

    def krange(self, start, stop, step):
        i = 1
        kstart = np.square((start + step) / k2e)
        kstop = np.square(stop / k2e)
        while(kstart < kstop):
            yield kstart
            i += 1
            kstart = np.square((start + (i*step)) / k2e)

    """
       Update Step/Npts on XAFS region GUI
    """
    def setStepNpts(self, wids, label, fix_npts=False):
        """
        Set step / npts for start/stop/step/npts/units list of widgets
        """
        start = float(wids[0].GetValue())  # start
        stop = float(wids[1].GetValue())  # stop
        step = float(wids[2].GetValue())  # step
        # read Units value eV or K
        un = wids[4]
        if hasattr(un, 'GetStringSelection'):
            units = un.GetStringSelection()
        else:
            units = un.GetLabel()

        if label == 'npts' or fix_npts:
            npts = float(max(2, wids[3].GetValue()))  # npts
        else:
            try:
                if units == u'K':  # [keV] units
                    kstop = abs(self.etok(stop))
                    kstart = abs(self.etok(start))
                    npts = len(list(self.krange(start=kstart, stop=kstop, step=abs(step))))
                else:  # [eV] units
                    npts = float(max(2, 1 + int(0.1 + abs(stop-start)/abs(step))))
            except ZeroDivisionError:
                npts = 3

        if units == u'eV' or npts == 3:
            wids[2].SetValue(unicode(round((stop-start)/(npts-1), 3)))  # changed by LWW , act=False)
        if not fix_npts:
            try:
                wids[3].SetValue(unicode(npts))  # changed by LWW , act=False)
            except AttributeError:
                pass

    """
       Update XAFS region GUI values from user event
    """
    def onVal(self, evt=None, index=0, label=None, value=None, **kws):
        """
        XAFS onVal
        """
        ## if not self._initialized:
        ##     return
        wids = self.reg_settings[index]

        e0_off = 0

        if 0 == self.m_absRel.GetSelection():  # absolute
            e0_off = self.m_SetEdgeEnergy.GetValue()

        if label in ('start', 'stop', 'step', 'npts'):
            self.setStepNpts(wids, label)
            if label == 'stop' and index < len(self.reg_settings)-1:
                self.reg_settings[index+1][0].SetValue(unicode(value))  # by LWW, act=False)
                self.setStepNpts(self.reg_settings[index+1], label)
            elif label == 'start' and index > 0:
                self.reg_settings[index-1][1].SetValue(unicode(value))  # by LWW, act=False)
                self.setStepNpts(self.reg_settings[index-1], label)

    def scanPosGen(self, e0, regions):
        """
        e0 = XAFS Edge Energy
        regions = Region of Interest items
                  pre-edge(start/stop/step/npts(time)/units)
                  xanes(start/stop/step/npts(time)/units)
                             ..... to XAFS4
        Generation format :
            eOut = scanPosGen(5989, [(-35, -5, 2, 1), (-5, 25, 0.1, 1), (25, 255, 2, 1)])
        """
        eOut = []
        reg = []

        # Todo: we need find disable regions and not generate tuple or position
        # generate region tuples
        for wids in regions:
            # wids[0]=start, wids[1]=stop, wids[2]=step, wids[3]=npts, wids[4]=units
            reg.append((float(wids[0].GetValue()), float(wids[1].GetValue()),
                        float(wids[2].GetValue()), float(wids[3].GetValue()), wids[4]))

        # generate all step position
        for start, stop, step, npts, units in reg:
            # get units and check unit fist
            if hasattr(units, 'GetStringSelection'):  # eV or keV
                unitValue = units.GetStringSelection()
            else:
                unitValue = units.GetLabel()   # eV only

            if unitValue == u'K':  # [keV] units
                kstop = abs(self.etok(stop))
                kstart = abs(self.etok(start))
                tempEout = list(self.krange(start=kstart, stop=kstop, step=abs(step)))
                for i in tempEout:
                    eOut.append(e0 + i)
            else:
                for ipt in range(int((stop-start) / step + 0.1)):
                    eOut.append(e0 + start + step * ipt)

        #Todo: please erase P1PA values after put new values.
        # self.scan2.table = eOut   # write new position to scan2.P1PA
        # DCM IOC need keV unit
        self.scan2.table = list(np.divide(eOut, 1000.))  # write new position to scan2.P1PA
        # set epics scan2.NPTS
        self.scan2.npts = len(eOut)
        # set epics scan2.P1SM (scan mode, 0=Linear, 1=Table, 2=Fly)
        self.scan2.mode = 1


    """---------------------------------------------------------------------------------
    Make canvs for PLOT PANEL
    """
    def make_canvas(self, canvas_name, parent_panel):
        """
        Create plot canvas for parent Panel and make it accessible as an attribute .canvas_name
        :param canvas_name: string containing canvas/attribute name
        :param parent_panel: parent wx.Panel for canvas
        :return: canvas reference
        """
        canvas = plot.PlotCanvas(parent_panel)
        canvas.SetInitialSize(size=parent_panel.GetSize())
        canvas.SetEnableZoom(True)
        canvas.SetEnableGrid(True)

        ## canvas.SetEnableDrag(True)

        canvas.SetGridColour('#CCCCCC')
        canvas.Layout()
        setattr(self, canvas_name, canvas)
        return canvas

    def plotSpectrum(self, x, y, xtitle, ytitle, canvas, moreYf=None, moreYr=None, vlines=None, vline_ymax=None):
        """
        send list of (x/y) tuples to plot output in destination(here called "where")
        :param x: x data(1st data)
        :param y: y data
        :param xtitle: x axis title
        :param ytitle: y axis title
        :param canvas: canvas object reference
        :param moreYf: optional additional ydata serise(2nd data)
        :param moreYr: another additional ydata serise(3rd data)
        :param vlines: an list of x-coordinates to place vertical(green) lines
                        at extending over the current canvas
        :param vline_ymax: if ylines are supplied, supplying this determines their max.
        :return: ID of the canvas object drawn on(useful for clearing a canvas
                  from outside this function; needs XXX = wx.FindWindowById(canvasID)
                  at external point to find this canvas; then clear with XXX.Clear() )
        """
        # clear corresponding canvas first
        canvas.Clear()
        # zip data arrays together into list of tuples (wx.plot requires tuples)
        # then define "line" objects to carry the data into the plot
        plotData = zip(x, y)

        line = plot.PolyLine(plotData, colour='black', width=1)
        maker = plot.PolyMarker(plotData, colour='black', width=0, size=1)

        if moreYf is not None:
            plotMoreData = zip(x, moreYf)
            #moreLine = plot.PolyLine(plotMoreData, colour='blue', width=1)
            moreLine = plot.PolyMarker(plotMoreData, colour='blue', width=1)

        if moreYr is not None:
            plotMoreData2 = zip(x, moreYr)
            #moreLine2 = plot.PolyLine(plotMoreData2, colour='green', width=1)
            moreLine2 = plot.PolyMarker(plotMoreData2, colour='green', width=1)

        serise = [line]

        if moreYf is not None:
            serise.append(moreLine)
        if moreYr is not None:
            serise.append(moreLine2)

        if vlines is not None:
            # Now just plot somthing to ensure that autoscaling show the full range
            #line = plot.PolyLine([(0,1), (self.det.detector_data.mca_bins-1, 1)],
            #                     solour='white', widt=1)
            line = plot.PolyMarker([(0,1), (self.det.detector_data.mca_bins-1, 1)],
                                 solour='white', widt=1)
            serise.append(line)

            # plot ROI range limit lines
            ymax = canvas.ClientSize[1]

            if vline_ymax is not None:
                canvas.SetYSpec('min')
                ymax = vline_ymax
            for x in vlines:
                #line_x = plot.PolyLine([(x,1), (x,ymax)], colour='green', width=1)
                line_x = plot.PolyMarker([(x,1), (x,ymax)], colour='green', width=1)
                serise.append(line_x)

        serise.append(maker)

        gc = plot.PlotGraphics(serise, '', xtitle, ytitle)
        canvas.Draw(gc)
        return canvas.GetId()