"""
    tasks/aimless_pipe/CTaskaimless_pipe.py: CCP4 GUI Project
    Copyright (C) 2012 STFC
    """

"""
Martyn Winn August 2012 - aimless_pipe gui
Phil Evans 2014
"""

from PyQt4 import QtGui,QtCore
import CCP4TaskWidget
import CCP4Widgets

class CTaskaimless_pipe(CCP4TaskWidget.CTaskWidget):
    
    # Subclass CTaskWidget to give specific task window
    TASKNAME = 'aimless_pipe'
    TASKVERSION = 0.0
    TASKMODULE='data_reduction'
    TASKTITLE='Data reduction - AIMLESS'
    SHORTTASKTITLE='Data reduction'
    TASKLABEL='aimles'
    WHATNEXT = ['phaser_pipeline','molrep_pipe','crank2','shelx']
    PROGRAMHELP = ['aimless','pointless','ctruncate']
    RANK=1
    DESCRIPTION = '''Scale and analyse unmerged data and suggest space group (Pointless, Aimless, Ctruncate, FreeRflag)'''

    # -------------------------------------------------------------
    def __init__(self,parent):
        CCP4TaskWidget.CTaskWidget.__init__(self,parent)
    
    
    # -------------------------------------------------------------
    def drawContents(self):
        
        self.setProgramHelpFile('aimless')
        self.container.guiControls.SCALING_PROTOCOL_SET = False

        # - - - - - - - - - - - - - - - - - - - - - - - - - - -  Input data folder
        folder = self.openFolder(folderFunction='inputData',title='Input Data')
                
        self.createLine( ['widget', '-title','Select unmerged data files',
                          'UNMERGEDFILES'] )
        self.connect(self.container.inputData.UNMERGEDFILES, QtCore.SIGNAL('dataChanged'),
                     self.getUnknownCell)


        line = self.createLine( ['label','Resolution range (\xc5)',
                                 'widget', 'RESOLUTION_RANGE',
                                 'advice',' Maximum resolution in files ',
                                 'label','range to be determined'],
                                toggleFunction=[self.getMaximumResolution,['UNMERGEDFILES']] )
        # get label widget, note itemAt counts from 0
        self.maximum_resolution_label = line.layout().itemAt(3).widget()
        self.createLine(['widget','POINTLESS_USE_RESOLUTION_RANGE',
                         'label',
                         ' use explicit resolution range in symmetry determination as well as in scaling'])

        self.createLine( ['label','Options for symmetry determination', 'widget', 'MODE'] )
        self.connect(self.container.controlParameters.MODE, QtCore.SIGNAL('dataChanged'),
                     self.handleChangeMode)

        # CHOOSE mode options
        self.createLine( ['advice', 'Options for choice of space group or Laue group:'],
                         toggle=['MODE','open',['CHOOSE']]  )
        line_choose = self.createLine( ['widget', 'CHOOSE_MODE'],
                                       toggle=['MODE','open',['CHOOSE']]  )
        self.createLine( ['widget', 'CHOOSE_SOLUTION_NO'], appendLine=line_choose,
                        toggle=['CHOOSE_MODE', 'open', ['SOLUTION_NO']] )
        self.createLine( ['widget', 'CHOOSE_SPACEGROUP'], appendLine=line_choose,
                        toggle=['CHOOSE_MODE', 'open', ['SPACEGROUP','REINDEX_SPACE']] )
        self.createLine( ['Use reindex operator ', \
                          'widget', 'REINDEX_OPERATOR'],
                         toggle=['MODE', 'open', ['CHOOSE']] )
        self.createLine( ['subtitle','<i>Optional input data</i>',
                          'Reference data and existing FreeR sets, if any'])

        # Reference data for MODE == MATCH: reflection data ...
        self.createLine( ['subtitle','1. Reference data to resolve indexing ambiguity and space group',
                          'In cases where there are indexing ambiguities, these can be resolved '+\
                          'by providing as reference a previously processed data set or '+\
                          'coordinates. The space group in the reference will be assumed to be correct'])

        self.createLine( ['label','   ', 'widget', 'REFERENCE_FOR_AIMLESS',
                          'label', ' use reference data in analysis against Batch after scaling'])
        self.connect(self.container.controlParameters.REFERENCE_FOR_AIMLESS,QtCore.SIGNAL('dataChanged'),
                     self.handleSelectAimlessReference)

        line_hklref = self.createLine( ['tip',
                          'The reference may be a merged or unmerged reflection list, of coordinates for Fcalc^2',
                                        'label','   Reference data are ','widget',  'REFERENCE_DATASET'])
        self.createLine( ['advice', ' and is optionally defined in next line'],
                          appendLine=line_hklref,
                          toggleFunction=[ self.refdataNotNeeded,
                                           [ 'MODE', 'HKLIN_REF', 'XYZIN_REF']] )
        self.createLine( ['advice', ' and MUST be defined in next line'],
                          appendLine=line_hklref,
                          toggleFunction=[ self.refdataNeeded,
                                           [ 'MODE', 'HKLIN_REF', 'XYZIN_REF']] )

        # reflection list ...
        self.createLine( ['widget','-browseDb', True,'HKLIN_REF'],
                        toggleFunction=[ self.openHKLIN_REF, [ 'MODE', 'REFERENCE_DATASET' ] ] )
        self.connect(self.container.inputData.HKLIN_REF,QtCore.SIGNAL('dataChanged'),
                     self.handleSelectHklinRef)
        # ... or coordinates
        self.createLine( ['widget', 'XYZIN_REF'],
                        toggleFunction=[ self.openXYZIN_REF, [ 'MODE', 'REFERENCE_DATASET' ] ] )
        self.connect(self.container.inputData.XYZIN_REF,QtCore.SIGNAL('dataChanged'),
                     self.handleSelectXyzinRef)

        # existing FreeR set
        self.createLine( ['subtitle',
                          '2. Optional existing FreeR set, define to copy or extend if necessary',
                          'If there are existing FreeR sets, you should choose a compatible one, '+\
                          'ie with same cell and point group'])
        
        self.createLine( ['widget', 'FREERFLAG'] )
        self.connect(self.container.inputData.FREERFLAG,QtCore.SIGNAL('dataChanged'),
                     self.handleSelectFreeRflag)
        
        self.createLine(['label', 'Fraction of reflections in generated freeR set',
                         'widget','FREER_FRACTION',
                         'advice', 'Default fraction is 0.05'],
                        toggle=['COMPLETE', 'closed', [True]] )


        # - - - - - - - - - - - - - - - - - - - - - - - - - - -  Important options folder
        self.openFolder(title='Important Options',drawFolder=self.drawImportant)

        

        # - - - - - - - - - - - - - - - - - - - - - - - - - - -  Additional options folder
        self.openFolder(title='Additional Options',drawFolder=self.drawAdditional)

    def drawImportant(self):

        self.createLine( ['subtitle',
                          'Options for symmetry determination in Pointless:   -------',
                       'Less common non-default options for crystal symmetry determination '])

        self.createLine( ['label','   Maximum resolution for scoring set by CC(1/2) in P1 > ',
                          'widget', 'CCHALFLIMIT','label',' [usual method, default 0.6]'])
        self.createLine( ['label','   Maximum resolution for scoring set by I/sigma(I) > ',
                          'widget', 'ISIGLIMIT','label',' [fall-back method, default 6]'])

        self.createLine( ['label','   Tolerance for comparing lattices (degrees or equivalent on lengths) ',
                          'widget', 'TOLERANCE','label',' [default 2.0]'])
        self.createLine(['label',' '])

        self.createLine( ['subtitle','Options for scaling and merging in Aimless:  -------',
                         'Less common non-default options in scaling and merging'])
        
        # intensity (profile/summation) and partials
        self.intensitiesAndPartials()
        # parameters for SDcorrection
        self.SDcorrection()
        # scaling
        self.scalingDetails()
        self.createLine(['label',' '])

        # Parameters for Free R
        self.createLine( ['subtitle','Options for FreeR set extension:  -------'])
        self.openSubFrame(frame=True, toggle=['COMPLETE', 'closed', [False]])

        self.createLine( ['advice','If you are extending an existing FreeR set, it must match the observed data in unit cell and Laue group'])
        self.createLine( ['advice','The unit cells should match to the lower resolution of the two datasets'])
        self.createLine([
            'tip','DANGEROUS: only sensible if the unit cells are very similar',
            'widget', 'OVERRIDE_CELL_DIFFERENCE',
                         'label', 'allow existing freeR set to have different unit cells'])
        self.createLine(['advice',
          '<span style="color: DarkOrange;font-weight: bold;">Be sure you know what you are doing: the cells must be very similar even if outside the test limits</span>'])
        self.closeSubFrame()


        # - - - - - - - - - - - - - - - - - - - - - - - - - - -  folder

    def drawAdditional(self):

        self.createLine(['label',' '])
        self.createLine( ['subtitle',
                          'Options for symmetry determination in Pointless:   -------',
                          'Common non-default options for crystal symmetry determination '])
        self.createLine( ['subtitle','   Choice of cell setting conventions:',
                          'The default option is the IUCr standard, but you may prefer '+\
                          '"reference" settings, eg P2<sub>1</sub>2<sub>1</sub>2 rather than '+\
                          'P22<sub>1</sub>2<sub>1</sub>, and also not to use I2 instead of C2'])
        self.createLine( ['widget', 'SET_SETTING'] )

        self.createLine(['label',' '])

        # Aimless things
        self.createLine(['subtitle',
                          'Options for scaling in Aimless:   -------',
                         'Common non-default options in scaling and merging'])
        self.scaleProtocol()
        self.rejectOutliers()
        self.createLine(['label',' '])

        self.createLine(['subtitle',
                          'Options for both Pointless and Aimless:   -------',
                         'Run definitions by batch range apply to both steps'])
        self.createLine(['subtitle',
                         '   Override automatic definition of runs to mark discontinuities in data',
              'Batch numbers after the 1st file may be incremented by a multiple of 1000, so this must be taken into account here'])

        self.createLine(['tip','by file mode applies only to Pointless',
                         'label','Run selection options',
                         'widget','-guiMode','radio', 'RUN_MODE'])

        self.createLine(['widget',
                         '-title','Batch ranges to define runs (after any renumbering in Pointless)',
                         'RUN_BATCHLIST'],
                        toggle=['RUN_MODE', 'open', ['BYRANGE']] )
        self.createLine(['label',' '])
    # -------------------------------------------------------------
    def getMaximumResolution( self ) :
        highRes = 1000000.0
        for i in range(len(self.container.inputData.UNMERGEDFILES)):
            if self.container.inputData.UNMERGEDFILES[i].file.fileContent.highRes.isSet():
                highRes = min(highRes, self.container.inputData.UNMERGEDFILES[i].file.fileContent.highRes.__float__())

        if  highRes > 999999.0:
            highRes = 0.0
        self.maximum_resolution_label.setText("%5.2f\xc5" % highRes)
        return True

    # -------------------------------------------------------------
    def getUnknownCell( self, force = False ) :
        # returns true is any files are of types which are missing the cell,
        # ie SCA unmerged or ShelX
        #print "getUnknownCell"

        # 1) if any file is of type SCA unmerged or ShelX, set cell from GUI or from known cell
        # 2) if any file is of type SCA or ShelX, set wavelength from GUI or from known wavelength
        # 3) if any file is of type SCA or ShelX, or MERGED, set ONLYMERGE, else set DEFAULT
        #  Not fool-proof if there are multiple files, but these will be picked up by Pointless

        anyunknowncell = False
        goodcell = None
        anyunknownwavelength = False
        goodwavelength = None
        anyunscaleablefile = False

        forceCell = False
        forceWavelength = False
        
        for i in range(len(self.container.inputData.UNMERGEDFILES)):
            print "fileContent", i, \
                  self.container.inputData.UNMERGEDFILES[i].file.fileContent
            print "self.container.inputData.UNMERGEDFILES[i]", self.container.inputData.UNMERGEDFILES[i]

            knowncell = self.container.inputData.UNMERGEDFILES[i].file.fileContent.knowncell
            # cell from file or GUI
            filecell = self.container.inputData.UNMERGEDFILES[i].cell
            contentcell = self.container.inputData.UNMERGEDFILES[i].file.fileContent.cell
            #print "Filecell, knowncell: ", filecell, knowncell
            #print "contentcell", contentcell, contentcell.isSet()
            if knowncell:
                # cell from file or GUI
                if contentcell.isSet():
                    goodcell = contentcell
                    forceCell = True
                else:
                    goodcell = filecell
            else:
                anyunknowncell = True

            knownwavelength = self.container.inputData.UNMERGEDFILES[i].file.fileContent.knownwavelength
            wavelength = self.container.inputData.UNMERGEDFILES[i].file.fileContent.wavelength
            #print 'knownwavelength, wavelength', knownwavelength, wavelength
            if knownwavelength:
                # wavelength from file or GUI
                goodwavelength = wavelength
                forceWavelength = True
            else:
                anyunknownwavelength = True

            fileformat = self.container.inputData.UNMERGEDFILES[i].file.fileContent.format
            mergedfile = self.container.inputData.UNMERGEDFILES[i].file.fileContent.merged
            print "fileformat, mergedfile", fileformat, mergedfile
            if (not knowncell) or (fileformat == 'sca') or (mergedfile == 'merged'):
                anyunscaleablefile = True

        # Set cell if needed
        #print "getUnknownCell setting things", anyunscaleablefile
        #print "self.container.guiControls.SCALING_PROTOCOL_SET", \
        #      self.container.guiControls.SCALING_PROTOCOL_SET
        if anyunknowncell:
            if goodcell is not None:
                self.container.controlParameters.CELL = goodcell
            else:
                self.container.controlParameters.CELL = filecell
        elif (force or forceCell):
             self.container.controlParameters.CELL.unSet()

        # Set wavelength if needed
        if anyunknownwavelength:
            if goodwavelength is not None:
                self.container.controlParameters.WAVELENGTH = goodwavelength
            else:
                self.container.controlParameters.WAVELENGTH = wavelength
        elif (force or forceWavelength):
             self.container.controlParameters.WAVELENGTH.unSet()

        if anyunscaleablefile:
            #print "anyunscaleablefile"
            self.container.controlParameters.ONLYMERGE = True
            self.container.controlParameters.SCALING_PROTOCOL = 'ONLYMERGE'
            self.container.guiControls.SCALING_PROTOCOL_SET = False
        else:
            if not self.container.guiControls.SCALING_PROTOCOL_SET:
                #print "SCALING_PROTOCOL_SET false"
                self.container.controlParameters.ONLYMERGE = False
                self.container.controlParameters.SCALING_PROTOCOL = 'DEFAULT'

        return (not anyunknowncell)

    '''
    # -------------------------------------------------------------
    def getInputBatches( self ) :
        
        import hklfile
        input_batches = ""
        for i in range(len(self.container.inputData.UNMERGEDFILES)):
            reflection_list = hklfile.ReflectionList()
            reflection_list.init(str(self.container.inputData.UNMERGEDFILES[i].file.fullPath))
            #            print self.container.inputData.UNMERGEDFILES[i].file.fullPath
            input_batches += reflection_list.formatBatchNumberlist()
            #print reflection_list.formatBatchNumberlist()
            input_batches += ", "
        
        #print dir(self.input_batches_label)
        if self.input_batches_label is not None:
            self.input_batches_label.setText(input_batches)
        
        if self.container.controlParameters.EXCLUDE_BATCH:
            return True
        else:
            return False
    '''
 
    # -------------------------------------------------------------
    def scaleProtocol(self):
        #  define Aimless scaling protocol and parameters, for all runs (for now)

        line = self.createLine(['label','Scale','widget','SCALING_PROTOCOL'])
        self.connect(self.container.controlParameters.SCALING_PROTOCOL, QtCore.SIGNAL('dataChanged'),
                     self.handleChangeProtocol)

        self.createLine(['label',' with relative B-factor','widget','BFACTOR_SCALE'],
                        appendLine=line,
                        toggleFunction=[self.scaleProtocolBfactorOn,
                                        ['SCALING_PROTOCOL', 'BFACTOR_SCALE']])
        self.createLine(['label',' with no relative B-factor','widget','BFACTOR_SCALE'],
                        appendLine=line,
                        toggleFunction=[self.scaleProtocolBfactorOff,
                                        ['SCALING_PROTOCOL', 'BFACTOR_SCALE']])
        # . . . . . {
        self.openSubFrame(toggleFunction=[self.scaleProtocolVariable, ['SCALING_PROTOCOL']])
        # . . . {
        self.openSubFrame(toggle=['SCALING_PROTOCOL','open',['ROTATION','SECONDARY']])
        line = self.createLine(['label','Define scale ranges along rotation axis by     ',
                                'widget','SCALES_ROTATION_TYPE'])
        self.createLine(['widget','SCALES_ROTATION_SPACING','label',' degrees'],
                        appendLine=line,
                        toggle=['SCALES_ROTATION_TYPE','open',['SPACING']])
        self.createLine(['widget','SCALES_ROTATION_NBINS'], appendLine=line,
                        toggle=['SCALES_ROTATION_TYPE','open',['NBINS']])
        line = self.createLine(['label','Define B-factor ranges along rotation axis by',
                                'widget','SCALES_BROTATION_TYPE'])
        self.createLine(['widget','SCALES_BROTATION_SPACING','label',' degrees'],
                        appendLine=line,
                        toggle=['SCALES_BROTATION_TYPE','open',['SPACING']])
        self.createLine(['widget','SCALES_BROTATION_NBINS'], appendLine=line,
                        toggle=['SCALES_BROTATION_TYPE','open',['NBINS']])
        
        self.closeSubFrame()
        # . . . }
        self.createLine(['label',
                         'Maximum order of spherical harmonics for secondary beam correction (eg 4 or 6) ',
                         'widget','SCALES_SECONDARY_NSPHHARMONICS'],
                        toggle=['SCALING_PROTOCOL','open',['SECONDARY']])
        # . . . {
        self.openSubFrame(toggle=['SCALING_PROTOCOL','open',['SECONDARY']])
        self.createLine(['label','Tile scaling for CCD detectors',
                         'widget','SCALES_TILETYPE'])
        self.createLine(['label','       number of tiles on X', 'widget', 'SCALES_NTILEX',
                         'label',' and on Y', 'widget', 'SCALES_NTILEY'],
                        toggle=['SCALES_TILETYPE','closed',['DEFAULT', 'NONE']])
        self.closeSubFrame()
        # . . . }
        
        self.closeSubFrame()
        # . . . . . }

    # -------------------------------------------------------------
    def rejectOutliers(self):
        # parameters for outlier rejection
        self.createLine(['widget','OUTLIER_OVERRIDE',
            'advice','override default parameters for outlier rejection'])

        # . . . . . {
        self.openSubFrame(frame=True, toggle=['OUTLIER_OVERRIDE','open',[True]])

        self.createLine(['label','Reject outliers if > ',
                                'widget','OUTLIER_SDMAX',
                                'label',' from mean, or > ',
                                'widget','OUTLIER_SDMAX2',
                                'label',' if 2 observations'])
        self.createLine(['label','Reject outliers between I+ and I- if > ', 
                         'widget','OUTLIER_SDMAXALL','label',', ',
                         'widget','OUTLIER_SDMAXALL_ADJUST',
                         'label',' increase for large anomalous differences'])
        line = self.createLine(['label','         ','widget','OUTLIER_COMBINE'])
        self.createLine(['label', ' compare outliers across all datasets'], appendLine=line,
                        toggle=['OUTLIER_COMBINE','open'])
        self.createLine(['label', ' compare outliers within each datasets'], appendLine=line,
                        toggle=['OUTLIER_COMBINE','closed'])

        self.createLine(['label', 'Set maximum E to reject unreasonably large intensities',
                        'widget','OUTLIER_EMAX'])

        self.closeSubFrame()
        # . . . . . }

    # -------------------------------------------------------------
    def SDcorrection(self)  :
        # parameters for SD correction
        self.createLine(['widget','SDCORRECTION_OVERRIDE',
                         'advice','override default parameters for SD correction'])

        # . . . . . {
        self.openSubFrame(frame=True, toggle=['SDCORRECTION_OVERRIDE','open',[True]])
        line = self.createLine(['widget','SDCORRECTION_REFINE'])
        self.createLine(['label','refine SDcorrection parameters'],appendLine=line,
                        toggle=['SDCORRECTION_REFINE','open',[True]])
        self.createLine(['label','do not refine SDcorrection parameters'],appendLine=line,
                        toggle=['SDCORRECTION_REFINE','open',[False]])

        self.createLine(['widget','SDCORRECTION_SET',
                         'label','set SD correction parameters: SdFac',
                         'widget','SDCORRECTION_SDFAC',
                         'label','   SdB','widget','SDCORRECTION_SDB',
                         'label','   SdAdd','widget','SDCORRECTION_SDADD'],
                        toggle=['SDCORRECTION_REFINE','open',[False]])
        self.connect(self.container.controlParameters.SDCORRECTION_SDFAC,
                     QtCore.SIGNAL('dataChanged'),self.handleSetSDcorrection)
        self.connect(self.container.controlParameters.SDCORRECTION_SDB,
                     QtCore.SIGNAL('dataChanged'),self.handleSetSDcorrection)
        self.connect(self.container.controlParameters.SDCORRECTION_SDADD,
                     QtCore.SIGNAL('dataChanged'),self.handleSetSDcorrection)

        
        line = self.createLine(['widget','SDCORRECTION_OPTIONS',
                                'label','to be determined'],
                               toggleFunction=[self.getSDcorrectionlabel,
                                               ['SDCORRECTION_REFINE','SDCORRECTION_OPTIONS']] )
        # get label widget, note itemAt counts from 0
        self.sdcorrection_label = line.layout().itemAt(1).widget()

        line = self.createLine(['widget','SDCORRECTION_FIXSDB','label','fix sdB parameters'],
                        toggle=['SDCORRECTION_REFINE','open',[True]])
        self.createLine(['spacing',150,'label','SD to tie sdB to zero',
                         'widget','SDCORRECTION_TIESDB_SD'],appendLine=line)

        line = self.createLine(['advice','Similarity restraint SDs: '],
                        toggleFunction=[self.SDcorrectionSimilar,
                                        ['SDCORRECTION_REFINE','SDCORRECTION_OPTIONS']])
        self.createLine(['label','sdFac','widget','SDCORRECTION_SIMILARITY_SDFAC'],
                        appendLine=line)
        self.createLine(['label',' sdB','widget','SDCORRECTION_SIMILARITY_SDB'],
                        appendLine=line)
        self.createLine(['label',' sdAdd','widget','SDCORRECTION_SIMILARITY_SDADD'],
                        appendLine=line)
        self.closeSubFrame()
        # . . . . . }

    # -------------------------------------------------------------
    def handleSetSDcorrection(self):
        self.container.controlParameters.SDCORRECTION_SET = True

    # -------------------------------------------------------------
    def SDcorrectionSimilar(self):
        if self.container.controlParameters.SDCORRECTION_REFINE:
            if self.container.controlParameters.SDCORRECTION_OPTIONS == 'SIMILAR':
                return True
        return False
        
    # -------------------------------------------------------------
    def getSDcorrectionlabel(self):

        s = ""
        if self.container.controlParameters.SDCORRECTION_REFINE:
            if self.container.controlParameters.SDCORRECTION_OPTIONS == 'INDIVIDUAL':
                s = " different parameters for each run"
            elif self.container.controlParameters.SDCORRECTION_OPTIONS == 'SAME':
                s = " same parameters for each run"
            elif self.container.controlParameters.SDCORRECTION_OPTIONS == 'SIMILAR':
                s = " similar parameters for each run"
            self.sdcorrection_label.setText(s)
            return True
        else:
            self.sdcorrection_label.setText(s)
            return False

    # -------------------------------------------------------------
    def intensitiesAndPartials(self):
        # parameters for intensity selection
        self.createLine(['widget','INTENSITIES_OVERRIDE',
                         'advice',
       'override default parameters for selection of intensities and treatment of partials'])

        # . . . . . {
        self.openSubFrame(frame=True, toggle=['INTENSITIES_OVERRIDE','open',[True]])
        line = self.createLine(['label','Use','widget','INTENSITIES_OPTIONS'])
        self.createLine(['label','(profile-fitted for weak intensities, summation for strong)'],
                        appendLine=line,
                        toggle=['INTENSITIES_OPTIONS','open',['COMBINE']])
        self.createLine(['widget','PARTIALS_TEST',
                         'label','Only accept partials with total fraction between',
                         'widget','PARTIALS_FRACLOW','label',' and',
                         'widget','PARTIALS_FRACHIGH'])
        self.connect(self.container.controlParameters.PARTIALS_FRACLOW,
                     QtCore.SIGNAL('dataChanged'),self.handlePartialstest)
        self.connect(self.container.controlParameters.PARTIALS_FRACHIGH,
                     QtCore.SIGNAL('dataChanged'),self.handlePartialstest)

        line = self.createLine(['widget','PARTIALS_CHECK'])
        self.createLine(['label','Scale partials outside rejection range'],
                        appendLine=line,
                        toggle=['PARTIALS_CHECK','open',[False]])
        self.createLine(['label','Scale partials in range',
                         'widget','PARTIALS_SCALE_MIN',
                         'label','to lower acceptance limit'],
                        appendLine=line,
                        toggle=['PARTIALS_CHECK','open',[True]])
        self.createLine(['widget','ACCEPT_OVERLOADS',
                         'label',' accept overloaded observations'])
        self.createLine(['widget','ACCEPT_EDGES',
                         'label',' accept observations on edge of tile or detector'])
        self.createLine(['widget','ACCEPT_XDS_MISFITS',
                         'label',' accept observations flagged by XDS as outliers (MISFITS)'])
    
        self.closeSubFrame()
        # . . . . . }

    # -------------------------------------------------------------
    def handlePartialstest(self):
        self.container.controlParameters.PARTIALS_TEST = True

    # -------------------------------------------------------------
    def scalingDetails(self):
        # parameters for scaling
        self.createLine(['widget','SCALING_DETAILS',
                         'advice','override default parameters for scaling details'])

        # . . . . . {
        self.openSubFrame(frame=True, toggle=['SCALING_DETAILS','open',[True]])
        self.createLine(['widget','CYCLES_FLAG',
                         'label','Refine scale factors for',
                         'widget','CYCLES_N','label','cycles'])
        self.connect(self.container.controlParameters.CYCLES_N,
                     QtCore.SIGNAL('dataChanged'),self.handleNcycles)
        self.createLine(['widget','SELECT1','widget','SELECT_IOVSDMIN',
                         'label','minimum I/sd for 1st round scaling   ',
                         'widget','SELECT2','widget','SELECT_EMIN',
                         'label','minimum E for 2nd round scaling'])
        self.connect(self.container.controlParameters.SELECT_IOVSDMIN,
                     QtCore.SIGNAL('dataChanged'),self.handleSelect1)
        self.connect(self.container.controlParameters.SELECT_EMIN,
                     QtCore.SIGNAL('dataChanged'),self.handleSelect2)
        self.createLine(['widget','TIE_ROTATION','label',
                         'Restrain neighbouring scale factors on rotation axis with SD',
                         'widget','TIE_ROTATION_SD'])
        self.connect(self.container.controlParameters.TIE_ROTATION_SD,
                     QtCore.SIGNAL('dataChanged'),self.handleTie_rotation_sd)
        self.createLine(['widget','TIE_SURFACE','label',
                         'Restrain surface parameters to a sphere with SD',
                         'widget','TIE_SURFACE_SD'])
        self.connect(self.container.controlParameters.TIE_SURFACE_SD,
                     QtCore.SIGNAL('dataChanged'),self.handleTie_surface_sd)
        self.createLine(['widget','TIE_BFACTOR','label',
                         'Restrain neighbouring B-factors on rotation axis with SD',
                         'widget','TIE_BFACTOR_SD'])
        self.connect(self.container.controlParameters.TIE_BFACTOR_SD,
                     QtCore.SIGNAL('dataChanged'),self.handleTie_bfactor_sd)
        self.createLine(['widget','TIE_BZERO','label',
                         'Restrain B-factors to zero with SD',
                         'widget','TIE_BZERO_SD'])
        self.connect(self.container.controlParameters.TIE_BZERO_SD,
                     QtCore.SIGNAL('dataChanged'),self.handleTie_bzero_sd)
        
        self.closeSubFrame()
        # . . . . . }

    # -------------------------------------------------------------
    def handleNcycles(self):
        self.container.controlParameters.CYCLES_FLAG = True

    # -------------------------------------------------------------
    def handleSelect1(self):
        self.container.controlParameters.SELECT1 = True

    # -------------------------------------------------------------
    def handleSelect2(self):
        self.container.controlParameters.SELECT2 = True

    # -------------------------------------------------------------
    def handleTie_rotation_sd(self):
        self.container.controlParameters.TIE_ROTATION = True

    # -------------------------------------------------------------
    def handleTie_surface_sd(self):
        self.container.controlParameters.TIE_SURFACE = True

    # -------------------------------------------------------------
    def handleTie_bfactor_sd(self):
        self.container.controlParameters.TIE_BFACTOR = True

    # -------------------------------------------------------------
    def handleTie_bzero_sd(self):
        self.container.controlParameters.TIE_BZERO = True

    # -------------------------------------------------------------
    def openHKLIN_REF( self ) :
        
        par = self.container.controlParameters
        if par.REFERENCE_DATASET == 'HKL':
            return True
        else:
            return False

    # -------------------------------------------------------------
    def openXYZIN_REF( self ) :

        par = self.container.controlParameters
        if par.REFERENCE_DATASET == 'XYZ':
            return True
        else:
            return False

    # -------------------------------------------------------------
    def handleSelectAimlessReference(self):
        if self.container.controlParameters.REFERENCE_FOR_AIMLESS:
            self.container.controlParameters.REFERENCE_DATASET = 'XYZ'
        else:
            self.container.controlParameters.REFERENCE_DATASET = 'HKL'

    # -------------------------------------------------------------
    def handleSelectHklinRef(self):

     if self.container.inputData.HKLIN_REF.isSet():
         self.container.controlParameters.MODE = 'MATCH'
     else:
         # Don't forget users can unselect something!
         if self.container.controlParameters.MODE == 'MATCH':
             self.container.controlParameters.MODE = 'LAUE'

    # -------------------------------------------------------------
    def handleSelectXyzinRef(self):

     if self.container.inputData.XYZIN_REF.isSet():
         self.container.controlParameters.MODE = 'MATCH'
     else:
         # Don't forget users can unselect something!
         if self.container.controlParameters.MODE == 'MATCH':
             self.container.controlParameters.MODE = 'LAUE'

    # -------------------------------------------------------------
    def handleChangeMode(self):

        if self.container.controlParameters.MODE != 'MATCH':
            self.container.inputData.HKLIN_REF.unSet()
            self.container.inputData.XYZIN_REF.unSet()


    # -------------------------------------------------------------
    def handleSelectFreeRflag(self):

        if self.container.inputData.FREERFLAG.isSet():
            self.container.controlParameters.COMPLETE = True
        else:
            self.container.controlParameters.COMPLETE = False

    # -------------------------------------------------------------
    def handleChangeProtocol(self):
        #print "ChangeProtocol", self.container.controlParameters.SCALING_PROTOCOL
        #print "Protocol", self.container.guiControls.SCALING_PROTOCOL_SET
        self.container.guiControls.SCALING_PROTOCOL_SET = True
        if self.container.controlParameters.SCALING_PROTOCOL != 'ONLYMERGE':
            self.container.controlParameters.ONLYMERGE = False

    # -------------------------------------------------------------
    def refdataNotNeeded(self):
#        if self.container.inputData.HKLIN_REF.isSet() or \
#           self.container.inputData.XYZIN_REF.isSet():
#            return True

        if self.container.controlParameters.MODE != 'MATCH':
            return True

        return False
        
    # -------------------------------------------------------------
    def refdataNeeded(self):
        
        if self.container.controlParameters.MODE == 'MATCH':
            return True

        return False

    # -------------------------------------------------------------
    def scaleProtocolVariable(self):
        # True if scaling protocol not DEFAULT or CONSTANT or ONLYMERGE
        if ((self.container.controlParameters.SCALING_PROTOCOL != 'DEFAULT') and
            (self.container.controlParameters.SCALING_PROTOCOL != 'CONSTANT') and
            (self.container.controlParameters.SCALING_PROTOCOL != 'ONLYMERGE')):
            return True
        return False

    # -------------------------------------------------------------
    def scaleProtocolBfactorOn(self):
        if (self.scaleProtocolVariable()
            and self.container.controlParameters.BFACTOR_SCALE):
            return True
        return False

    # -------------------------------------------------------------
    def scaleProtocolBfactorOff(self):
        if (self.scaleProtocolVariable()
            and (not self.container.controlParameters.BFACTOR_SCALE)):
            return True
        return False

