class EDPluginControlStrategyv10(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """

    def __init__ (self):
        EDPluginControl.__init__(self)

        self.__strPluginRaddoseName = "EDPluginRaddosev10"
        self.__oedPluginRaddose = None
        self.__oedHandlerXSDataRaddose = None

        self.__strPluginBestName = "EDPluginBestv10"
        self.__edPluginBest = None
        self.__edHandlerXSDataBest = None

        self.__strCONF_SYMOP_HOME = "symopHome"
        # Default value for the location of the symop table
        self.__strSymopHome = "/opt/pxsoft/ccp4-6.0.2/lib/data"

        self.__xsDataSampleCopy = None

        # For default chemical composition
        self.__fAverageAminoAcidVolume = 135.49
        self.__fAverageCrystalSolventContent = 0.47
        self.__fAverageSulfurContentPerAminoacid = 0.05
        self.__fAverageSulfurConcentration = 314

        self.setXSDataInputClass(XSDataStrategyInput)


    def setSymopHome(self, _strSymopHome):
        self.__strSymopHome = _strSymopHome


    def getSymopHome(self):
        return self.__strSymopHome


    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        EDVerbose.DEBUG("EDPluginControlStrategyv10.preProcess...")
        self.__edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput().getSample()

        if(xsDataSampleCrystalMM is None):
            self.__xsDataSampleCopy = XSDataSampleCrystalMM()

        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self.__xsDataSampleCopy = XSDataSampleCrystalMM.parseString(strXmlStringDataSample)

        xsDataCrystal = self.getDataInput().getCrystalRefined()
        if(xsDataCrystal is not None):
            self.__xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Raddose is enabled only if the beam flux is set
        if(self.getDataInput().getExperimentalCondition().getBeam().getFlux() is None):
            warningMessage = EDMessage.WARNING_CANNOT_USE_PLUGIN_03 % ('EDPluginControlStrategyv10.preProcess', self.__strPluginRaddoseName, "Beam Flux not set")
            EDVerbose.warning(warningMessage)
            self.addWarningMessage(warningMessage)

        else:
            self.__edPluginRaddose = self.loadPlugin(self.__strPluginRaddoseName)

            if (self.__edPluginRaddose is not None):
                EDVerbose.DEBUG("EDPluginControlStrategyv10.preProcess: " + self.__strPluginRaddoseName + " Found... setting Data Input")

                strFileSymop = os.path.join(self.getSymopHome(), "symop.lib")

                xsDataStringSpaceGroup = self.getDataInput().getDiffractionPlan().getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                if(xsDataStringSpaceGroup is not None):
                    strSpaceGroup = xsDataStringSpaceGroup.getValue()
                    EDVerbose.DEBUG("EDPluginControlStrategyv10.preProcess: Forced Space Group Found: " + strSpaceGroup)
                    try:
                        strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(strSpaceGroup, strFileSymop)
                    except Exception, detail:
                        errorMessage = EDMessage.ERROR_EXECUTION_03 % ('EDPluginControlStrategyv10.preProcess', "Problem to calculate Number of symmetry operators", detail)
                        EDVerbose.error(errorMessage)
                        self.addErrorMessage(errorMessage)
                        raise RuntimeError, errorMessage
                # Space Group has NOT been forced
                else:
                    xsDataStringSpaceGroup = self.__xsDataSampleCopy.getCrystal().getSpaceGroup().getName()
                    if (xsDataStringSpaceGroup is not None):
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroupName = self.__xsDataSampleCopy.getCrystal().getSpaceGroup().getName().getValue()
                        EDVerbose.DEBUG("EDPluginControlStrategyv10.preProcess: Space Group IT Name found by indexing: " + strSpaceGroupName)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(strSpaceGroupName, strFileSymop)
                        except Exception, detail:
                            errorMessage = EDMessage.ERROR_EXECUTION_03 % ('EDPluginControlStrategyv10.preProcess', "Problem to calculate Number of symmetry operators", detail)
                            EDVerbose.error(errorMessage)
                            self.addErrorMessage(errorMessage)
                            raise RuntimeError, errorMessage
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        strSpaceGroupITNumber = str(self.__xsDataSampleCopy.getCrystal().getSpaceGroup().getITNumber().getValue())
                        EDVerbose.DEBUG("EDPluginControlStrategyv10.preProcess: Space Group IT Number Found by indexing: " + strSpaceGroupITNumber)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(strSpaceGroupITNumber, strFileSymop)
                        except Exception, detail:
                            errorMessage = EDMessage.ERROR_EXECUTION_03 % ('EDPluginControlStrategyv10.preProcess', "Problem to calculate Number of symmetry operators", detail)
                            EDVerbose.error(errorMessage)
                            self.addErrorMessage(errorMessage)
                            raise RuntimeError, errorMessage
class EDPluginControlStrategyv1_1(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """
    def __init__(self):
        EDPluginControl.__init__(self)
        self.setXSDataInputClass(XSDataInputStrategy)

        self.__strPluginRaddoseName = "EDPluginRaddosev10"
        self.__edPluginRaddose = None
        self.__edHandlerXSDataRaddose = None

        self.__strPluginBestName = "EDPluginBestv1_1"
        self.__edPluginBest = None
        self.__edHandlerXSDataBest = None

        self.__strCONF_SYMOP_HOME = "symopHome"
        # Default value for the location of the symop table
        self.__strSymopHome = "/opt/pxsoft/ccp4-6.0.2/lib/data"

        self.__xsDataSampleCopy = None

        # For default chemical composition
        self.__fAverageAminoAcidVolume = 135.49
        self.__fAverageCrystalSolventContent = 0.47
        self.__fAverageSulfurContentPerAminoacid = 0.05
        self.__fAverageSulfurConcentration = 314

    def setSymopHome(self, _strSymopHome):
        self.__strSymopHome = _strSymopHome

    def getSymopHome(self):
        return self.__strSymopHome

    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        EDVerbose.DEBUG("EDPluginControlStrategyv1_1.preProcess...")
        self.__edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput().getSample()

        if (xsDataSampleCrystalMM is None):
            self.__xsDataSampleCopy = XSDataSampleCrystalMM()

        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self.__xsDataSampleCopy = XSDataSampleCrystalMM.parseString(
                strXmlStringDataSample)

        xsDataCrystal = self.getDataInput().getCrystalRefined()
        if (xsDataCrystal is not None):
            self.__xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Raddose is enabled only if the beam flux is set
        if (self.getDataInput().getExperimentalCondition().getBeam().getFlux()
                is None):
            pyStrWarningMessage = EDMessage.WARNING_CANNOT_USE_PLUGIN_03 % (
                'EDPluginControlStrategyv1_1.preProcess',
                self.__strPluginRaddoseName, "Beam Flux not set")
            EDVerbose.warning(pyStrWarningMessage)
            self.addWarningMessage(pyStrWarningMessage)

        else:
            self.__edPluginRaddose = self.loadPlugin(
                self.__strPluginRaddoseName)

            if (self.__edPluginRaddose is not None):
                EDVerbose.DEBUG("EDPluginControlStrategyv1_1.preProcess: " +
                                self.__strPluginRaddoseName +
                                " Found... setting Data Input")

                strFileSymop = os.path.join(self.getSymopHome(), "symop.lib")

                xsDataStringSpaceGroup = self.getDataInput(
                ).getDiffractionPlan().getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                strNumOperators = None
                strSpaceGroup = None
                if (xsDataStringSpaceGroup is not None):
                    strSpaceGroup = xsDataStringSpaceGroup.getValue().upper()
                    EDVerbose.DEBUG(
                        "EDPluginControlStrategyv1_1.preProcess: Forced Space Group Found: "
                        + strSpaceGroup)
                    try:
                        strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                            strSpaceGroup, strFileSymop)
                    except Exception, detail:
                        pyStrErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                            'EDPluginControlStrategyv1_1.preProcess',
                            "Problem to calculate Number of symmetry operators",
                            detail)
                        EDVerbose.error(pyStrErrorMessage)
                        self.addErrorMessage(pyStrErrorMessage)
                        self.setFailure()
                # Space Group has NOT been forced
                else:
                    xsDataStringSpaceGroup = self.__xsDataSampleCopy.getCrystal(
                    ).getSpaceGroup().getName()
                    if (xsDataStringSpaceGroup is not None):
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroupName = self.__xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getName().getValue()
                        EDVerbose.DEBUG(
                            "EDPluginControlStrategyv1_1.preProcess: Space Group IT Name found by indexing: "
                            + strSpaceGroupName)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                strSpaceGroupName, strFileSymop)
                        except Exception, detail:
                            pyStrErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                                'EDPluginControlStrategyv1_1.preProcess',
                                "Problem to calculate Number of symmetry operators",
                                detail)
                            EDVerbose.error(pyStrErrorMessage)
                            self.addErrorMessage(pyStrErrorMessage)
                            self.setFailure()
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        iSpaceGroupITNumber = self.__xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getITNumber().getValue()
                        EDVerbose.DEBUG(
                            "EDPluginControlStrategyv1_1.preProcess: Space Group IT Number Found by indexing: "
                            + str(iSpaceGroupITNumber))
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(
                                str(iSpaceGroupITNumber), strFileSymop)
                        except Exception, detail:
                            pyStrErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                                'EDPluginControlStrategyv1_1.preProcess',
                                "Problem to calculate Number of symmetry operators",
                                detail)
                            EDVerbose.error(pyStrErrorMessage)
                            self.addErrorMessage(pyStrErrorMessage)
                            self.setFailure()
Esempio n. 3
0
class EDPluginControlStrategyv1_2(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """
    def __init__(self):
        """
        """
        EDPluginControl.__init__(self)
        self.setXSDataInputClass(XSDataInputStrategy)

        self._strPluginRaddoseName = "EDPluginRaddosev10"
        self._edPluginRaddose = None
        self._edHandlerXSDataRaddose = None

        self._strPluginBestName = "EDPluginBestv1_2"
        self._edPluginBest = None
        self._edHandlerXSDataBest = None

        self._strPluginPlotGleName = "EDPluginExecPlotGlev1_0"
        self._edPluginPlotGle = None

        self._strCONF_SYMOP_HOME = "symopHome"
        # Default value for the location of the symop table
        self._strSymopHome = None

        self._xsDataSampleCopy = None

        # For default chemical composition
        self._fAverageAminoAcidVolume = 135.49
        self._fAverageCrystalSolventContent = 0.47
        self._fAverageSulfurContentPerAminoacid = 0.05
        self._fAverageSulfurConcentration = 314

        # This varaible determines if Raddose should be executed or not
        self._bEstimateRadiationDamage = None

        # Raddose log file
        self.xsDataFileRaddoseLog = None

    def setSymopHome(self, _strSymopHome):
        self._strSymopHome = _strSymopHome

    def getSymopHome(self):
        return self._strSymopHome

    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        EDVerbose.DEBUG("EDPluginControlStrategyv1_2.preProcess...")
        self._edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput().getSample()

        if (xsDataSampleCrystalMM is None):
            self._xsDataSampleCopy = XSDataSampleCrystalMM()
        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self._xsDataSampleCopy = XSDataSampleCrystalMM.parseString(
                strXmlStringDataSample)

        xsDataCrystal = self.getDataInput().getCrystalRefined()
        if (xsDataCrystal is not None):
            self._xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Load the Best plugin
        self._edPluginBest = self.loadPlugin(self._strPluginBestName)
        self._edPluginBest.setBaseDirectory(self.getWorkingDirectory())
        self._edPluginBest.setBaseName(self._strPluginBestName)

        # Load the plot gle plugin
        self._edPluginPlotGle = self.loadPlugin(self._strPluginPlotGleName)

        # Check if radiation damage estimation is required or not in the diffraction plan
        xsDataDiffractionPlan = self.getDataInput().getDiffractionPlan()
        if xsDataDiffractionPlan is not None:
            if xsDataDiffractionPlan.getEstimateRadiationDamage():
                if xsDataDiffractionPlan.getEstimateRadiationDamage().getValue(
                ):
                    # Yes, is requested
                    self._bEstimateRadiationDamage = True
                else:
                    # No, is explicitly not requested
                    self._bEstimateRadiationDamage = False
            elif xsDataDiffractionPlan.getStrategyOption() is not None:
                if xsDataDiffractionPlan.getStrategyOption().getValue().find(
                        "-DamPar") != -1:
                    # The "-DamPar" option requires estimation of radiation damage
                    self._bEstimateRadiationDamage = True

        # Check if we know what to do with radiation damage
        if self._bEstimateRadiationDamage is None:
            # "Force" the estimation of radiation damage if the flux is present
            if self.getDataInput().getExperimentalCondition().getBeam(
            ).getFlux() is None:
                strWarningMessage = "EDPluginControlStrategyv1_2: Missing flux input - cannot estimate radiation damage."
                EDVerbose.WARNING(strWarningMessage)
                self.addWarningMessage(strWarningMessage)
                self._bEstimateRadiationDamage = False
            else:
                self._bEstimateRadiationDamage = True

        if self._bEstimateRadiationDamage:
            if self.getDataInput().getExperimentalCondition().getBeam(
            ).getFlux() is None:
                strErrorMessage = "EDPluginControlStrategyv1_2: Missing flux input. Cannot estimate radiation damage"
                EDVerbose.ERROR(strErrorMessage)
                self.addErrorMessage(strErrorMessage)
                self.setFailure()

        if not self.isFailure():

            self._edPluginRaddose = self.loadPlugin(self._strPluginRaddoseName)

            if (self._edPluginRaddose is not None):
                EDVerbose.DEBUG("EDPluginControlStrategyv1_2.preProcess: " +
                                self._strPluginRaddoseName +
                                " Found... setting Data Input")

                strFileSymop = os.path.join(self.getSymopHome(), "symop.lib")

                xsDataStringSpaceGroup = self.getDataInput(
                ).getDiffractionPlan().getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                if (xsDataStringSpaceGroup is not None):
                    strSpaceGroup = xsDataStringSpaceGroup.getValue().upper()
                    EDVerbose.DEBUG(
                        "EDPluginControlStrategyv1_2.preProcess: Forced Space Group Found: "
                        + strSpaceGroup)
                    try:
                        strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                            strSpaceGroup, strFileSymop)
                    except Exception, detail:
                        strErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                            'EDPluginControlStrategyv1_2.preProcess',
                            "Problem to calculate Number of symmetry operators",
                            detail)
                        EDVerbose.error(strErrorMessage)
                        self.addErrorMessage(strErrorMessage)
                        raise RuntimeError, strErrorMessage
                # Space Group has NOT been forced
                else:
                    xsDataStringSpaceGroup = self._xsDataSampleCopy.getCrystal(
                    ).getSpaceGroup().getName()
                    if (xsDataStringSpaceGroup is not None):
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroupName = self._xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getName().getValue()
                        EDVerbose.DEBUG(
                            "EDPluginControlStrategyv1_2.preProcess: Space Group IT Name found by indexing: "
                            + strSpaceGroupName)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                strSpaceGroupName, strFileSymop)
                        except Exception, detail:
                            strErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                                'EDPluginControlStrategyv1_2.preProcess',
                                "Problem to calculate Number of symmetry operators",
                                detail)
                            EDVerbose.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        iSpaceGroupITNumber = self._xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getITNumber().getValue()
                        EDVerbose.DEBUG(
                            "EDPluginControlStrategyv1_2.preProcess: Space Group IT Number Found by indexing: %d"
                            % iSpaceGroupITNumber)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(
                                str(iSpaceGroupITNumber), strFileSymop)
                        except Exception, detail:
                            strErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                                'EDPluginControlStrategyv1_2.preProcess',
                                "Problem to calculate Number of symmetry operators",
                                detail)
                            EDVerbose.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
class EDPluginControlStrategyv1_2(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """

    def __init__ (self):
        """
        """
        EDPluginControl.__init__(self)
        self.setXSDataInputClass(XSDataInputStrategy)

        self._strPluginRaddoseName = "EDPluginRaddosev10"
        self._edPluginRaddose = None
        self._edHandlerXSDataRaddose = None

        self._strPluginBestName = "EDPluginBestv1_2"
        self._edPluginBest = None
        self._edHandlerXSDataBest = None

        self._strPluginPlotGleName = "EDPluginExecPlotGlev1_0"
        self._edPluginPlotGle = None

        self._strCONF_SYMOP_HOME = "symopHome"
        # Default value for the location of the symop table
        self._strSymopHome = None

        self._xsDataSampleCopy = None

        # For default chemical composition
        self._fAverageAminoAcidVolume = 135.49
        self._fAverageCrystalSolventContent = 0.47
        self._fAverageSulfurContentPerAminoacid = 0.05
        self._fAverageSulfurConcentration = 314

        # This varaible determines if Raddose should be executed or not
        self._bEstimateRadiationDamage = None
        
        # Raddose log file
        self.xsDataFileRaddoseLog = None


    def setSymopHome(self, _strSymopHome):
        self._strSymopHome = _strSymopHome


    def getSymopHome(self):
        return self._strSymopHome


    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        EDVerbose.DEBUG("EDPluginControlStrategyv1_2.preProcess...")
        self._edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput().getSample()

        if(xsDataSampleCrystalMM is None):
            self._xsDataSampleCopy = XSDataSampleCrystalMM()
        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self._xsDataSampleCopy = XSDataSampleCrystalMM.parseString(strXmlStringDataSample)

        xsDataCrystal = self.getDataInput().getCrystalRefined()
        if(xsDataCrystal is not None):
            self._xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Load the Best plugin
        self._edPluginBest = self.loadPlugin(self._strPluginBestName)
        self._edPluginBest.setBaseDirectory(self.getWorkingDirectory())
        self._edPluginBest.setBaseName(self._strPluginBestName)

        # Load the plot gle plugin
        self._edPluginPlotGle = self.loadPlugin(self._strPluginPlotGleName)

        # Check if radiation damage estimation is required or not in the diffraction plan
        xsDataDiffractionPlan = self.getDataInput().getDiffractionPlan()
        if xsDataDiffractionPlan is not None:
            if xsDataDiffractionPlan.getEstimateRadiationDamage():
                if xsDataDiffractionPlan.getEstimateRadiationDamage().getValue():
                    # Yes, is requested
                    self._bEstimateRadiationDamage = True
                else:
                    # No, is explicitly not requested
                    self._bEstimateRadiationDamage = False
            elif xsDataDiffractionPlan.getStrategyOption() is not None:
                if xsDataDiffractionPlan.getStrategyOption().getValue().find("-DamPar") != -1:
                    # The "-DamPar" option requires estimation of radiation damage
                    self._bEstimateRadiationDamage = True

        # Check if we know what to do with radiation damage
        if self._bEstimateRadiationDamage is None:
            # "Force" the estimation of radiation damage if the flux is present
            if self.getDataInput().getExperimentalCondition().getBeam().getFlux() is None:
                strWarningMessage = "EDPluginControlStrategyv1_2: Missing flux input - cannot estimate radiation damage."
                EDVerbose.WARNING(strWarningMessage)
                self.addWarningMessage(strWarningMessage)
                self._bEstimateRadiationDamage = False
            else:
                self._bEstimateRadiationDamage = True


        if self._bEstimateRadiationDamage:
            if self.getDataInput().getExperimentalCondition().getBeam().getFlux() is None:
                strErrorMessage = "EDPluginControlStrategyv1_2: Missing flux input. Cannot estimate radiation damage"
                EDVerbose.ERROR(strErrorMessage)
                self.addErrorMessage(strErrorMessage)
                self.setFailure()

        if not self.isFailure():

            self._edPluginRaddose = self.loadPlugin(self._strPluginRaddoseName)

            if (self._edPluginRaddose is not None):
                EDVerbose.DEBUG("EDPluginControlStrategyv1_2.preProcess: " + self._strPluginRaddoseName + " Found... setting Data Input")

                strFileSymop = os.path.join(self.getSymopHome(), "symop.lib")

                xsDataStringSpaceGroup = self.getDataInput().getDiffractionPlan().getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                if(xsDataStringSpaceGroup is not None):
                    strSpaceGroup = xsDataStringSpaceGroup.getValue().upper()
                    EDVerbose.DEBUG("EDPluginControlStrategyv1_2.preProcess: Forced Space Group Found: " + strSpaceGroup)
                    try:
                        strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(strSpaceGroup, strFileSymop)
                    except Exception, detail:
                        strErrorMessage = EDMessage.ERROR_EXECUTION_03 % ('EDPluginControlStrategyv1_2.preProcess', "Problem to calculate Number of symmetry operators", detail)
                        EDVerbose.error(strErrorMessage)
                        self.addErrorMessage(strErrorMessage)
                        raise RuntimeError, strErrorMessage
                # Space Group has NOT been forced
                else:
                    xsDataStringSpaceGroup = self._xsDataSampleCopy.getCrystal().getSpaceGroup().getName()
                    if (xsDataStringSpaceGroup is not None):
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroupName = self._xsDataSampleCopy.getCrystal().getSpaceGroup().getName().getValue()
                        EDVerbose.DEBUG("EDPluginControlStrategyv1_2.preProcess: Space Group IT Name found by indexing: " + strSpaceGroupName)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(strSpaceGroupName, strFileSymop)
                        except Exception, detail:
                            strErrorMessage = EDMessage.ERROR_EXECUTION_03 % ('EDPluginControlStrategyv1_2.preProcess', "Problem to calculate Number of symmetry operators", detail)
                            EDVerbose.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        iSpaceGroupITNumber = self._xsDataSampleCopy.getCrystal().getSpaceGroup().getITNumber().getValue()
                        EDVerbose.DEBUG("EDPluginControlStrategyv1_2.preProcess: Space Group IT Number Found by indexing: %d" % iSpaceGroupITNumber)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(str(iSpaceGroupITNumber), strFileSymop)
                        except Exception, detail:
                            strErrorMessage = EDMessage.ERROR_EXECUTION_03 % ('EDPluginControlStrategyv1_2.preProcess', "Problem to calculate Number of symmetry operators", detail)
                            EDVerbose.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
class EDPluginControlStrategyv1_2(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """

    def __init__(self):
        """
        """
        EDPluginControl.__init__(self)
        self.setXSDataInputClass(XSDataInputStrategy)

        self._strPluginRaddoseName = "EDPluginRaddosev10"
        self._edPluginRaddose = None
        self._edHandlerXSDataRaddose = None

        self._strPluginBestName = "EDPluginBestv1_2"
        self._edPluginBest = None
        self._edHandlerXSDataBest = None

        self._strPluginPlotGleName = "EDPluginExecPlotGlev1_1"
        self._edPluginPlotGle = None

        self._strCONF_SYMOP_HOME = "symopHome"
        # Default value for the location of the symop table
        self._strSymopHome = None

        self._xsDataSampleCopy = None

        # For default chemical composition
        self._fAverageAminoAcidVolume = 135.49
        self._fAverageCrystalSolventContent = 0.47
        self._fAverageSulfurContentPerAminoacid = 0.05
        self._fAverageSulfurConcentration = 314

        # This varaible determines if Raddose should be executed or not
        self._bEstimateRadiationDamage = None

        # Raddose log file
        self.xsDataFileRaddoseLog = None

        self.roundUpToEven100 = False

    def setSymopHome(self, _strSymopHome):
        self._strSymopHome = _strSymopHome

    def getSymopHome(self):
        return self._strSymopHome

    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        self.DEBUG("EDPluginControlStrategyv1_2.preProcess...")
        self._edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput().getSample()

        if xsDataSampleCrystalMM is None:
            self._xsDataSampleCopy = XSDataSampleCrystalMM()
        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self._xsDataSampleCopy = XSDataSampleCrystalMM.parseString(strXmlStringDataSample)

        xsDataCrystal = self.getDataInput().getCrystalRefined()
        if xsDataCrystal is not None:
            self._xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Load the Best plugin
        self._edPluginBest = self.loadPlugin(self._strPluginBestName)
        self._edPluginBest.setBaseDirectory(self.getWorkingDirectory())
        self._edPluginBest.setBaseName(self._strPluginBestName)

        # Load the plot gle plugin
        self._edPluginPlotGle = self.loadPlugin(self._strPluginPlotGleName)

        # Check if radiation damage estimation is required or not in the diffraction plan
        xsDataDiffractionPlan = self.getDataInput().getDiffractionPlan()
        if xsDataDiffractionPlan is not None:
            if xsDataDiffractionPlan.getEstimateRadiationDamage():
                if xsDataDiffractionPlan.getEstimateRadiationDamage().getValue():
                    # Yes, is requested
                    self._bEstimateRadiationDamage = True
                else:
                    # No, is explicitly not requested
                    self._bEstimateRadiationDamage = False
            elif xsDataDiffractionPlan.getStrategyOption() is not None:
                if xsDataDiffractionPlan.getStrategyOption().getValue().find("-DamPar") != -1:
                    # The "-DamPar" option requires estimation of radiation damage
                    self._bEstimateRadiationDamage = True

        # Check if we know what to do with radiation damage
        if self._bEstimateRadiationDamage is None:
            # "Force" the estimation of radiation damage if the flux is present
            if self.getDataInput().getExperimentalCondition().getBeam().getFlux() is None:
                strWarningMessage = (
                    "EDPluginControlStrategyv1_2: Missing flux input - cannot estimate radiation damage."
                )
                self.WARNING(strWarningMessage)
                self.addWarningMessage(strWarningMessage)
                self._bEstimateRadiationDamage = False
            else:
                self._bEstimateRadiationDamage = True

        if self._bEstimateRadiationDamage:
            if self.getDataInput().getExperimentalCondition().getBeam().getFlux() is None:
                strErrorMessage = "EDPluginControlStrategyv1_2: Missing flux input. Cannot estimate radiation damage"
                self.ERROR(strErrorMessage)
                self.addErrorMessage(strErrorMessage)
                self.setFailure()

        if not self.isFailure():

            self._edPluginRaddose = self.loadPlugin(self._strPluginRaddoseName)

            if self._edPluginRaddose is not None:
                self.DEBUG(
                    "EDPluginControlStrategyv1_2.preProcess: "
                    + self._strPluginRaddoseName
                    + " Found... setting Data Input"
                )

                strFileSymop = os.path.join(self.getSymopHome(), "symop.lib")

                xsDataStringSpaceGroup = self.getDataInput().getDiffractionPlan().getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                bSpaceGroupForced = False
                if xsDataStringSpaceGroup is not None:
                    strSpaceGroup = xsDataStringSpaceGroup.getValue().upper().replace(" ", "")
                    if strSpaceGroup != "":
                        self.DEBUG("EDPluginControlStrategyv1_2.preProcess: Forced Space Group Found: " + strSpaceGroup)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                strSpaceGroup, strFileSymop
                            )
                            bSpaceGroupForced = True
                        except Exception as detail:
                            strErrorMessage = "EDPluginControlStrategyv1_2: Problem to calculate Number of symmetry operators: {0}".format(
                                detail
                            )
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError(strErrorMessage)
                if not bSpaceGroupForced:
                    # Space Group has NOT been forced
                    xsDataStringSpaceGroup = self._xsDataSampleCopy.getCrystal().getSpaceGroup().getName()
                    if xsDataStringSpaceGroup is not None:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroupName = self._xsDataSampleCopy.getCrystal().getSpaceGroup().getName().getValue()
                        self.DEBUG(
                            "EDPluginControlStrategyv1_2.preProcess: Space Group IT Name found by indexing: "
                            + strSpaceGroupName
                        )
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                strSpaceGroupName, strFileSymop
                            )
                        except Exception as detail:
                            strErrorMessage = "EDPluginControlStrategyv1_2: Problem to calculate Number of symmetry operators: {0}".format(
                                detail
                            )
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError(strErrorMessage)
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        iSpaceGroupITNumber = (
                            self._xsDataSampleCopy.getCrystal().getSpaceGroup().getITNumber().getValue()
                        )
                        self.DEBUG(
                            "EDPluginControlStrategyv1_2.preProcess: Space Group IT Number Found by indexing: %d"
                            % iSpaceGroupITNumber
                        )
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(
                                str(iSpaceGroupITNumber), strFileSymop
                            )
                        except Exception as detail:
                            strErrorMessage = "EDPluginControlStrategyv1_2: Problem to calculate Number of symmetry operators: {0}".format(
                                detail
                            )
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError(strErrorMessage)

                if strNumOperators is not None:
                    iNumOperators = int(strNumOperators)
                else:
                    strErrorMessage = "EDPluginControlStrategyv1_2: No symmetry operators found for Space Group: {0}".format(
                        strNumOperators
                    )
                    self.error(strErrorMessage)
                    self.addErrorMessage(strErrorMessage)
                    raise RuntimeError(strErrorMessage)

                xsDataChemicalComposition = self._xsDataSampleCopy.getChemicalComposition()

                if xsDataChemicalComposition is None:
                    # create a default chemical composition and assign it to the sample
                    xsDataDefaultChemicalComposition = self.getDefaultChemicalComposition(
                        self._xsDataSampleCopy, iNumOperators
                    )
                    self._xsDataSampleCopy.setChemicalComposition(xsDataDefaultChemicalComposition)
                else:
                    # Check for Sulfur atoms, if none, add native sulfur atoms
                    xsDataUpdatedChemicalComposition = self.updateChemicalComposition(xsDataChemicalComposition)
                    self._xsDataSampleCopy.setChemicalComposition(xsDataUpdatedChemicalComposition)

                # create Data Input for Raddose
                from EDHandlerXSDataRaddosev10 import EDHandlerXSDataRaddosev10

                self._edHandlerXSDataRaddose = EDHandlerXSDataRaddosev10()
                xsDataBeam = self.getDataInput().getExperimentalCondition().getBeam()

                # Calculate number of images (MXSUP-1616):
                iNumberOfImages = None
                xsDataCollection = self.dataInput.dataCollection
                if xsDataCollection is not None:
                    iNumberOfImages = 0
                    for xsDataSubWedge in xsDataCollection.subWedge:
                        xsDataGoniostat = xsDataSubWedge.experimentalCondition.goniostat
                        iOscStart = xsDataGoniostat.rotationAxisStart.value
                        iOscEnd = xsDataGoniostat.rotationAxisEnd.value
                        iOscWidth = xsDataGoniostat.oscillationWidth.value
                        iNumberOfImages += int(round((iOscEnd - iOscStart) / iOscWidth, 0))
                if iNumberOfImages is None:
                    iNumberOfImages = 1
                    self.WARNING("No goniostat information, number of images for RADDOSE set to 1")

                xsDataRaddoseInput = self._edHandlerXSDataRaddose.getXSDataRaddoseInput(
                    xsDataBeam, self._xsDataSampleCopy, iNumOperators, iNumberOfImages
                )
                if xsDataRaddoseInput is not None:
                    self._edPluginRaddose.setDataInput(xsDataRaddoseInput)
                    self._edPluginRaddose.setBaseDirectory(self.getWorkingDirectory())
                    self._edPluginRaddose.setBaseName(self._strPluginRaddoseName)

    def configure(self):
        EDPluginControl.configure(self)
        self.DEBUG("EDPluginControlStrategyv1_2.configure")
        strSymopHome = self.config.get(self._strCONF_SYMOP_HOME)
        if strSymopHome is None:
            strWarningMessage = "EDPluginControlStrategyv1_2: No configuration parameter found for {0}".format(
                self._strCONF_SYMOP_HOME
            )
            self.warning(strWarningMessage)
            self.addWarningMessage(strWarningMessage)
        else:
            self.setSymopHome(strSymopHome)
        # Even 100 images?
        self.roundUpToEven100 = self.config.get("roundUpToEven100", False)

    def process(self, _edObject=None):
        EDPluginControl.process(self, _edObject)
        self.DEBUG("EDPluginControlStrategyv1_2.process...")
        self._edPluginBest.connectSUCCESS(self.doSuccessActionBest)
        self._edPluginBest.connectFAILURE(self.doFailureActionBest)
        if self._bEstimateRadiationDamage:
            self._edPluginRaddose.connectSUCCESS(self.doRaddoseToBestTransition)
            self._edPluginRaddose.connectFAILURE(self.doFailureActionRaddose)
            self._edPluginRaddose.executeSynchronous()
        else:
            self.executeBest()

    def postProcess(self, _edObject=None):
        EDPluginControl.postProcess(self, _edObject)
        self.DEBUG("EDPluginControlStrategyv1_2.postProcess...")

        #
        # Create the BEST graphs from the plot mtv file
        #
        # Check if we have GLE files from BEST:
        xsDataResultBest = self._edPluginBest.getDataOutput()
        xsDataInputPlotGle = XSDataInputPlotGle()
        if xsDataResultBest.glePlot != []:
            for xsDataBestGlePlot in xsDataResultBest.glePlot:
                xsDataGlePlot = XSDataGlePlot()
                xsDataGlePlot.script = xsDataBestGlePlot.script
                xsDataGlePlot.data = xsDataBestGlePlot.data
                xsDataInputPlotGle.addGlePlot(xsDataGlePlot)
        else:
            xsDataInputPlotGle.filePlotMtv = xsDataResultBest.pathToPlotMtvFile
        self._edPluginPlotGle.dataInput = xsDataInputPlotGle
        self._edPluginPlotGle.executeSynchronous()

    def finallyProcess(self, _edObject=None):
        EDPluginControl.finallyProcess(self, _edObject)
        self.DEBUG("EDPluginControlStrategyv1_2.finallyProcess")
        xsDataResultStrategy = None
        xsDataResultBest = self._edPluginBest.getDataOutput()
        if xsDataResultBest is not None and self.getDataInput().getDiffractionPlan().getStrategyOption() is not None:
            if self.getDataInput().getDiffractionPlan().getStrategyOption().getValue() != "-Bonly":
                xsDataResultStrategy = self._edHandlerXSDataBest.getXSDataResultStrategy(
                    xsDataResultBest,
                    self.getDataInput().getExperimentalCondition(),
                    self._xsDataSampleCopy,
                    roundUpToEven100=self.roundUpToEven100,
                )
        else:
            xsDataResultStrategy = self._edHandlerXSDataBest.getXSDataResultStrategy(
                xsDataResultBest,
                self.getDataInput().getExperimentalCondition(),
                self._xsDataSampleCopy,
                roundUpToEven100=self.roundUpToEven100,
            )

        if self.xsDataFileRaddoseLog is not None:
            xsDataResultStrategy.setRaddoseLogFile(self.xsDataFileRaddoseLog)
        # Plots
        if not self._edPluginPlotGle.isFailure() and self._edPluginPlotGle.dataOutput is not None:
            listFileGraph = self._edPluginPlotGle.dataOutput.fileGraph
            xsDataResultStrategy.bestGraphFile = listFileGraph
        # Sample
        xsDataResultStrategy.setSample(self._xsDataSampleCopy)
        # timeToReachHendersonLimit
        if self._edPluginRaddose is not None:
            xsDataRaddoseOutput = self._edPluginRaddose.dataOutput
            if xsDataRaddoseOutput is not None:
                xsDataResultStrategy.timeToReachHendersonLimit = xsDataRaddoseOutput.timeToReachHendersonLimit
        self.setDataOutput(xsDataResultStrategy)
        self.generateStrategyShortSummary(xsDataResultStrategy)

    def doRaddoseToBestTransition(self, _edPlugin):
        self.DEBUG("EDPluginControlStrategyv1_2.doRaddoseToBestTransition")
        self.retrieveSuccessMessages(_edPlugin, "EDPluginControlStrategyv1_2.doRaddoseToBestTransition")

        xsDataRaddoseOutput = self._edPluginRaddose.getDataOutput()

        # update the strategy data with the data coming from Raddose
        self._xsDataSampleCopy.setAbsorbedDoseRate(xsDataRaddoseOutput.getAbsorbedDoseRate())
        if xsDataRaddoseOutput.getPathToLogFile() != None:
            self.xsDataFileRaddoseLog = xsDataRaddoseOutput.getPathToLogFile()

        # Call the Best Translator layer
        from EDHandlerXSDataBestv1_2 import EDHandlerXSDataBestv1_2

        self._edHandlerXSDataBest = EDHandlerXSDataBestv1_2()

        xsDataInputStrategyCopy = XSDataInputStrategy.parseString(self.getDataInput().marshal())
        xsDataInputStrategyCopy.setSample(self._xsDataSampleCopy)

        xsDataInputBest = self._edHandlerXSDataBest.getXSDataInputBest(xsDataInputStrategyCopy)

        self._edPluginBest.setDataInput(xsDataInputBest)
        self._edPluginBest.executeSynchronous()

    def doFailureActionRaddose(self, _edPlugin=None):
        """
        retrieve the potential warning messages
        retrieve the potential error messages
        """
        self.DEBUG("EDPluginControlStrategyv1_2.doFailureActionRaddose")
        self.retrieveFailureMessages(_edPlugin, "EDPluginControlStrategyv1_2.doFailureActionRaddose")
        strWarningMessage = "EDPluginControlStrategyv1_2: Raddose failure"
        self.warning(strWarningMessage)
        self.addWarningMessage(strWarningMessage)
        self.executeBest(self)

    def executeBest(self, _edPlugin=None):
        # Call the Best Translator layer

        from EDHandlerXSDataBestv1_2 import EDHandlerXSDataBestv1_2

        self._edHandlerXSDataBest = EDHandlerXSDataBestv1_2()
        xsDataInputStrategyCopy = XSDataInputStrategy.parseString(self.getDataInput().marshal())
        xsDataInputStrategyCopy.setSample(self._xsDataSampleCopy)
        xsDataInputBest = self._edHandlerXSDataBest.getXSDataInputBest(xsDataInputStrategyCopy)
        self._edPluginBest.setDataInput(xsDataInputBest)
        self._edPluginBest.executeSynchronous()

    def doSuccessActionBest(self, _edPlugin=None):
        """
        retrieve the potential warning messages
        """
        self.DEBUG("EDPluginControlStrategyv1_2.doSuccessActionBest")
        self.retrieveSuccessMessages(_edPlugin, "EDPluginControlStrategyv1_2.doSuccessActionBest")

    def doFailureActionBest(self, _edPlugin):
        """
        retrieve the potential warning messages
        retrieve the potential error messages
        """
        self.DEBUG("EDPluginControlStrategyv1_2.doFailureActionBest")
        self.retrieveFailureMessages(_edPlugin, "BEST failure:")
        self.generateExecutiveSummary(self)
        self.setFailure()

    def getDefaultChemicalComposition(self, _xsDataSample, _inumOperators):
        xsDataCell = _xsDataSample.getCrystal().getCell()
        a = xsDataCell.getLength_a().getValue()
        b = xsDataCell.getLength_b().getValue()
        c = xsDataCell.getLength_c().getValue()
        alpha = math.radians(xsDataCell.getAngle_alpha().getValue())
        beta = math.radians(xsDataCell.getAngle_beta().getValue())
        gamma = math.radians(xsDataCell.getAngle_gamma().getValue())

        fUnitCellVolume = (
            a
            * b
            * c
            * (
                math.sqrt(
                    1
                    - math.cos(alpha) * math.cos(alpha)
                    - math.cos(beta) * math.cos(beta)
                    - math.cos(gamma) * math.cos(gamma)
                    + 2 * math.cos(alpha) * math.cos(beta) * math.cos(gamma)
                )
            )
        )
        fPolymerVolume = fUnitCellVolume * (1 - self._fAverageCrystalSolventContent)
        fNumberOfMonomersPerUnitCell = fPolymerVolume / self._fAverageAminoAcidVolume
        fNumberOfMonomersPerAsymmetricUnit = fNumberOfMonomersPerUnitCell / _inumOperators
        iNumberOfSulfurAtom = int(round(fNumberOfMonomersPerAsymmetricUnit * self._fAverageSulfurContentPerAminoacid))

        xsDataAtom = XSDataAtom()
        xsDataAtom.setSymbol(XSDataString("S"))
        xsDataAtom.setNumberOf(XSDataDouble(iNumberOfSulfurAtom))
        xsDataAtomicComposition = XSDataAtomicComposition()
        xsDataAtomicComposition.addAtom(xsDataAtom)

        xsDataChain = XSDataChain()
        xsDataChain.setType(XSDataString("protein"))
        xsDataChain.setNumberOfMonomers(XSDataDouble(round(fNumberOfMonomersPerAsymmetricUnit)))
        xsDataChain.setNumberOfCopies(XSDataDouble(1))
        xsDataChain.setHeavyAtoms(xsDataAtomicComposition)

        xsDataStructure = XSDataStructure()
        xsDataStructure.addChain(xsDataChain)
        xsDataStructure.setNumberOfCopiesInAsymmetricUnit(XSDataDouble(1))

        xsDataAtomSolvent = XSDataAtom()
        xsDataAtomSolvent.setSymbol(XSDataString("S"))
        xsDataAtomSolvent.setConcentration(XSDataDouble(self._fAverageSulfurConcentration))
        xsDataAtomicCompositionSolvent = XSDataAtomicComposition()
        xsDataAtomicCompositionSolvent.addAtom(xsDataAtomSolvent)
        xsDataSolvent = XSDataSolvent()
        xsDataSolvent.setAtoms(xsDataAtomicCompositionSolvent)

        xsDataChemicalCompositionMM = XSDataChemicalCompositionMM()
        xsDataChemicalCompositionMM.setSolvent(xsDataSolvent)
        xsDataChemicalCompositionMM.setStructure(xsDataStructure)

        return xsDataChemicalCompositionMM

    def updateChemicalComposition(self, _xsDataChemicalComposition):
        xsDataChemicalComposition = _xsDataChemicalComposition

        for chain in xsDataChemicalComposition.getStructure().getChain():
            if chain.getType().getValue() == "protein":
                bSulfurExists = False
                xsDataAtomicCompositionHeavyAtoms = chain.getHeavyAtoms()
                if xsDataAtomicCompositionHeavyAtoms is None:
                    xsDataAtomicCompositionHeavyAtoms = XSDataAtomicComposition()
                else:
                    for heavyAtom in xsDataAtomicCompositionHeavyAtoms.getAtom():
                        if heavyAtom.getSymbol().getValue() == "S" or heavyAtom.getSymbol().getValue() == "s":
                            bSulfurExists = True

                # all protein chains should contain sulfur atom as a percentage of the number
                # of amino acids. Add them if the user did not input them.
                if bSulfurExists == False:
                    iNumberOfSulfurAtom = int(round(chain.getNumberOfMonomers().getValue() * 0.05))
                    xsDataSulfurAtom = XSDataAtom()
                    xsDataSulfurAtom.setSymbol(XSDataString("S"))
                    xsDataSulfurAtom.setNumberOf(XSDataDouble(iNumberOfSulfurAtom))
                    xsDataAtomicCompositionHeavyAtoms.addAtom(xsDataSulfurAtom)
                    chain.setHeavyAtoms(xsDataAtomicCompositionHeavyAtoms)

        return xsDataChemicalComposition

    def generateExecutiveSummary(self, _edPlugin):
        """
        Generates a summary of the execution of the plugin.
        """
        self.DEBUG("EDPluginControlStrategyv1_2.generateExecutiveSummary")
        self.addExecutiveSummaryLine("Summary of Strategy:")
        self.addErrorWarningMessagesToExecutiveSummary()

        xsDataResultStrategy = self.getDataOutput()

        if self._edPluginRaddose is not None:
            if self._edPluginRaddose.getDataOutput() is not None:

                self.addExecutiveSummaryLine("")
                self.appendExecutiveSummary(self._edPluginRaddose, "Raddose : ")

            if xsDataResultStrategy is not None:
                self.addExecutiveSummaryLine("")
                self.addExecutiveSummaryLine("Calculations assuming polymer crystal with:")
                self.addExecutiveSummaryLine("------------------------------------------")
                self.addExecutiveSummaryLine("")

                xsDataStructure = (
                    xsDataResultStrategy.getCollectionPlan()[0]
                    .getCollectionStrategy()
                    .getSample()
                    .getChemicalComposition()
                    .getStructure()
                )

                self.addExecutiveSummaryLine(
                    "Number of structure copies in asymmetric unit: %.2f"
                    % xsDataStructure.getNumberOfCopiesInAsymmetricUnit().getValue()
                )
                self.addExecutiveSummaryLine("")

                chains = xsDataStructure.getChain()
                self.addExecutiveSummaryLine("Chains:")
                for chain in chains:
                    strChainType = chain.getType().getValue()
                    self.addExecutiveSummaryLine("    Type                           : %s" % strChainType)
                    if strChainType == "protein":
                        self.addExecutiveSummaryLine(
                            "    Number of residues             : %.2f" % chain.getNumberOfMonomers().getValue()
                        )
                    elif strChainType == "dna" or strChainType == "rna":
                        self.addExecutiveSummaryLine(
                            "    Number of nucleotides          : %.2f" % chain.getNumberOfMonomers().getValue()
                        )
                    strHeavyAtomsChain = "    Number of heavy atoms          :"
                    if chain.getHeavyAtoms() is not None:
                        heavyAtomsChain = chain.getHeavyAtoms().getAtom()
                        for heavyAtomChain in heavyAtomsChain:
                            strHeavyAtomsChain = strHeavyAtomsChain + " %s=%d" % (
                                heavyAtomChain.getSymbol().getValue(),
                                heavyAtomChain.getNumberOf().getValue(),
                            )
                    else:
                        strHeavyAtomsChain = strHeavyAtomsChain + " No heavy atoms"
                    self.addExecutiveSummaryLine(strHeavyAtomsChain)

                    self.addExecutiveSummaryLine(
                        "    Number of copies in structure  : %.2f" % chain.getNumberOfCopies().getValue()
                    )
                    self.addExecutiveSummaryLine("")

                ligands = xsDataStructure.getLigand()
                if len(ligands) != 0:
                    self.addExecutiveSummaryLine("Ligands:")

                for ligand in ligands:
                    self.addExecutiveSummaryLine(
                        "    Number of light atoms          : %.2f" % ligand.getNumberOfLightAtoms().getValue()
                    )
                    strHeavyAtomsLigand = "    Number of heavy atoms          :"
                    if ligand.getHeavyAtoms() is not None:
                        heavyAtomsLigand = ligand.getHeavyAtoms().getAtom()
                        for heavyAtomLigand in heavyAtomsLigand:
                            strHeavyAtomsLigand = strHeavyAtomsLigand + " %s=%d" % (
                                heavyAtomLigand.getSymbol().getValue(),
                                heavyAtomLigand.getNumberOf().getValue(),
                            )
                    else:
                        strHeavyAtomsChain = strHeavyAtomsChain + " No heavy atoms"
                    self.addExecutiveSummaryLine(strHeavyAtomsLigand)
                    self.addExecutiveSummaryLine(
                        "    Number of copies in structure  : %.2f" % chain.getNumberOfCopies().getValue()
                    )
                    self.addExecutiveSummaryLine("")

        if self._edPluginBest is not None:
            if self._edPluginBest.getDataOutput() is not None:
                self.appendExecutiveSummary(self._edPluginBest, "Best : ")
                self.addExecutiveSummaryLine("")

    def generateStrategyShortSummary(self, _xsDataResultStrategy):
        """
        Generates a short summary of the BEST strategy
        """
        self.DEBUG("EDPluginControlIntegrationv10.generateIntegrationShortSummary")
        strStrategyShortSummary = ""
        iTotalNoImages = 0
        fTotalExposureTime = 0.0
        xsDataDiffractionPlan = None
        if self.getDataInput():
            if self.getDataInput().getDiffractionPlan():
                xsDataDiffractionPlan = self.getDataInput().getDiffractionPlan()
        if self._bEstimateRadiationDamage:
            strStrategyShortSummary += "Strategy: Radiation damage estimated"
            if self._edPluginRaddose.getDataOutput().getTimeToReachHendersonLimit():
                strStrategyShortSummary += (
                    ", time to reach Henderson limit: %.1f s\n"
                    % self._edPluginRaddose.getDataOutput().getTimeToReachHendersonLimit().getValue()
                )
            else:
                strStrategyShortSummary += "\n"

        else:
            strStrategyShortSummary += "Strategy: No radiation damage estimation"
            if xsDataDiffractionPlan:
                if xsDataDiffractionPlan.getMaxExposureTimePerDataCollection():
                    strStrategyShortSummary += (
                        ", max exposure time per data collection: %.1f s\n"
                        % xsDataDiffractionPlan.getMaxExposureTimePerDataCollection().getValue()
                    )
                else:
                    strStrategyShortSummary += "\n"
            else:
                strStrategyShortSummary += "\n"
        if xsDataDiffractionPlan:
            strStrategyShortSummary += "Strategy: Options: "
            listStrategyOptions = []
            if xsDataDiffractionPlan.getAnomalousData():
                if xsDataDiffractionPlan.getAnomalousData().getValue():
                    listStrategyOptions.append("anomalous data")
            if xsDataDiffractionPlan.getAimedCompleteness():
                listStrategyOptions.append(
                    "aimed completeness = %.1f" % xsDataDiffractionPlan.getAimedCompleteness().getValue()
                )
            if xsDataDiffractionPlan.getAimedMultiplicity():
                listStrategyOptions.append(
                    "aimed multiplicity = %d" % xsDataDiffractionPlan.getAimedMultiplicity().getValue()
                )
            if xsDataDiffractionPlan.getAimedResolution():
                listStrategyOptions.append(
                    "aimed resolution = %.2f A" % xsDataDiffractionPlan.getAimedResolution().getValue()
                )
            if xsDataDiffractionPlan.getComplexity():
                listStrategyOptions.append("complexity = %s" % xsDataDiffractionPlan.getComplexity().getValue())
            if xsDataDiffractionPlan.getStrategyOption():
                listStrategyOptions.append(
                    "extra strategy option(s) = %s" % xsDataDiffractionPlan.getStrategyOption().getValue()
                )
            if listStrategyOptions != []:
                for strStrategyOption in listStrategyOptions[:-1]:
                    strStrategyShortSummary += strStrategyOption + ", "
                strStrategyShortSummary += listStrategyOptions[-1]
            strStrategyShortSummary += "\n"
        fResolutionMax = None
        fRankingResolution = None
        for xsDataCollectionPlan in _xsDataResultStrategy.getCollectionPlan():
            iNoCollectionPlan = xsDataCollectionPlan.getCollectionPlanNumber().getValue()
            strStrategyShortSummary += "Strategy: Collection plan %d" % iNoCollectionPlan
            xsDataStrategySummary = xsDataCollectionPlan.getStrategySummary()
            if xsDataStrategySummary.getResolutionReasoning() != None:
                strResolutionResoning = xsDataStrategySummary.getResolutionReasoning().getValue()
                strStrategyShortSummary += ": %s\n" % strResolutionResoning
            else:
                strStrategyShortSummary += "\n"
            xsDataCollectionStrategy = xsDataCollectionPlan.getCollectionStrategy()
            if xsDataStrategySummary.getRankingResolution() is not None:
                fRankingResolution = xsDataStrategySummary.getRankingResolution().getValue()
                strStrategyShortSummary += "Strategy: Ranking resolution: %.2f [A]\n" % fRankingResolution
            for xsDataSubWedge in xsDataCollectionStrategy.getSubWedge():
                iWedgeNo = xsDataCollectionPlan.getCollectionPlanNumber().getValue()
                strStrategyShortSummary += "Strategy: wedge %d: " % iWedgeNo
                xsDataStrategySummary = xsDataCollectionPlan.getStrategySummary()
                fResolution = xsDataStrategySummary.getResolution().getValue()
                if (fResolutionMax is None) or (fResolution < fResolutionMax):
                    fResolutionMax = fResolution
                strStrategyShortSummary += "resolution %.2f [A], " % fResolution
                xsDataStringAction = xsDataSubWedge.getAction()
                if xsDataStringAction is not None:
                    strStrategyShortSummary += "%s, " % xsDataStringAction.getValue()
                iSubWedgeNo = xsDataSubWedge.getSubWedgeNumber().getValue()
                strStrategyShortSummary += "sub wedge %d: " % iSubWedgeNo
                xsDataExperimentalCondition = xsDataSubWedge.getExperimentalCondition()
                xsDataGoniostat = xsDataExperimentalCondition.getGoniostat()
                fRotationStart = xsDataGoniostat.getRotationAxisStart().getValue()
                strStrategyShortSummary += "start %.2f, " % fRotationStart
                fRange = xsDataGoniostat.getOscillationWidth().getValue()
                fRotationEnd = xsDataGoniostat.getRotationAxisEnd().getValue()
                iNoImages = int((fRotationEnd - fRotationStart) / fRange + 0.1)
                strStrategyShortSummary += "images %d, " % iNoImages
                strStrategyShortSummary += "width %.2f, " % fRange
                xsDataBeam = xsDataExperimentalCondition.getBeam()
                fExpTime = xsDataBeam.getExposureTime().getValue()
                strStrategyShortSummary += "time %.2f [s], " % fExpTime
                fTransmission = xsDataBeam.getTransmission().getValue()
                strStrategyShortSummary += "transmission %.2f\n" % fTransmission
                iTotalNoImages += iNoImages
                fTotalExposureTime += fExpTime * iNoImages
            strStrategyShortSummary += "Strategy: total no images %d, total exposure time %.1f [s]\n" % (
                iTotalNoImages,
                fTotalExposureTime,
            )
        if fRankingResolution is not None:
            if (fRankingResolution < fResolutionMax) and (abs(fRankingResolution - fResolutionMax) > 0.1):
                strStrategyShortSummary += "\n"
                strStrategyShortSummary += "NOTE! " * 20 + "\n"
                strStrategyShortSummary += "\n"
                strStrategyShortSummary += (
                    "BEST has calculated that it should be possible to collect data to %.2f A from this sample.\n"
                    % fRankingResolution
                )
                strStrategyShortSummary += (
                    "If you want to calculate a new strategy for data collection to this resolution you\n"
                )
                strStrategyShortSummary += "must first recollect reference images at this resolution.\n"
                strStrategyShortSummary += "\n"
                strStrategyShortSummary += "NOTE! " * 20 + "\n"
                strStrategyShortSummary += "\n"

        self.setDataOutput(XSDataString(strStrategyShortSummary), "strategyShortSummary")
class EDPluginControlKappaStrategyv2_0(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """

    def __init__ (self):
        EDPluginControl.__init__(self)
        #self.setXSDataInputClass(EDList)

        self.setRequiredToHaveConfiguration(True)

        self.strPluginRaddoseName = "EDPluginRaddosev10"
        self.edPluginRaddose = None
        self.edHandlerXSDataRaddose = None

        self.strPluginBestName = "EDPluginBestv1_2"
        self.edPluginBest = None
        from EDHandlerXSDataBestv1_2    import EDHandlerXSDataBestv1_2
        self.edHandlerXSDataBest = EDHandlerXSDataBestv1_2()

        self.strPluginAlignmentName = "EDPluginSTACAlignmentv2_0"
        self.edPluginAlignment = None
        self.edHandlerXSDataAlignment = None

        self.strPluginKappaStrategyName = "EDPluginSTACStrategyv2_0"
        self.edPluginKappaStrategy = None
        self.edHandlerXSDataKappaStrategy = None

        self.setXSDataInputClass(XSDataInputStrategy, "mxv1InputStrategy")
        EDFactoryPluginStatic.loadModule("XSDataMXv2")
        import XSDataMXv2
        self.setXSDataInputClass(XSDataMXv2.XSDataCollection, "mxv2DataCollection")
        import XSDataMXv1
        self.setXSDataInputClass(XSDataMXv1.XSDataIndexingResult, "mxv1IndexingResult")

        #disable kappa by default
        self.KappaStrategy = 0

        self.strCONF_SYMOP_HOME = "symopHome"
        # Default value for the location of the symop table
        self.strSymopHome = os.path.normpath("/opt/pxsoft/ccp4-6.0.2/lib/data")

        self.xsDataSampleCopy = None

        # For default chemical composition
        self.fAverageAminoAcidVolume = 135.49
        self.fAverageCrystalSolventContent = 0.47
        self.fAverageSulfurContentPerAminoacid = 0.05
        self.fAverageSulfurConcentration = 314


    def setSymopHome(self, _strSymopHome):
        self.strSymopHome = _strSymopHome


    def getSymopHome(self):
        return self.strSymopHome


    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        EDVerbose.DEBUG("EDPluginControlKappaStrategyv2_0.preProcess...")
        self.edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput("mxv1InputStrategy")[0].getSample()

        if(xsDataSampleCrystalMM is None):
            self.xsDataSampleCopy = XSDataSampleCrystalMM()

        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self.xsDataSampleCopy = XSDataSampleCrystalMM.parseString(strXmlStringDataSample)

        xsDataCrystal = self.getDataInput("mxv1InputStrategy")[0].getCrystalRefined()
        if(xsDataCrystal is not None):
            self.xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Raddose is enabled only if the beam flux is set
        if(self.getDataInput("mxv1InputStrategy")[0].getExperimentalCondition().getBeam().getFlux() is None):
            strWarningMessage = EDMessage.WARNING_CANNOT_USE_PLUGIN_03 % ('EDPluginControlKappaStrategyv2_0.preProcess', self.strPluginRaddoseName, "Beam Flux not set")
            EDVerbose.warning(strWarningMessage)
            self.addWarningMessage(strWarningMessage)

        else:
            self.edPluginRaddose = self.loadPlugin(self.strPluginRaddoseName)

            if (self.edPluginRaddose is not None):
                EDVerbose.DEBUG("EDPluginControlKappaStrategyv2_0.preProcess: " + self.strPluginRaddoseName + " Found... setting Data Input")

                strFileSymop = os.path.join(self.getSymopHome(), "symop.lib")

                xsDataStringSpaceGroup = self.getDataInput("mxv1InputStrategy")[0].getDiffractionPlan().getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                strNumOperators = None
                strSpaceGroup = None
                if(xsDataStringSpaceGroup is not None):
                    strSpaceGroup = xsDataStringSpaceGroup.getValue()
                    EDVerbose.DEBUG("EDPluginControlKappaStrategyv2_0.preProcess: Forced Space Group Found: " + strSpaceGroup)
                    try:
                        strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(strSpaceGroup, strFileSymop)
                    except Exception, detail:
                        strErrorMessage = EDMessage.ERROR_EXECUTION_03 % ('EDPluginControlKappaStrategyv2_0.preProcess', "Problem to calculate Number of symmetry operators", detail)
                        EDVerbose.error(strErrorMessage)
                        self.addErrorMessage(strErrorMessage)
                        raise RuntimeError, strErrorMessage
                # Space Group has NOT been forced
                else:
                    xsDataStringSpaceGroup = self.xsDataSampleCopy.getCrystal().getSpaceGroup().getName()
                    if (xsDataStringSpaceGroup is not None):
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroup = self.xsDataSampleCopy.getCrystal().getSpaceGroup().getName().getValue()
                        EDVerbose.DEBUG("EDPluginControlKappaStrategyv2_0.preProcess: Space Group IT Name found by indexing: " + strSpaceGroup)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(strSpaceGroup, strFileSymop)
                        except Exception, detail:
                            strErrorMessage = EDMessage.ERROR_EXECUTION_03 % ('EDPluginControlKappaStrategyv2_0.preProcess', "Problem to calculate Number of symmetry operators", detail)
                            EDVerbose.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        dSpaceGroupITNumber = self.xsDataSampleCopy.getCrystal().getSpaceGroup().getITNumber().getValue()
                        EDVerbose.DEBUG("EDPluginControlKappaStrategyv2_0.preProcess: Space Group IT Number Found by indexing: %d" % dSpaceGroupITNumber)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(str(dSpaceGroupITNumber), strFileSymop)
                        except Exception, detail:
                            strErrorMessage = EDMessage.ERROR_EXECUTION_03 % ('EDPluginControlKappaStrategyv2_0.preProcess', "Problem to calculate Number of symmetry operators", detail)
                            EDVerbose.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
Esempio n. 7
0
class EDPluginControlStrategyv1_2(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """
    def __init__(self):
        """
        """
        EDPluginControl.__init__(self)
        self.setXSDataInputClass(XSDataInputStrategy)

        self._strPluginRaddoseName = "EDPluginRaddosev10"
        self._edPluginRaddose = None
        self._edHandlerXSDataRaddose = None

        self._strPluginBestName = "EDPluginBestv1_2"
        self._edPluginBest = None
        self._edHandlerXSDataBest = None

        self._strPluginPlotGleName = "EDPluginExecPlotGlev1_1"
        self._edPluginPlotGle = None

        self._xsDataSampleCopy = None

        # For default chemical composition
        self._fAverageAminoAcidVolume = 135.49
        self._fAverageCrystalSolventContent = 0.47
        self._fAverageSulfurContentPerAminoacid = 0.05
        self._fAverageSulfurConcentration = 314

        # This varaible determines if Raddose should be executed or not
        self._bEstimateRadiationDamage = None

        # Raddose log file
        self.xsDataFileRaddoseLog = None

        self.roundUpToEven100 = False

    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        self.DEBUG("EDPluginControlStrategyv1_2.preProcess...")
        self._edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput().getSample()

        if (xsDataSampleCrystalMM is None):
            self._xsDataSampleCopy = XSDataSampleCrystalMM()
        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self._xsDataSampleCopy = XSDataSampleCrystalMM.parseString(
                strXmlStringDataSample)

        xsDataCrystal = self.getDataInput().getCrystalRefined()
        if (xsDataCrystal is not None):
            self._xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Load the Best plugin
        self._edPluginBest = self.loadPlugin(self._strPluginBestName)
        self._edPluginBest.setBaseDirectory(self.getWorkingDirectory())
        self._edPluginBest.setBaseName(self._strPluginBestName)

        # Load the plot gle plugin
        self._edPluginPlotGle = self.loadPlugin(self._strPluginPlotGleName)

        # Check if radiation damage estimation is required or not in the diffraction plan
        xsDataDiffractionPlan = self.getDataInput().getDiffractionPlan()
        if xsDataDiffractionPlan is not None:
            if xsDataDiffractionPlan.getEstimateRadiationDamage():
                if xsDataDiffractionPlan.getEstimateRadiationDamage().getValue(
                ):
                    # Yes, is requested
                    self._bEstimateRadiationDamage = True
                else:
                    # No, is explicitly not requested
                    self._bEstimateRadiationDamage = False
            elif xsDataDiffractionPlan.getStrategyOption() is not None:
                if xsDataDiffractionPlan.getStrategyOption().getValue().find(
                        "-DamPar") != -1:
                    # The "-DamPar" option requires estimation of radiation damage
                    self._bEstimateRadiationDamage = True

        # Check if we know what to do with radiation damage
        if self._bEstimateRadiationDamage is None:
            # "Force" the estimation of radiation damage if the flux is present
            if self.getDataInput().getExperimentalCondition().getBeam(
            ).getFlux() is None:
                strWarningMessage = "EDPluginControlStrategyv1_2: Missing flux input - cannot estimate radiation damage."
                self.WARNING(strWarningMessage)
                self.addWarningMessage(strWarningMessage)
                self._bEstimateRadiationDamage = False
            else:
                self._bEstimateRadiationDamage = True

        if self._bEstimateRadiationDamage:
            if self.getDataInput().getExperimentalCondition().getBeam(
            ).getFlux() is None:
                strErrorMessage = "EDPluginControlStrategyv1_2: Missing flux input. Cannot estimate radiation damage"
                self.ERROR(strErrorMessage)
                self.addErrorMessage(strErrorMessage)
                self.setFailure()

        if not self.isFailure():

            self._edPluginRaddose = self.loadPlugin(self._strPluginRaddoseName)

            if (self._edPluginRaddose is not None):
                self.DEBUG("EDPluginControlStrategyv1_2.preProcess: " +
                           self._strPluginRaddoseName +
                           " Found... setting Data Input")

                xsDataStringSpaceGroup = self.getDataInput(
                ).getDiffractionPlan().getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                bSpaceGroupForced = False
                if (xsDataStringSpaceGroup is not None):
                    strSpaceGroup = xsDataStringSpaceGroup.getValue().upper(
                    ).replace(" ", "")
                    if strSpaceGroup != "":
                        self.DEBUG(
                            "EDPluginControlStrategyv1_2.preProcess: Forced Space Group Found: "
                            + strSpaceGroup)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                strSpaceGroup)
                            bSpaceGroupForced = True
                        except Exception as detail:
                            strErrorMessage = "EDPluginControlStrategyv1_2: Problem to calculate Number of symmetry operators: {0}".format(
                                detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError(strErrorMessage)
                if not bSpaceGroupForced:
                    # Space Group has NOT been forced
                    xsDataStringSpaceGroup = self._xsDataSampleCopy.getCrystal(
                    ).getSpaceGroup().getName()
                    if (xsDataStringSpaceGroup is not None):
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroupName = self._xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getName().getValue()
                        self.DEBUG(
                            "EDPluginControlStrategyv1_2.preProcess: Space Group IT Name found by indexing: "
                            + strSpaceGroupName)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                strSpaceGroupName)
                        except Exception as detail:
                            strErrorMessage = "EDPluginControlStrategyv1_2: Problem to calculate Number of symmetry operators: {0}".format(
                                detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError(strErrorMessage)
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        iSpaceGroupITNumber = self._xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getITNumber().getValue()
                        self.DEBUG(
                            "EDPluginControlStrategyv1_2.preProcess: Space Group IT Number Found by indexing: %d"
                            % iSpaceGroupITNumber)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(
                                str(iSpaceGroupITNumber))
                        except Exception as detail:
                            strErrorMessage = "EDPluginControlStrategyv1_2: Problem to calculate Number of symmetry operators: {0}".format(
                                detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError(strErrorMessage)

                if (strNumOperators is not None):
                    iNumOperators = int(strNumOperators)
                else:
                    strErrorMessage = "EDPluginControlStrategyv1_2: No symmetry operators found for Space Group: {0}".format(
                        strNumOperators)
                    self.error(strErrorMessage)
                    self.addErrorMessage(strErrorMessage)
                    raise RuntimeError(strErrorMessage)

                xsDataChemicalComposition = self._xsDataSampleCopy.getChemicalComposition(
                )

                if (xsDataChemicalComposition is None):
                    # create a default chemical composition and assign it to the sample
                    xsDataDefaultChemicalComposition = self.getDefaultChemicalComposition(
                        self._xsDataSampleCopy, iNumOperators)
                    self._xsDataSampleCopy.setChemicalComposition(
                        xsDataDefaultChemicalComposition)
                else:
                    # Check for Sulfur atoms, if none, add native sulfur atoms
                    xsDataUpdatedChemicalComposition = self.updateChemicalComposition(
                        xsDataChemicalComposition)
                    self._xsDataSampleCopy.setChemicalComposition(
                        xsDataUpdatedChemicalComposition)

                # create Data Input for Raddose
                from EDHandlerXSDataRaddosev10 import EDHandlerXSDataRaddosev10
                self._edHandlerXSDataRaddose = EDHandlerXSDataRaddosev10()
                xsDataBeam = self.getDataInput().getExperimentalCondition(
                ).getBeam()

                # Calculate number of images (MXSUP-1616):
                iNumberOfImages = None
                xsDataCollection = self.dataInput.dataCollection
                if xsDataCollection is not None:
                    iNumberOfImages = 0
                    for xsDataSubWedge in xsDataCollection.subWedge:
                        xsDataGoniostat = xsDataSubWedge.experimentalCondition.goniostat
                        iOscStart = xsDataGoniostat.rotationAxisStart.value
                        iOscEnd = xsDataGoniostat.rotationAxisEnd.value
                        iOscWidth = xsDataGoniostat.oscillationWidth.value
                        iNumberOfImages += int(
                            round((iOscEnd - iOscStart) / iOscWidth, 0))
                if iNumberOfImages is None:
                    iNumberOfImages = 1
                    self.WARNING(
                        "No goniostat information, number of images for RADDOSE set to 1"
                    )

                xsDataRaddoseInput = self._edHandlerXSDataRaddose.getXSDataRaddoseInput(
                    xsDataBeam, self._xsDataSampleCopy, iNumOperators,
                    iNumberOfImages)
                if xsDataRaddoseInput is not None:
                    self._edPluginRaddose.setDataInput(xsDataRaddoseInput)
                    self._edPluginRaddose.setBaseDirectory(
                        self.getWorkingDirectory())
                    self._edPluginRaddose.setBaseName(
                        self._strPluginRaddoseName)

    def configure(self):
        EDPluginControl.configure(self)
        self.DEBUG("EDPluginControlStrategyv1_2.configure")
        # Even 100 images?
        self.roundUpToEven100 = self.config.get("roundUpToEven100", False)

    def process(self, _edObject=None):
        EDPluginControl.process(self, _edObject)
        self.DEBUG("EDPluginControlStrategyv1_2.process...")
        self._edPluginBest.connectSUCCESS(self.doSuccessActionBest)
        self._edPluginBest.connectFAILURE(self.doFailureActionBest)
        if self._bEstimateRadiationDamage:
            self._edPluginRaddose.connectSUCCESS(
                self.doRaddoseToBestTransition)
            self._edPluginRaddose.connectFAILURE(self.doFailureActionRaddose)
            self._edPluginRaddose.executeSynchronous()
        else:
            self.executeBest()

    def postProcess(self, _edObject=None):
        EDPluginControl.postProcess(self, _edObject)
        self.DEBUG("EDPluginControlStrategyv1_2.postProcess...")

        #
        # Create the BEST graphs from the plot mtv file
        #
        # Check if we have GLE files from BEST:
        xsDataResultBest = self._edPluginBest.getDataOutput()
        xsDataInputPlotGle = XSDataInputPlotGle()
        if xsDataResultBest.glePlot != []:
            for xsDataBestGlePlot in xsDataResultBest.glePlot:
                xsDataGlePlot = XSDataGlePlot()
                xsDataGlePlot.script = xsDataBestGlePlot.script
                xsDataGlePlot.data = xsDataBestGlePlot.data
                xsDataInputPlotGle.addGlePlot(xsDataGlePlot)
        else:
            xsDataInputPlotGle.filePlotMtv = xsDataResultBest.pathToPlotMtvFile
        self._edPluginPlotGle.dataInput = xsDataInputPlotGle
        self._edPluginPlotGle.executeSynchronous()

    def finallyProcess(self, _edObject=None):
        EDPluginControl.finallyProcess(self, _edObject)
        self.DEBUG("EDPluginControlStrategyv1_2.finallyProcess")
        xsDataResultStrategy = None
        xsDataResultBest = self._edPluginBest.getDataOutput()
        if (xsDataResultBest is not None and
                self.getDataInput().getDiffractionPlan().getStrategyOption()
                is not None):
            if (self.getDataInput().getDiffractionPlan().getStrategyOption().
                    getValue() != "-Bonly"):
                xsDataResultStrategy = self._edHandlerXSDataBest.getXSDataResultStrategy(
                    xsDataResultBest,
                    self.getDataInput().getExperimentalCondition(),
                    self._xsDataSampleCopy,
                    roundUpToEven100=self.roundUpToEven100)
        else:
            xsDataResultStrategy = self._edHandlerXSDataBest.getXSDataResultStrategy(
                xsDataResultBest,
                self.getDataInput().getExperimentalCondition(),
                self._xsDataSampleCopy,
                roundUpToEven100=self.roundUpToEven100)

        if self.xsDataFileRaddoseLog is not None:
            xsDataResultStrategy.setRaddoseLogFile(self.xsDataFileRaddoseLog)
        # Plots
        if not self._edPluginPlotGle.isFailure(
        ) and self._edPluginPlotGle.dataOutput is not None:
            listFileGraph = self._edPluginPlotGle.dataOutput.fileGraph
            xsDataResultStrategy.bestGraphFile = listFileGraph
        # Sample
        xsDataResultStrategy.setSample(self._xsDataSampleCopy)
        # timeToReachHendersonLimit
        if self._edPluginRaddose is not None:
            xsDataRaddoseOutput = self._edPluginRaddose.dataOutput
            if xsDataRaddoseOutput is not None:
                xsDataResultStrategy.timeToReachHendersonLimit = xsDataRaddoseOutput.timeToReachHendersonLimit
        self.setDataOutput(xsDataResultStrategy)
        self.generateStrategyShortSummary(xsDataResultStrategy)

    def doRaddoseToBestTransition(self, _edPlugin):
        self.DEBUG("EDPluginControlStrategyv1_2.doRaddoseToBestTransition")
        self.retrieveSuccessMessages(
            _edPlugin, "EDPluginControlStrategyv1_2.doRaddoseToBestTransition")

        xsDataRaddoseOutput = self._edPluginRaddose.getDataOutput()

        # update the strategy data with the data coming from Raddose
        self._xsDataSampleCopy.setAbsorbedDoseRate(
            xsDataRaddoseOutput.getAbsorbedDoseRate())
        if xsDataRaddoseOutput.getPathToLogFile() != None:
            self.xsDataFileRaddoseLog = xsDataRaddoseOutput.getPathToLogFile()

        # Call the Best Translator layer
        from EDHandlerXSDataBestv1_2 import EDHandlerXSDataBestv1_2
        self._edHandlerXSDataBest = EDHandlerXSDataBestv1_2()

        xsDataInputStrategyCopy = XSDataInputStrategy.parseString(
            self.getDataInput().marshal())
        xsDataInputStrategyCopy.setSample(self._xsDataSampleCopy)

        xsDataInputBest = self._edHandlerXSDataBest.getXSDataInputBest(
            xsDataInputStrategyCopy)

        self._edPluginBest.setDataInput(xsDataInputBest)
        self._edPluginBest.executeSynchronous()

    def doFailureActionRaddose(self, _edPlugin=None):
        """
        retrieve the potential warning messages
        retrieve the potential error messages
        """
        self.DEBUG("EDPluginControlStrategyv1_2.doFailureActionRaddose")
        self.retrieveFailureMessages(
            _edPlugin, "EDPluginControlStrategyv1_2.doFailureActionRaddose")
        strWarningMessage = "EDPluginControlStrategyv1_2: Raddose failure"
        self.warning(strWarningMessage)
        self.addWarningMessage(strWarningMessage)
        self.executeBest(self)

    def executeBest(self, _edPlugin=None):
        # Call the Best Translator layer

        from EDHandlerXSDataBestv1_2 import EDHandlerXSDataBestv1_2
        self._edHandlerXSDataBest = EDHandlerXSDataBestv1_2()
        xsDataInputStrategyCopy = XSDataInputStrategy.parseString(
            self.getDataInput().marshal())
        xsDataInputStrategyCopy.setSample(self._xsDataSampleCopy)
        xsDataInputBest = self._edHandlerXSDataBest.getXSDataInputBest(
            xsDataInputStrategyCopy)
        self._edPluginBest.setDataInput(xsDataInputBest)
        self._edPluginBest.executeSynchronous()

    def doSuccessActionBest(self, _edPlugin=None):
        """
        retrieve the potential warning messages
        """
        self.DEBUG("EDPluginControlStrategyv1_2.doSuccessActionBest")
        self.retrieveSuccessMessages(
            _edPlugin, "EDPluginControlStrategyv1_2.doSuccessActionBest")

    def doFailureActionBest(self, _edPlugin):
        """
        retrieve the potential warning messages
        retrieve the potential error messages
        """
        self.DEBUG("EDPluginControlStrategyv1_2.doFailureActionBest")
        self.retrieveFailureMessages(_edPlugin, "BEST failure:")
        self.generateExecutiveSummary(self)
        self.setFailure()

    def getDefaultChemicalComposition(self, _xsDataSample, _inumOperators):
        xsDataCell = _xsDataSample.getCrystal().getCell()
        a = xsDataCell.getLength_a().getValue()
        b = xsDataCell.getLength_b().getValue()
        c = xsDataCell.getLength_c().getValue()
        alpha = math.radians(xsDataCell.getAngle_alpha().getValue())
        beta = math.radians(xsDataCell.getAngle_beta().getValue())
        gamma = math.radians(xsDataCell.getAngle_gamma().getValue())

        fUnitCellVolume = a * b * c * (math.sqrt(1 - math.cos(alpha) * math.cos(alpha) - \
                                                 math.cos(beta) * math.cos(beta) - \
                                                 math.cos(gamma) * math.cos(gamma) + \
                                                 2 * math.cos(alpha) * math.cos(beta) * math.cos(gamma)))
        fPolymerVolume = fUnitCellVolume * (
            1 - self._fAverageCrystalSolventContent)
        fNumberOfMonomersPerUnitCell = fPolymerVolume / self._fAverageAminoAcidVolume
        fNumberOfMonomersPerAsymmetricUnit = fNumberOfMonomersPerUnitCell / _inumOperators
        iNumberOfSulfurAtom = int(
            round(fNumberOfMonomersPerAsymmetricUnit *
                  self._fAverageSulfurContentPerAminoacid))

        xsDataAtom = XSDataAtom()
        xsDataAtom.setSymbol(XSDataString("S"))
        xsDataAtom.setNumberOf(XSDataDouble(iNumberOfSulfurAtom))
        xsDataAtomicComposition = XSDataAtomicComposition()
        xsDataAtomicComposition.addAtom(xsDataAtom)

        xsDataChain = XSDataChain()
        xsDataChain.setType(XSDataString("protein"))
        xsDataChain.setNumberOfMonomers(
            XSDataDouble(round(fNumberOfMonomersPerAsymmetricUnit)))
        xsDataChain.setNumberOfCopies(XSDataDouble(1))
        xsDataChain.setHeavyAtoms(xsDataAtomicComposition)

        xsDataStructure = XSDataStructure()
        xsDataStructure.addChain(xsDataChain)
        xsDataStructure.setNumberOfCopiesInAsymmetricUnit(XSDataDouble(1))

        xsDataAtomSolvent = XSDataAtom()
        xsDataAtomSolvent.setSymbol(XSDataString("S"))
        xsDataAtomSolvent.setConcentration(
            XSDataDouble(self._fAverageSulfurConcentration))
        xsDataAtomicCompositionSolvent = XSDataAtomicComposition()
        xsDataAtomicCompositionSolvent.addAtom(xsDataAtomSolvent)
        xsDataSolvent = XSDataSolvent()
        xsDataSolvent.setAtoms(xsDataAtomicCompositionSolvent)

        xsDataChemicalCompositionMM = XSDataChemicalCompositionMM()
        xsDataChemicalCompositionMM.setSolvent(xsDataSolvent)
        xsDataChemicalCompositionMM.setStructure(xsDataStructure)

        return xsDataChemicalCompositionMM

    def updateChemicalComposition(self, _xsDataChemicalComposition):
        xsDataChemicalComposition = _xsDataChemicalComposition

        for chain in xsDataChemicalComposition.getStructure().getChain():
            if (chain.getType().getValue() == "protein"):
                bSulfurExists = False
                xsDataAtomicCompositionHeavyAtoms = chain.getHeavyAtoms()
                if (xsDataAtomicCompositionHeavyAtoms is None):
                    xsDataAtomicCompositionHeavyAtoms = XSDataAtomicComposition(
                    )
                else:
                    for heavyAtom in xsDataAtomicCompositionHeavyAtoms.getAtom(
                    ):
                        if (heavyAtom.getSymbol().getValue() == "S"
                                or heavyAtom.getSymbol().getValue() == "s"):
                            bSulfurExists = True

                # all protein chains should contain sulfur atom as a percentage of the number
                # of amino acids. Add them if the user did not input them.
                if (bSulfurExists == False):
                    iNumberOfSulfurAtom = int(
                        round(chain.getNumberOfMonomers().getValue() * 0.05))
                    xsDataSulfurAtom = XSDataAtom()
                    xsDataSulfurAtom.setSymbol(XSDataString("S"))
                    xsDataSulfurAtom.setNumberOf(
                        XSDataDouble(iNumberOfSulfurAtom))
                    xsDataAtomicCompositionHeavyAtoms.addAtom(xsDataSulfurAtom)
                    chain.setHeavyAtoms(xsDataAtomicCompositionHeavyAtoms)

        return xsDataChemicalComposition

    def generateExecutiveSummary(self, _edPlugin):
        """
        Generates a summary of the execution of the plugin.
        """
        self.DEBUG("EDPluginControlStrategyv1_2.generateExecutiveSummary")
        self.addExecutiveSummaryLine("Summary of Strategy:")
        self.addErrorWarningMessagesToExecutiveSummary()

        xsDataResultStrategy = self.getDataOutput()

        if (self._edPluginRaddose is not None):
            if (self._edPluginRaddose.getDataOutput() is not None):

                self.addExecutiveSummaryLine("")
                self.appendExecutiveSummary(self._edPluginRaddose,
                                            "Raddose : ")

            if (xsDataResultStrategy is not None):
                self.addExecutiveSummaryLine("")
                self.addExecutiveSummaryLine(
                    "Calculations assuming polymer crystal with:")
                self.addExecutiveSummaryLine(
                    "------------------------------------------")
                self.addExecutiveSummaryLine("")

                xsDataStructure = xsDataResultStrategy.getCollectionPlan(
                )[0].getCollectionStrategy().getSample(
                ).getChemicalComposition().getStructure()

                self.addExecutiveSummaryLine(
                    "Number of structure copies in asymmetric unit: %.2f" %
                    xsDataStructure.getNumberOfCopiesInAsymmetricUnit(
                    ).getValue())
                self.addExecutiveSummaryLine("")

                chains = xsDataStructure.getChain()
                self.addExecutiveSummaryLine("Chains:")
                for chain in chains:
                    strChainType = chain.getType().getValue()
                    self.addExecutiveSummaryLine(
                        "    Type                           : %s" %
                        strChainType)
                    if (strChainType == "protein"):
                        self.addExecutiveSummaryLine(
                            "    Number of residues             : %.2f" %
                            chain.getNumberOfMonomers().getValue())
                    elif (strChainType == "dna" or strChainType == "rna"):
                        self.addExecutiveSummaryLine(
                            "    Number of nucleotides          : %.2f" %
                            chain.getNumberOfMonomers().getValue())
                    strHeavyAtomsChain = "    Number of heavy atoms          :"
                    if (chain.getHeavyAtoms() is not None):
                        heavyAtomsChain = chain.getHeavyAtoms().getAtom()
                        for heavyAtomChain in heavyAtomsChain:
                            strHeavyAtomsChain = strHeavyAtomsChain + " %s=%d" % (
                                heavyAtomChain.getSymbol().getValue(),
                                heavyAtomChain.getNumberOf().getValue())
                    else:
                        strHeavyAtomsChain = strHeavyAtomsChain + " No heavy atoms"
                    self.addExecutiveSummaryLine(strHeavyAtomsChain)

                    self.addExecutiveSummaryLine(
                        "    Number of copies in structure  : %.2f" %
                        chain.getNumberOfCopies().getValue())
                    self.addExecutiveSummaryLine("")

                ligands = xsDataStructure.getLigand()
                if (len(ligands) != 0):
                    self.addExecutiveSummaryLine("Ligands:")

                for ligand in ligands:
                    self.addExecutiveSummaryLine(
                        "    Number of light atoms          : %.2f" %
                        ligand.getNumberOfLightAtoms().getValue())
                    strHeavyAtomsLigand = "    Number of heavy atoms          :"
                    if (ligand.getHeavyAtoms() is not None):
                        heavyAtomsLigand = ligand.getHeavyAtoms().getAtom()
                        for heavyAtomLigand in heavyAtomsLigand:
                            strHeavyAtomsLigand = strHeavyAtomsLigand + " %s=%d" % (
                                heavyAtomLigand.getSymbol().getValue(),
                                heavyAtomLigand.getNumberOf().getValue())
                    else:
                        strHeavyAtomsChain = strHeavyAtomsChain + " No heavy atoms"
                    self.addExecutiveSummaryLine(strHeavyAtomsLigand)
                    self.addExecutiveSummaryLine(
                        "    Number of copies in structure  : %.2f" %
                        chain.getNumberOfCopies().getValue())
                    self.addExecutiveSummaryLine("")

        if (self._edPluginBest is not None):
            if (self._edPluginBest.getDataOutput() is not None):
                self.appendExecutiveSummary(self._edPluginBest, "Best : ")
                self.addExecutiveSummaryLine("")

    def generateStrategyShortSummary(self, _xsDataResultStrategy):
        """
        Generates a short summary of the BEST strategy
        """
        self.DEBUG(
            "EDPluginControlIntegrationv10.generateIntegrationShortSummary")
        strStrategyShortSummary = ""
        iTotalNoImages = 0
        fTotalExposureTime = 0.0
        xsDataDiffractionPlan = None
        if self.getDataInput():
            if self.getDataInput().getDiffractionPlan():
                xsDataDiffractionPlan = self.getDataInput().getDiffractionPlan(
                )
        if self._bEstimateRadiationDamage:
            strStrategyShortSummary += "Strategy: Radiation damage estimated"
            if self._edPluginRaddose.getDataOutput(
            ).getTimeToReachHendersonLimit():
                strStrategyShortSummary += ", time to reach Henderson limit: %.1f s\n" % self._edPluginRaddose.getDataOutput(
                ).getTimeToReachHendersonLimit().getValue()
            else:
                strStrategyShortSummary += "\n"

        else:
            strStrategyShortSummary += "Strategy: No radiation damage estimation"
            if xsDataDiffractionPlan:
                if xsDataDiffractionPlan.getMaxExposureTimePerDataCollection():
                    strStrategyShortSummary += ", max exposure time per data collection: %.1f s\n" % xsDataDiffractionPlan.getMaxExposureTimePerDataCollection(
                    ).getValue()
                else:
                    strStrategyShortSummary += "\n"
            else:
                strStrategyShortSummary += "\n"
        if xsDataDiffractionPlan:
            strStrategyShortSummary += "Strategy: Options: "
            listStrategyOptions = []
            if xsDataDiffractionPlan.getAnomalousData():
                if xsDataDiffractionPlan.getAnomalousData().getValue():
                    listStrategyOptions.append("anomalous data")
            if xsDataDiffractionPlan.getAimedCompleteness():
                listStrategyOptions.append(
                    "aimed completeness = %.1f" %
                    xsDataDiffractionPlan.getAimedCompleteness().getValue())
            if xsDataDiffractionPlan.getAimedMultiplicity():
                listStrategyOptions.append(
                    "aimed multiplicity = %d" %
                    xsDataDiffractionPlan.getAimedMultiplicity().getValue())
            if xsDataDiffractionPlan.getAimedResolution():
                listStrategyOptions.append(
                    "aimed resolution = %.2f A" %
                    xsDataDiffractionPlan.getAimedResolution().getValue())
            if xsDataDiffractionPlan.getComplexity():
                listStrategyOptions.append(
                    "complexity = %s" %
                    xsDataDiffractionPlan.getComplexity().getValue())
            if xsDataDiffractionPlan.getStrategyOption():
                listStrategyOptions.append(
                    "extra strategy option(s) = %s" %
                    xsDataDiffractionPlan.getStrategyOption().getValue())
            if listStrategyOptions != []:
                for strStrategyOption in listStrategyOptions[:-1]:
                    strStrategyShortSummary += strStrategyOption + ", "
                strStrategyShortSummary += listStrategyOptions[-1]
            strStrategyShortSummary += "\n"
        fResolutionMax = None
        fRankingResolution = None
        for xsDataCollectionPlan in _xsDataResultStrategy.getCollectionPlan():
            iNoCollectionPlan = xsDataCollectionPlan.getCollectionPlanNumber(
            ).getValue()
            strStrategyShortSummary += "Strategy: Collection plan %d" % iNoCollectionPlan
            xsDataStrategySummary = xsDataCollectionPlan.getStrategySummary()
            if xsDataStrategySummary.getResolutionReasoning() != None:
                strResolutionResoning = xsDataStrategySummary.getResolutionReasoning(
                ).getValue()
                strStrategyShortSummary += ": %s\n" % strResolutionResoning
            else:
                strStrategyShortSummary += "\n"
            xsDataCollectionStrategy = xsDataCollectionPlan.getCollectionStrategy(
            )
            if xsDataStrategySummary.getRankingResolution() is not None:
                fRankingResolution = xsDataStrategySummary.getRankingResolution(
                ).getValue()
                strStrategyShortSummary += "Strategy: Ranking resolution: %.2f [A]\n" % fRankingResolution
            for xsDataSubWedge in xsDataCollectionStrategy.getSubWedge():
                iWedgeNo = xsDataCollectionPlan.getCollectionPlanNumber(
                ).getValue()
                strStrategyShortSummary += "Strategy: wedge %d: " % iWedgeNo
                xsDataStrategySummary = xsDataCollectionPlan.getStrategySummary(
                )
                fResolution = xsDataStrategySummary.getResolution().getValue()
                if (fResolutionMax is None) or (fResolution < fResolutionMax):
                    fResolutionMax = fResolution
                strStrategyShortSummary += "resolution %.2f [A], " % fResolution
                xsDataStringAction = xsDataSubWedge.getAction()
                if xsDataStringAction is not None:
                    strStrategyShortSummary += "%s, " % xsDataStringAction.getValue(
                    )
                iSubWedgeNo = xsDataSubWedge.getSubWedgeNumber().getValue()
                strStrategyShortSummary += "sub wedge %d: " % iSubWedgeNo
                xsDataExperimentalCondition = xsDataSubWedge.getExperimentalCondition(
                )
                xsDataGoniostat = xsDataExperimentalCondition.getGoniostat()
                fRotationStart = xsDataGoniostat.getRotationAxisStart(
                ).getValue()
                strStrategyShortSummary += "start %.2f, " % fRotationStart
                fRange = xsDataGoniostat.getOscillationWidth().getValue()
                fRotationEnd = xsDataGoniostat.getRotationAxisEnd().getValue()
                iNoImages = int((fRotationEnd - fRotationStart) / fRange + 0.1)
                strStrategyShortSummary += "images %d, " % iNoImages
                strStrategyShortSummary += "width %.2f, " % fRange
                xsDataBeam = xsDataExperimentalCondition.getBeam()
                fExpTime = xsDataBeam.getExposureTime().getValue()
                strStrategyShortSummary += "time %.2f [s], " % fExpTime
                fTransmission = xsDataBeam.getTransmission().getValue()
                strStrategyShortSummary += "transmission %.2f\n" % fTransmission
                iTotalNoImages += iNoImages
                fTotalExposureTime += fExpTime * iNoImages
            strStrategyShortSummary += "Strategy: total no images %d, total exposure time %.1f [s]\n" % \
                                    (iTotalNoImages, fTotalExposureTime)
        if fRankingResolution is not None:
            if (fRankingResolution < fResolutionMax) and (
                    abs(fRankingResolution - fResolutionMax) > 0.1):
                strStrategyShortSummary += "\n"
                strStrategyShortSummary += "NOTE! " * 20 + "\n"
                strStrategyShortSummary += "\n"
                strStrategyShortSummary += "BEST has calculated that it should be possible to collect data to %.2f A from this sample.\n" % fRankingResolution
                strStrategyShortSummary += "If you want to calculate a new strategy for data collection to this resolution you\n"
                strStrategyShortSummary += "must first recollect reference images at this resolution.\n"
                strStrategyShortSummary += "\n"
                strStrategyShortSummary += "NOTE! " * 20 + "\n"
                strStrategyShortSummary += "\n"

        self.setDataOutput(XSDataString(strStrategyShortSummary),
                           "strategyShortSummary")
class EDPluginControlKappaStrategyv2_0(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """
    def __init__(self):
        EDPluginControl.__init__(self)

        self.setRequiredToHaveConfiguration(True)

        self.strPluginRaddoseName = "EDPluginRaddosev10"
        self.edPluginRaddose = None
        self.edHandlerXSDataRaddose = None

        self.strPluginBestName = "EDPluginBestv1_2"
        self.edPluginBest = None
        from EDHandlerXSDataBestv1_2 import EDHandlerXSDataBestv1_2
        self.edHandlerXSDataBest = EDHandlerXSDataBestv1_2()

        self.strPluginAlignmentName = "EDPluginSTACAlignmentv2_0"
        self.edPluginAlignment = None
        self.edHandlerXSDataAlignment = None

        self.strPluginKappaStrategyName = "EDPluginSTACStrategyv2_0"
        self.edPluginKappaStrategy = None
        self.edHandlerXSDataKappaStrategy = None

        self.setXSDataInputClass(XSDataInputStrategy, "mxv1InputStrategy")
        EDFactoryPluginStatic.loadModule("XSDataMXv2")
        import XSDataMXv2
        self.setXSDataInputClass(XSDataMXv2.XSDataCollection,
                                 "mxv2DataCollection")
        import XSDataMXv1
        self.setXSDataInputClass(XSDataMXv1.XSDataIndexingResult,
                                 "mxv1IndexingResult")

        # disable kappa by default
        self.KappaStrategy = 0

        self.xsDataSampleCopy = None

        # For default chemical composition
        self.fAverageAminoAcidVolume = 135.49
        self.fAverageCrystalSolventContent = 0.47
        self.fAverageSulfurContentPerAminoacid = 0.05
        self.fAverageSulfurConcentration = 314

    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        self.DEBUG("EDPluginControlKappaStrategyv2_0.preProcess...")
        self.edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput(
            "mxv1InputStrategy")[0].getSample()

        if (xsDataSampleCrystalMM is None):
            self.xsDataSampleCopy = XSDataSampleCrystalMM()

        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self.xsDataSampleCopy = XSDataSampleCrystalMM.parseString(
                strXmlStringDataSample)

        xsDataCrystal = self.getDataInput(
            "mxv1InputStrategy")[0].getCrystalRefined()
        if (xsDataCrystal is not None):
            self.xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Raddose is enabled only if the beam flux is set
        if (self.getDataInput("mxv1InputStrategy")
            [0].getExperimentalCondition().getBeam().getFlux() is None):
            strWarningMessage = EDMessage.WARNING_CANNOT_USE_PLUGIN_03 % (
                'EDPluginControlKappaStrategyv2_0.preProcess',
                self.strPluginRaddoseName, "Beam Flux not set")
            self.warning(strWarningMessage)
            self.addWarningMessage(strWarningMessage)

        else:
            self.edPluginRaddose = self.loadPlugin(self.strPluginRaddoseName)

            if (self.edPluginRaddose is not None):
                self.DEBUG("EDPluginControlKappaStrategyv2_0.preProcess: " +
                           self.strPluginRaddoseName +
                           " Found... setting Data Input")

                xsDataStringSpaceGroup = self.getDataInput(
                    "mxv1InputStrategy")[0].getDiffractionPlan(
                    ).getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                strNumOperators = None
                strSpaceGroup = None
                if (xsDataStringSpaceGroup is not None):
                    strSpaceGroup = xsDataStringSpaceGroup.getValue()
                    self.DEBUG(
                        "EDPluginControlKappaStrategyv2_0.preProcess: Forced Space Group Found: "
                        + strSpaceGroup)
                    try:
                        strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                            strSpaceGroup)
                    except Exception as detail:
                        strErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                            'EDPluginControlKappaStrategyv2_0.preProcess',
                            "Problem to calculate Number of symmetry operators",
                            detail)
                        self.error(strErrorMessage)
                        self.addErrorMessage(strErrorMessage)
                        raise RuntimeError(strErrorMessage)
                # Space Group has NOT been forced
                else:
                    xsDataStringSpaceGroup = self.xsDataSampleCopy.getCrystal(
                    ).getSpaceGroup().getName()
                    if (xsDataStringSpaceGroup is not None):
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroup = self.xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getName().getValue()
                        self.DEBUG(
                            "EDPluginControlKappaStrategyv2_0.preProcess: Space Group IT Name found by indexing: "
                            + strSpaceGroup)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                strSpaceGroup)
                        except Exception as detail:
                            strErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                                'EDPluginControlKappaStrategyv2_0.preProcess',
                                "Problem to calculate Number of symmetry operators",
                                detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError(strErrorMessage)
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        dSpaceGroupITNumber = self.xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getITNumber().getValue()
                        self.DEBUG(
                            "EDPluginControlKappaStrategyv2_0.preProcess: Space Group IT Number Found by indexing: %d"
                            % dSpaceGroupITNumber)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(
                                str(dSpaceGroupITNumber))
                        except Exception as detail:
                            strErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                                'EDPluginControlKappaStrategyv2_0.preProcess',
                                "Problem to calculate Number of symmetry operators",
                                detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError(strErrorMessage)

                if (strNumOperators is not None):
                    iNumOperators = int(strNumOperators)
                else:
                    strErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                        'EDPluginControlKappaStrategyv2_0.preProcess',
                        "No symmetry operators found for Space Group: ",
                        strSpaceGroup)
                    self.error(strErrorMessage)
                    self.addErrorMessage(strErrorMessage)
                    raise RuntimeError(strErrorMessage)

                xsDataChemicalComposition = self.xsDataSampleCopy.getChemicalComposition(
                )

                if (xsDataChemicalComposition is None):
                    # create a default chemical composition and assign it to the sample
                    xsDataDefaultChemicalComposition = self.getDefaultChemicalComposition(
                        self.xsDataSampleCopy, iNumOperators)
                    self.xsDataSampleCopy.setChemicalComposition(
                        xsDataDefaultChemicalComposition)
                else:
                    # Check for Sulfur atoms, if none, add native sulfur atoms
                    xsDataUpdatedChemicalComposition = self.updateChemicalComposition(
                        xsDataChemicalComposition)
                    self.xsDataSampleCopy.setChemicalComposition(
                        xsDataUpdatedChemicalComposition)

                # create Data Input for Raddose
                from EDHandlerXSDataRaddosev10 import EDHandlerXSDataRaddosev10
                self.edHandlerXSDataRaddose = EDHandlerXSDataRaddosev10()
                xsDataBeam = self.getDataInput("mxv1InputStrategy")[
                    0].getExperimentalCondition().getBeam()

                xsDataRaddoseInput = None
                iNumberOfImages = 1
                self.warning("Number of images for RADDOSE forced to 1")
                try:
                    xsDataRaddoseInput = self.edHandlerXSDataRaddose.getXSDataRaddoseInput(
                        xsDataBeam, self.xsDataSampleCopy, iNumOperators,
                        iNumberOfImages)

                except Exception as detail:
                    strWarningMessage = EDMessage.WARNING_CANNOT_USE_PLUGIN_03 % (
                        'EDPluginControlKappaStrategyv2_0.preProcess',
                        self.strPluginRaddoseName,
                        "EDHandlerXSDataRaddose : " + detail)
                    self.warning(strWarningMessage)
                    self.addWarningMessage(strWarningMessage)

                if (xsDataRaddoseInput is not None):
                    self.edPluginRaddose.setDataInput(xsDataRaddoseInput)
                    self.edPluginRaddose.setBaseDirectory(
                        self.getWorkingDirectory())
                    self.edPluginRaddose.setBaseName(self.strPluginRaddoseName)

                    # More checks?
#                    try:
#                        self.edPluginRaddose.setDataInput( xsDataRaddoseInput )
#                        self.edPluginRaddose.setBaseDirectory( self.getWorkingDirectory() )
#                        self.edPluginRaddose.setBaseName( self.strPluginRaddoseName )
#
#                    except Exception, detail:
#                        strWarningMessage = EDMessage.WARNING_CANNOT_USE_PLUGIN_03 % ('EDPluginControlStrategyv1_1.preProcess', self.strPluginRaddoseName,  detail ) )
#                        self.warning( strWarningMessage )
#                        self.addWarningMessage( strWarningMessage )

            else:
                strErrorMessage = EDMessage.ERROR_PLUGIN_NOT_LOADED_02 % (
                    'EDPluginControlKappaStrategyv2_0.preProcess',
                    self.strPluginRaddoseName)
                self.error(strErrorMessage)
                self.addErrorMessage(strErrorMessage)
                raise RuntimeError(strErrorMessage)

        self.edPluginBest = self.loadPlugin(self.strPluginBestName)
        if (self.edPluginBest is None):
            strErrorMessage = EDMessage.ERROR_PLUGIN_NOT_LOADED_02 % (
                'EDPluginControlKappaStrategyv2_0.preProcess',
                self.strPluginBestName)
            self.error(strErrorMessage)
            self.addErrorMessage(strErrorMessage)
            raise RuntimeError(strErrorMessage)
        else:
            self.edPluginBest.setBaseDirectory(self.getWorkingDirectory())
            self.edPluginBest.setBaseName(self.strPluginBestName)

        if (self.KappaStrategy):
            # Alignment
            self.edPluginAlignment = self.loadPlugin(
                self.strPluginAlignmentName)
            if (self.edPluginAlignment is None):
                errorMessage = EDMessage.ERROR_PLUGIN_NOT_LOADED_02 % (
                    'EDPluginControlKappaStrategyv2_0.preProcess',
                    self.strPluginAlignmentName)
                self.error(errorMessage)
                self.addErrorMessage(errorMessage)
                # do not kill the application just because this feature is not available
                # raise RuntimeError, errorMessage
            else:
                self.edPluginAlignment.setBaseDirectory(
                    self.getWorkingDirectory())
                self.edPluginAlignment.setBaseName(self.strPluginAlignmentName)

            # KappaStaregy
            self.edPluginKappaStrategy = self.loadPlugin(
                self.strPluginKappaStrategyName)
            if (self.edPluginKappaStrategy is None):
                errorMessage = EDMessage.ERROR_PLUGIN_NOT_LOADED_02 % (
                    'EDPluginControlKappaStrategyv2_0.preProcess',
                    self.strPluginKappaStrategyName)
                self.error(errorMessage)
                self.addErrorMessage(errorMessage)
                # raise RuntimeError, errorMessage
            else:
                self.edPluginKappaStrategy.setBaseDirectory(
                    self.getWorkingDirectory())
                self.edPluginKappaStrategy.setBaseName(
                    self.strPluginKappaStrategyName)

    def configure(self):
        EDPluginControl.configure(self)
        self.DEBUG("EDPluginControlKappaStrategyv2_0.configure")
        bKappaOn = self.config.get("KAPPA")
        if bKappaOn:
            # self.strPluginStrategyName = "EDPluginControlStrategyv10"
            # self.strPluginStrategyName = "EDPluginControlStrategyv2_0"
            self.KappaStrategy = 1
        else:
            self.KappaStrategy = 0

    def process(self, _edObject=None):
        """
        """
        EDPluginControl.process(self, _edObject)
        self.DEBUG("EDPluginControlKappaStrategyv2_0.process...")

        # In case Beam Flux has not been set, The plugin Raddose has not been created, so it could be None
        # and it won't be launched in this case
        if (self.edPluginRaddose is not None):
            self.connectProcess(self.edPluginRaddose.executeSynchronous)
            self.edPluginRaddose.connectSUCCESS(self.doRaddoseToBestTransition)
            self.edPluginRaddose.connectFAILURE(self.doFailureActionRaddose)
        else:
            # The plugin Best should not be None as this has been checked in the preProcess method... Double check it anyway
            if (self.edPluginBest is not None):
                self.connectProcess(self.executeBest)

        # Launches Best anyway whether Raddose has been launched or not
        # The plugin Best should not be None as this has been checked in the preProcess method... Double check it anyway
        if (self.edPluginBest is not None):
            self.edPluginBest.connectSUCCESS(self.doSuccessActionBest)
            self.edPluginBest.connectFAILURE(self.doFailureActionBest)

        # Kappa strategy calculation
        if self.hasDataInput("mxv2DataCollection"):
            if self.edPluginAlignment is not None:
                self.connectProcess(self.doBestToAlignmentTransition)
#                self.edPluginAlignment.connectSUCCESS( self.doAlignmentToKappaStrategyTransition )
#                self.edPluginAlignment.connectFAILURE( self.doFailureActionAlignment )
#                self.edPluginKappaStrategy.connectSUCCESS( self.doKappaStrategyMerge )
#                self.edPluginKappaStrategy.connectFAILURE( self.doFailureActionKappaStrategy )

# Kappa strategy calculation
            if self.edPluginKappaStrategy is not None:
                self.connectProcess(self.doAlignmentToStrategyTransition)
#                self.edPluginKappaStrategy.connectSUCCESS( self.doKappaStrategyMerge )
#                self.edPluginKappaStrategy.connectFAILURE( self.doFailureActionKappaStrategy )

    def postProcess(self, _edObject=None):
        """
        """
        EDPluginControl.postProcess(self, _edObject)
        self.DEBUG("EDPluginControlKappaStrategyv2_0.postProcess...")

        xsDataResultBest = self.edPluginBest.getDataOutput()
        xsDataResultStrategy = None

        if (xsDataResultBest is not None):
            xsDataResultStrategy = self.edHandlerXSDataBest.getXSDataResultStrategy(
                xsDataResultBest,
                self.getDataInput("mxv1InputStrategy")
                [0].getExperimentalCondition(), self.xsDataSampleCopy)

        self.setDataOutput(xsDataResultStrategy)

        # possibleAlignments
        try:
            self.setDataOutput(self.edPluginAlignment.getDataOutput(),
                               "possibleOrientations")
        except:
            self.WARNING("Could not get the list of Possible orientations.")

    def doRaddoseToBestTransition(self, _edPlugin):
        """
        """
        self.DEBUG(
            "EDPluginControlKappaStrategyv2_0.doRaddoseToBestTransition")
        self.retrieveSuccessMessages(
            _edPlugin,
            "EDPluginControlKappaStrategyv2_0.doRaddoseToBestTransition")

        xsDataRaddoseOutput = self.edPluginRaddose.getDataOutput()

        # update the strategy data with the data coming from Raddose
        self.xsDataSampleCopy.setAbsorbedDoseRate(
            xsDataRaddoseOutput.getAbsorbedDoseRate())

        # Call the Best Translator layer

        xsDataInputStrategyCopy = XSDataInputStrategy.parseString(
            self.getDataInput("mxv1InputStrategy")[0].marshal())
        xsDataInputStrategyCopy.setSample(self.xsDataSampleCopy)

        xsDataInputBest = self.edHandlerXSDataBest.getXSDataInputBest(
            xsDataInputStrategyCopy)

        self.edPluginBest.setDataInput(xsDataInputBest)
        self.edPluginBest.executeSynchronous()

    def doBestToAlignmentTransition(self, _edPlugin):
        """
        """
        self.DEBUG(
            "EDPluginControlKappaStrategyv2_0.doBestToAlignmentTransition")
        # self.retrieveSuccessMessages( _edPlugin, "EDPluginControlStrategyv01.doRaddoseToBestTransition" )

        xsDataInputStrategyCopy = XSDataInputStrategy.parseString(
            self.getDataInput("mxv1InputStrategy")[0].marshal())
        xsDataInputStrategyCopy.setSample(self.xsDataSampleCopy)

        xsDataInputBest = self.edHandlerXSDataBest.getXSDataInputBest(
            xsDataInputStrategyCopy)
        self.edPluginAlignment.setDataInput(xsDataInputBest, "inputBest")
        self.edPluginAlignment.setDataInput(
            self.getDataInput("mxv2DataCollection")[0], "dataCollection")
        self.edPluginAlignment.setDataInput(
            self.getDataInput("mxv1IndexingResult")[0], "indexingResult")

        self.edPluginAlignment.executeSynchronous()

    def doAlignmentToStrategyTransition(self, _edPlugin):
        """
        """
        self.DEBUG("EDPluginControlKappaStrategyv2_0.doAlignmentToStrategy")
        # self.retrieveSuccessMessages( _edPlugin, "EDPluginControlStrategyv01.doRaddoseToBestTransition" )

        # Call the Best Translator layer
        # from XSDataSTACv01 import kappa_alignment_response
        # from XSDataSTACv01 import kappa_strategy_request
        # from XSDataSTACv01 import strategy_request

        self.xsKappaStrategyRequest = kappa_strategy_request()
        # self.xsKappaStrategyRequest.build(???)

        KappaAlignmentResponse = self.edPluginAlignment.getDataOutput()
        xsDataKappaAlignmentList = KappaAlignmentResponse.getPossible_orientation(
        )
        self.xsKappaStrategyRequest.setDesired_datum(xsDataKappaAlignmentList)

        self.xsksreq = strategy_request()
        self.xsKappaStrategyRequest.setStandard_request(self.xsksreq)

        self.edPluginKappaStrategy.setDataInput(self.xsKappaStrategyRequest,
                                                "kappa_strategy_request")
        self.edPluginKappaStrategy.setDataInput(
            self.getDataInput("mxv2DataCollection")[0], "dataCollection")
        self.edPluginKappaStrategy.setDataInput(
            self.getDataInput("mxv1InputStrategy")[0], "inputBest")

        # self.edPluginKappaStrategy.m_xsDataBestFileContentPar=self.getDataInput()[0].getBestFileContentPar()
        self.edPluginKappaStrategy.executeSynchronous()

    def doFailureActionRaddose(self, _edPlugin):
        """
        retrieve the potential warning messages
        retrieve the potential error messages
        """
        self.DEBUG("EDPluginControlKappaStrategyv2_0.doFailureActionRaddose")
        self.retrieveFailureMessages(
            _edPlugin,
            "EDPluginControlKappaStrategyv2_0.doFailureActionRaddose")
        strWarningMessage = EDMessage.WARNING_CANNOT_USE_PLUGIN_03 % (
            'EDPluginControlKappaStrategyv2_0.doFailureActionRaddose',
            self.strPluginRaddoseName, "Raddose failure")
        self.warning(strWarningMessage)
        self.addWarningMessage(strWarningMessage)
        self.executeBest(self)

    def executeBest(self, _edPlugin):
        xsDataInputBest = None
        # Call the Best Translator layer

        from EDHandlerXSDataBestv1_2 import EDHandlerXSDataBestv1_2
        self.__edHandlerXSDataBest = EDHandlerXSDataBestv1_2()
        xsDataInputStrategyCopy = XSDataInputStrategy.parseString(
            self.getDataInput("mxv1InputStrategy")[0].marshal())
        xsDataInputStrategyCopy.setSample(self.xsDataSampleCopy)
        xsDataInputBest = self.__edHandlerXSDataBest.getXSDataInputBest(
            xsDataInputStrategyCopy)
        self.edPluginBest.setDataInput(xsDataInputBest)
        self.edPluginBest.executeSynchronous()

    def doSuccessActionBest(self, _edPlugin):
        """
        retrieve the potential warning messages
        """
        self.DEBUG("EDPluginControlKappaStrategyv2_0.doSuccessActionBest")
        self.retrieveSuccessMessages(
            _edPlugin, "EDPluginControlKappaStrategyv2_0.doSuccessActionBest")

    def doFailureActionBest(self, _edPlugin):
        """
        retrieve the potential warning messages
        retrieve the potential error messages
        """
        self.DEBUG("EDPluginControlKappaStrategyv2_0.doFailureActionBest")
        self.retrieveFailureMessages(
            _edPlugin, "EDPluginControlKappaStrategyv2_0.doFailureActionBest")

    def getDefaultChemicalComposition(self, _xsDataSample, _inumOperators):
        """
        """
        xsDataCell = _xsDataSample.getCrystal().getCell()
        a = xsDataCell.getLength_a().getValue()
        b = xsDataCell.getLength_b().getValue()
        c = xsDataCell.getLength_c().getValue()
        alpha = math.radians(xsDataCell.getAngle_alpha().getValue())
        beta = math.radians(xsDataCell.getAngle_beta().getValue())
        gamma = math.radians(xsDataCell.getAngle_gamma().getValue())

        fUnitCellVolume = a * b * c * (
            math.sqrt(1 - math.cos(alpha) * math.cos(alpha) - math.cos(beta) *
                      math.cos(beta) - math.cos(gamma) * math.cos(gamma) +
                      2 * math.cos(alpha) * math.cos(beta) * math.cos(gamma)))
        fPolymerVolume = fUnitCellVolume * (1 -
                                            self.fAverageCrystalSolventContent)
        fNumberOfMonomersPerUnitCell = fPolymerVolume / self.fAverageAminoAcidVolume
        fNumberOfMonomersPerAsymmetricUnit = fNumberOfMonomersPerUnitCell / _inumOperators
        iNumberOfSulfurAtom = int(
            round(fNumberOfMonomersPerAsymmetricUnit *
                  self.fAverageSulfurContentPerAminoacid))

        xsDataAtom = XSDataAtom()
        xsDataAtom.setSymbol(XSDataString("S"))
        xsDataAtom.setNumberOf(XSDataDouble(iNumberOfSulfurAtom))
        xsDataAtomicComposition = XSDataAtomicComposition()
        xsDataAtomicComposition.addAtom(xsDataAtom)

        xsDataChain = XSDataChain()
        xsDataChain.setType(XSDataString("protein"))
        xsDataChain.setNumberOfMonomers(
            XSDataDouble(round(fNumberOfMonomersPerAsymmetricUnit)))
        xsDataChain.setNumberOfCopies(XSDataDouble(1))
        xsDataChain.setHeavyAtoms(xsDataAtomicComposition)

        xsDataStructure = XSDataStructure()
        xsDataStructure.addChain(xsDataChain)
        xsDataStructure.setNumberOfCopiesInAsymmetricUnit(XSDataDouble(1))

        xsDataAtomSolvent = XSDataAtom()
        xsDataAtomSolvent.setSymbol(XSDataString("S"))
        xsDataAtomSolvent.setConcentration(
            XSDataDouble(self.fAverageSulfurConcentration))
        xsDataAtomicCompositionSolvent = XSDataAtomicComposition()
        xsDataAtomicCompositionSolvent.addAtom(xsDataAtomSolvent)
        xsDataSolvent = XSDataSolvent()
        xsDataSolvent.setAtoms(xsDataAtomicCompositionSolvent)

        xsDataChemicalCompositionMM = XSDataChemicalCompositionMM()
        xsDataChemicalCompositionMM.setSolvent(xsDataSolvent)
        xsDataChemicalCompositionMM.setStructure(xsDataStructure)

        return xsDataChemicalCompositionMM

    def updateChemicalComposition(self, _xsDataChemicalComposition):
        """
        """
        xsDataChemicalComposition = _xsDataChemicalComposition

        for chain in xsDataChemicalComposition.getStructure().getChain():
            if (chain.getType().getValue() == "protein"):
                bSulfurExists = False
                xsDataAtomicCompositionHeavyAtoms = chain.getHeavyAtoms()
                if (xsDataAtomicCompositionHeavyAtoms is None):
                    xsDataAtomicCompositionHeavyAtoms = XSDataAtomicComposition(
                    )
                else:
                    for heavyAtom in xsDataAtomicCompositionHeavyAtoms.getAtom(
                    ):
                        if (heavyAtom.getSymbol().getValue() == "S"
                                or heavyAtom.getSymbol().getValue() == "s"):
                            bSulfurExists = True

                # all protein chains should contain sulfur atom as a percentage of the number
                # of amino acids. Add them if the user did not input them.
                if (bSulfurExists == False):
                    iNumberOfSulfurAtom = int(
                        round(chain.getNumberOfMonomers().getValue() * 0.05))
                    xsDataSulfurAtom = XSDataAtom()
                    xsDataSulfurAtom.setSymbol(XSDataString("S"))
                    xsDataSulfurAtom.setNumberOf(
                        XSDataDouble(iNumberOfSulfurAtom))
                    xsDataAtomicCompositionHeavyAtoms.addAtom(xsDataSulfurAtom)
                    chain.setHeavyAtoms(xsDataAtomicCompositionHeavyAtoms)

        return xsDataChemicalComposition

    def generateExecutiveSummary(self, _edPlugin):
        """
        Generates a summary of the execution of the plugin.
        """
        self.DEBUG("EDPluginControlKappaStrategyv2_0.generateExecutiveSummary")
        self.addExecutiveSummaryLine("Summary of kappa strategy:")
        self.addErrorWarningMessagesToExecutiveSummary()

        xsDataResultStrategy = self.getDataOutput()

        if (self.edPluginRaddose is not None):
            if (self.edPluginRaddose.getDataOutput() is not None):
                self.appendExecutiveSummary(self.edPluginRaddose, "Raddose : ")
                self.addExecutiveSummaryLine("")
                self.addExecutiveSummaryLine(
                    "Calculations assuming polymer crystal with:")
                self.addExecutiveSummaryLine(
                    "------------------------------------------")
                self.addExecutiveSummaryLine("")

                xsDataStructure = xsDataResultStrategy.getCollectionPlan(
                )[0].getCollectionStrategy().getSample(
                ).getChemicalComposition().getStructure()

                self.addExecutiveSummaryLine(
                    "Number of structure copies in asymmetric unit: %.2f" %
                    xsDataStructure.getNumberOfCopiesInAsymmetricUnit(
                    ).getValue())
                self.addExecutiveSummaryLine("")

                chains = xsDataStructure.getChain()
                self.addExecutiveSummaryLine("Chains:")
                for chain in chains:
                    strChainType = chain.getType().getValue()
                    self.addExecutiveSummaryLine(
                        "    Type                           : %s" %
                        strChainType)
                    if (strChainType == "protein"):
                        self.addExecutiveSummaryLine(
                            "    Number of residues             : %.2f" %
                            chain.getNumberOfMonomers().getValue())
                    elif (strChainType == "dna" or strChainType == "rna"):
                        self.addExecutiveSummaryLine(
                            "    Number of nucleotides          : %.2f" %
                            chain.getNumberOfMonomers().getValue())
                    strHeavyAtomsChain = "    Number of heavy atoms          :"
                    if (chain.getHeavyAtoms() is not None):
                        heavyAtomsChain = chain.getHeavyAtoms().getAtom()
                        for heavyAtomChain in heavyAtomsChain:
                            strHeavyAtomsChain = strHeavyAtomsChain + " %s=%d" % (
                                heavyAtomChain.getSymbol().getValue(),
                                heavyAtomChain.getNumberOf().getValue())
                    else:
                        strHeavyAtomsChain = strHeavyAtomsChain + " No heavy atoms"
                    self.addExecutiveSummaryLine(strHeavyAtomsChain)

                    self.addExecutiveSummaryLine(
                        "    Number of copies in structure  : %.2f" %
                        chain.getNumberOfCopies().getValue())
                    self.addExecutiveSummaryLine("")

                ligands = xsDataStructure.getLigand()
                if (len(ligands) != 0):
                    self.addExecutiveSummaryLine("Ligands:")

                for ligand in ligands:
                    self.addExecutiveSummaryLine(
                        "    Number of light atoms          : %.2f" %
                        ligand.getNumberOfLightAtoms().getValue())
                    strHeavyAtomsLigand = "    Number of heavy atoms          :"
                    if (ligand.getHeavyAtoms() is not None):
                        heavyAtomsLigand = ligand.getHeavyAtoms().getAtom()
                        for heavyAtomLigand in heavyAtomsLigand:
                            strHeavyAtomsLigand = strHeavyAtomsLigand + " %s=%d" % (
                                heavyAtomLigand.getSymbol().getValue(),
                                heavyAtomLigand.getNumberOf().getValue())
                    else:
                        strHeavyAtomsChain = strHeavyAtomsChain + " No heavy atoms"
                    self.addExecutiveSummaryLine(strHeavyAtomsLigand)
                    self.addExecutiveSummaryLine(
                        "    Number of copies in structure  : %.2f" %
                        chain.getNumberOfCopies().getValue())
                    self.addExecutiveSummaryLine("")

        if (self.edPluginBest is not None):
            if (self.edPluginBest.getDataOutput() is not None):
                self.appendExecutiveSummary(self.edPluginBest, "Best : ")
                self.addExecutiveSummaryLine("")

        if (self.edPluginAlignment is not None):
            # if ( self.edPluginAlignment.getDataOutput() is not None ):
            self.appendExecutiveSummary(self.edPluginAlignment,
                                        "STAC - Alignment : ")
            self.addExecutiveSummaryLine("")

        if (self.edPluginKappaStrategy is not None):
            # if ( self.edPluginAlignment.getDataOutput() is not None ):
            self.appendExecutiveSummary(self.edPluginKappaStrategy,
                                        "STAC - Strategy : ")
            self.addExecutiveSummaryLine("")
class EDPluginControlStrategyv1_3(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """

    def __init__ (self):
        """
        """
        EDPluginControl.__init__(self)
        self.setXSDataInputClass(XSDataInputStrategy)

        self._strPluginRaddoseName = "EDPluginRaddosev10"
        self._edPluginRaddose = None
        self._edHandlerXSDataRaddose = None

        self._strPluginBestName = "EDPluginBestv1_3"
        self._edPluginBest = None
        self._edHandlerXSDataBest = None

        self._strPluginPlotGleName = "EDPluginExecPlotGlev1_1"
        self._edPluginPlotGle = None

        self._strCONF_SYMOP_HOME = "symopHome"
        # Default value for the location of the symop table
        self._strSymopHome = None

        self._xsDataSampleCopy = None

        # For default chemical composition
        self._fAverageAminoAcidVolume = 135.49
        self._fAverageCrystalSolventContent = 0.47
        self._fAverageSulfurContentPerAminoacid = 0.05
        self._fAverageSulfurConcentration = 314

        # This varaible determines if Raddose should be executed or not
        self._bEstimateRadiationDamage = None

        # Raddose log file
        self.xsDataFileRaddoseLog = None


    def setSymopHome(self, _strSymopHome):
        self._strSymopHome = _strSymopHome


    def getSymopHome(self):
        return self._strSymopHome


    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        self.DEBUG("EDPluginControlStrategyv1_3.preProcess...")
        self._edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput().getSample()

        if(xsDataSampleCrystalMM is None):
            self._xsDataSampleCopy = XSDataSampleCrystalMM()
        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self._xsDataSampleCopy = XSDataSampleCrystalMM.parseString(strXmlStringDataSample)

        xsDataCrystal = self.getDataInput().getCrystalRefined()
        if(xsDataCrystal is not None):
            self._xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Load the Best plugin
        self._edPluginBest = self.loadPlugin(self._strPluginBestName)
        self._edPluginBest.setBaseDirectory(self.getWorkingDirectory())
        self._edPluginBest.setBaseName(self._strPluginBestName)

        # Load the plot gle plugin
        self._edPluginPlotGle = self.loadPlugin(self._strPluginPlotGleName)

        # Check if radiation damage estimation is required or not in the diffraction plan
        xsDataDiffractionPlan = self.getDataInput().getDiffractionPlan()
        if xsDataDiffractionPlan is not None:
            if xsDataDiffractionPlan.getEstimateRadiationDamage():
                if xsDataDiffractionPlan.getEstimateRadiationDamage().getValue():
                    # Yes, is requested
                    self._bEstimateRadiationDamage = True
                else:
                    # No, is explicitly not requested
                    self._bEstimateRadiationDamage = False
            elif xsDataDiffractionPlan.getStrategyOption() is not None:
                if xsDataDiffractionPlan.getStrategyOption().getValue().find("-DamPar") != -1:
                    # The "-DamPar" option requires estimation of radiation damage
                    self._bEstimateRadiationDamage = True

        # Check if we know what to do with radiation damage
        if self._bEstimateRadiationDamage is None:
            # "Force" the estimation of radiation damage if the flux is present
            if self.getDataInput().getExperimentalCondition().getBeam().getFlux() is None:
                strWarningMessage = "EDPluginControlStrategyv1_3: Missing flux input - cannot estimate radiation damage."
                self.WARNING(strWarningMessage)
                self.addWarningMessage(strWarningMessage)
                self._bEstimateRadiationDamage = False
            else:
                self._bEstimateRadiationDamage = True


        if self._bEstimateRadiationDamage:
            if self.getDataInput().getExperimentalCondition().getBeam().getFlux() is None:
                strErrorMessage = "EDPluginControlStrategyv1_3: Missing flux input. Cannot estimate radiation damage"
                self.ERROR(strErrorMessage)
                self.addErrorMessage(strErrorMessage)
                self.setFailure()

        if not self.isFailure():

            self._edPluginRaddose = self.loadPlugin(self._strPluginRaddoseName)

            if (self._edPluginRaddose is not None):
                self.DEBUG("EDPluginControlStrategyv1_3.preProcess: " + self._strPluginRaddoseName + " Found... setting Data Input")

                strFileSymop = os.path.join(self.getSymopHome(), "symop.lib")

                xsDataStringSpaceGroup = self.getDataInput().getDiffractionPlan().getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                bSpaceGroupForced = False
                if(xsDataStringSpaceGroup is not None):
                    strSpaceGroup = xsDataStringSpaceGroup.getValue().upper().replace(" ", "")
                    if strSpaceGroup != "":
                        self.DEBUG("EDPluginControlStrategyv1_3.preProcess: Forced Space Group Found: " + strSpaceGroup)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(strSpaceGroup, strFileSymop)
                            bSpaceGroupForced = True
                        except Exception, detail:
                            strErrorMessage = "EDPluginControlStrategyv1_3: Problem to calculate Number of symmetry operators: {0}".format(detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
                if not bSpaceGroupForced:
                    # Space Group has NOT been forced
                    xsDataStringSpaceGroup = self._xsDataSampleCopy.getCrystal().getSpaceGroup().getName()
                    if (xsDataStringSpaceGroup is not None):
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroupName = self._xsDataSampleCopy.getCrystal().getSpaceGroup().getName().getValue()
                        self.DEBUG("EDPluginControlStrategyv1_3.preProcess: Space Group IT Name found by indexing: " + strSpaceGroupName)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(strSpaceGroupName, strFileSymop)
                        except Exception, detail:
                            strErrorMessage = "EDPluginControlStrategyv1_3: Problem to calculate Number of symmetry operators: {0}".format(detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        iSpaceGroupITNumber = self._xsDataSampleCopy.getCrystal().getSpaceGroup().getITNumber().getValue()
                        self.DEBUG("EDPluginControlStrategyv1_3.preProcess: Space Group IT Number Found by indexing: %d" % iSpaceGroupITNumber)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(str(iSpaceGroupITNumber), strFileSymop)
                        except Exception, detail:
                            strErrorMessage = "EDPluginControlStrategyv1_3: Problem to calculate Number of symmetry operators: {0}".format(detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage

                if (strNumOperators is not None):
                    iNumOperators = int(strNumOperators)
                else:
                    strErrorMessage = "EDPluginControlStrategyv1_3: No symmetry operators found for Space Group: {0}".format(strNumOperators)
                    self.error(strErrorMessage)
                    self.addErrorMessage(strErrorMessage)
                    raise RuntimeError, strErrorMessage

                xsDataChemicalComposition = self._xsDataSampleCopy.getChemicalComposition()

                if(xsDataChemicalComposition is None):
                    # create a default chemical composition and assign it to the sample
                    xsDataDefaultChemicalComposition = self.getDefaultChemicalComposition(self._xsDataSampleCopy, iNumOperators)
                    self._xsDataSampleCopy.setChemicalComposition(xsDataDefaultChemicalComposition)
                else:
                    # Check for Sulfur atoms, if none, add native sulfur atoms
                    xsDataUpdatedChemicalComposition = self.updateChemicalComposition(xsDataChemicalComposition)
                    self._xsDataSampleCopy.setChemicalComposition(xsDataUpdatedChemicalComposition)

                # create Data Input for Raddose
                from EDHandlerXSDataRaddosev10 import EDHandlerXSDataRaddosev10
                self._edHandlerXSDataRaddose = EDHandlerXSDataRaddosev10()
                xsDataBeam = self.getDataInput().getExperimentalCondition().getBeam()

                # Calculate number of images (MXSUP-1616):
                iNumberOfImages = None
                xsDataCollection = self.dataInput.dataCollection
                if xsDataCollection is not None:
                    iNumberOfImages = 0
                    for xsDataSubWedge in xsDataCollection.subWedge:
                        xsDataGoniostat = xsDataSubWedge.experimentalCondition.goniostat
                        iOscStart = xsDataGoniostat.rotationAxisStart.value
                        iOscEnd = xsDataGoniostat.rotationAxisEnd.value
                        iOscWidth = xsDataGoniostat.oscillationWidth.value
                        iNumberOfImages += int(round((iOscEnd - iOscStart) / iOscWidth, 0))
                if iNumberOfImages is None:
                    iNumberOfImages = 1
                    self.WARNING("No goniostat information, number of images for RADDOSE set to 1")

                xsDataRaddoseInput = self._edHandlerXSDataRaddose.getXSDataRaddoseInput(xsDataBeam, self._xsDataSampleCopy, iNumOperators, iNumberOfImages)
                if xsDataRaddoseInput is not None:
                    self._edPluginRaddose.setDataInput(xsDataRaddoseInput)
                    self._edPluginRaddose.setBaseDirectory(self.getWorkingDirectory())
                    self._edPluginRaddose.setBaseName(self._strPluginRaddoseName)
Esempio n. 10
0
class EDPluginControlKappaStrategyv2_0(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """
    def __init__(self):
        EDPluginControl.__init__(self)
        #self.setXSDataInputClass(EDList)

        self.setRequiredToHaveConfiguration(True)

        self.strPluginRaddoseName = "EDPluginRaddosev10"
        self.edPluginRaddose = None
        self.edHandlerXSDataRaddose = None

        self.strPluginBestName = "EDPluginBestv1_2"
        self.edPluginBest = None
        from EDHandlerXSDataBestv1_2 import EDHandlerXSDataBestv1_2
        self.edHandlerXSDataBest = EDHandlerXSDataBestv1_2()

        self.strPluginAlignmentName = "EDPluginSTACAlignmentv2_0"
        self.edPluginAlignment = None
        self.edHandlerXSDataAlignment = None

        self.strPluginKappaStrategyName = "EDPluginSTACStrategyv2_0"
        self.edPluginKappaStrategy = None
        self.edHandlerXSDataKappaStrategy = None

        self.setXSDataInputClass(XSDataInputStrategy, "mxv1InputStrategy")
        EDFactoryPluginStatic.loadModule("XSDataMXv2")
        import XSDataMXv2
        self.setXSDataInputClass(XSDataMXv2.XSDataCollection,
                                 "mxv2DataCollection")
        import XSDataMXv1
        self.setXSDataInputClass(XSDataMXv1.XSDataIndexingResult,
                                 "mxv1IndexingResult")

        #disable kappa by default
        self.KappaStrategy = 0

        self.strCONF_SYMOP_HOME = "symopHome"
        # Default value for the location of the symop table
        self.strSymopHome = os.path.normpath("/opt/pxsoft/ccp4-6.0.2/lib/data")

        self.xsDataSampleCopy = None

        # For default chemical composition
        self.fAverageAminoAcidVolume = 135.49
        self.fAverageCrystalSolventContent = 0.47
        self.fAverageSulfurContentPerAminoacid = 0.05
        self.fAverageSulfurConcentration = 314

    def setSymopHome(self, _strSymopHome):
        self.strSymopHome = _strSymopHome

    def getSymopHome(self):
        return self.strSymopHome

    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        EDVerbose.DEBUG("EDPluginControlKappaStrategyv2_0.preProcess...")
        self.edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput(
            "mxv1InputStrategy")[0].getSample()

        if (xsDataSampleCrystalMM is None):
            self.xsDataSampleCopy = XSDataSampleCrystalMM()

        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self.xsDataSampleCopy = XSDataSampleCrystalMM.parseString(
                strXmlStringDataSample)

        xsDataCrystal = self.getDataInput(
            "mxv1InputStrategy")[0].getCrystalRefined()
        if (xsDataCrystal is not None):
            self.xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Raddose is enabled only if the beam flux is set
        if (self.getDataInput("mxv1InputStrategy")
            [0].getExperimentalCondition().getBeam().getFlux() is None):
            strWarningMessage = EDMessage.WARNING_CANNOT_USE_PLUGIN_03 % (
                'EDPluginControlKappaStrategyv2_0.preProcess',
                self.strPluginRaddoseName, "Beam Flux not set")
            EDVerbose.warning(strWarningMessage)
            self.addWarningMessage(strWarningMessage)

        else:
            self.edPluginRaddose = self.loadPlugin(self.strPluginRaddoseName)

            if (self.edPluginRaddose is not None):
                EDVerbose.DEBUG(
                    "EDPluginControlKappaStrategyv2_0.preProcess: " +
                    self.strPluginRaddoseName + " Found... setting Data Input")

                strFileSymop = os.path.join(self.getSymopHome(), "symop.lib")

                xsDataStringSpaceGroup = self.getDataInput(
                    "mxv1InputStrategy")[0].getDiffractionPlan(
                    ).getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                strNumOperators = None
                strSpaceGroup = None
                if (xsDataStringSpaceGroup is not None):
                    strSpaceGroup = xsDataStringSpaceGroup.getValue()
                    EDVerbose.DEBUG(
                        "EDPluginControlKappaStrategyv2_0.preProcess: Forced Space Group Found: "
                        + strSpaceGroup)
                    try:
                        strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                            strSpaceGroup, strFileSymop)
                    except Exception, detail:
                        strErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                            'EDPluginControlKappaStrategyv2_0.preProcess',
                            "Problem to calculate Number of symmetry operators",
                            detail)
                        EDVerbose.error(strErrorMessage)
                        self.addErrorMessage(strErrorMessage)
                        raise RuntimeError, strErrorMessage
                # Space Group has NOT been forced
                else:
                    xsDataStringSpaceGroup = self.xsDataSampleCopy.getCrystal(
                    ).getSpaceGroup().getName()
                    if (xsDataStringSpaceGroup is not None):
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroup = self.xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getName().getValue()
                        EDVerbose.DEBUG(
                            "EDPluginControlKappaStrategyv2_0.preProcess: Space Group IT Name found by indexing: "
                            + strSpaceGroup)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                strSpaceGroup, strFileSymop)
                        except Exception, detail:
                            strErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                                'EDPluginControlKappaStrategyv2_0.preProcess',
                                "Problem to calculate Number of symmetry operators",
                                detail)
                            EDVerbose.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        dSpaceGroupITNumber = self.xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getITNumber().getValue()
                        EDVerbose.DEBUG(
                            "EDPluginControlKappaStrategyv2_0.preProcess: Space Group IT Number Found by indexing: %d"
                            % dSpaceGroupITNumber)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(
                                str(dSpaceGroupITNumber), strFileSymop)
                        except Exception, detail:
                            strErrorMessage = EDMessage.ERROR_EXECUTION_03 % (
                                'EDPluginControlKappaStrategyv2_0.preProcess',
                                "Problem to calculate Number of symmetry operators",
                                detail)
                            EDVerbose.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
class EDPluginControlStrategyv1_3(EDPluginControl):
    """
    The Plugin that controls the strategy step
    """
    def __init__(self):
        """
        """
        EDPluginControl.__init__(self)
        self.setXSDataInputClass(XSDataInputStrategy)

        self._strPluginRaddoseName = "EDPluginRaddosev10"
        self._edPluginRaddose = None
        self._edHandlerXSDataRaddose = None

        self._strPluginBestName = "EDPluginBestv1_3"
        self._edPluginBest = None
        self._edHandlerXSDataBest = None

        self._strPluginPlotGleName = "EDPluginExecPlotGlev1_1"
        self._edPluginPlotGle = None

        self._xsDataSampleCopy = None

        # For default chemical composition
        self._fAverageAminoAcidVolume = 135.49
        self._fAverageCrystalSolventContent = 0.47
        self._fAverageSulfurContentPerAminoacid = 0.05
        self._fAverageSulfurConcentration = 314

        # This varaible determines if Raddose should be executed or not
        self._bEstimateRadiationDamage = None

        # Raddose log file
        self.xsDataFileRaddoseLog = None

    def preProcess(self, _edObject=None):
        """
        Gets the Configuration Parameters, if found, overrides default parameters
        """
        EDPluginControl.preProcess(self, _edObject)
        self.DEBUG("EDPluginControlStrategyv1_3.preProcess...")
        self._edPluginRaddose = None

        xsDataSampleCrystalMM = self.getDataInput().getSample()

        if (xsDataSampleCrystalMM is None):
            self._xsDataSampleCopy = XSDataSampleCrystalMM()
        else:
            strXmlStringDataSample = xsDataSampleCrystalMM.marshal()
            self._xsDataSampleCopy = XSDataSampleCrystalMM.parseString(
                strXmlStringDataSample)

        xsDataCrystal = self.getDataInput().getCrystalRefined()
        if (xsDataCrystal is not None):
            self._xsDataSampleCopy.setCrystal(xsDataCrystal)

        # Load the Best plugin
        self._edPluginBest = self.loadPlugin(self._strPluginBestName)
        self._edPluginBest.setBaseDirectory(self.getWorkingDirectory())
        self._edPluginBest.setBaseName(self._strPluginBestName)

        # Load the plot gle plugin
        self._edPluginPlotGle = self.loadPlugin(self._strPluginPlotGleName)

        # Check if radiation damage estimation is required or not in the diffraction plan
        xsDataDiffractionPlan = self.getDataInput().getDiffractionPlan()
        if xsDataDiffractionPlan is not None:
            if xsDataDiffractionPlan.getEstimateRadiationDamage():
                if xsDataDiffractionPlan.getEstimateRadiationDamage().getValue(
                ):
                    # Yes, is requested
                    self._bEstimateRadiationDamage = True
                else:
                    # No, is explicitly not requested
                    self._bEstimateRadiationDamage = False
            elif xsDataDiffractionPlan.getStrategyOption() is not None:
                if xsDataDiffractionPlan.getStrategyOption().getValue().find(
                        "-DamPar") != -1:
                    # The "-DamPar" option requires estimation of radiation damage
                    self._bEstimateRadiationDamage = True

        # Check if we know what to do with radiation damage
        if self._bEstimateRadiationDamage is None:
            # "Force" the estimation of radiation damage if the flux is present
            if self.getDataInput().getExperimentalCondition().getBeam(
            ).getFlux() is None:
                strWarningMessage = "EDPluginControlStrategyv1_3: Missing flux input - cannot estimate radiation damage."
                self.WARNING(strWarningMessage)
                self.addWarningMessage(strWarningMessage)
                self._bEstimateRadiationDamage = False
            else:
                self._bEstimateRadiationDamage = True

        if self._bEstimateRadiationDamage:
            if self.getDataInput().getExperimentalCondition().getBeam(
            ).getFlux() is None:
                strErrorMessage = "EDPluginControlStrategyv1_3: Missing flux input. Cannot estimate radiation damage"
                self.ERROR(strErrorMessage)
                self.addErrorMessage(strErrorMessage)
                self.setFailure()

        if not self.isFailure():

            self._edPluginRaddose = self.loadPlugin(self._strPluginRaddoseName)

            if (self._edPluginRaddose is not None):
                self.DEBUG("EDPluginControlStrategyv1_3.preProcess: " +
                           self._strPluginRaddoseName +
                           " Found... setting Data Input")

                xsDataStringSpaceGroup = self.getDataInput(
                ).getDiffractionPlan().getForcedSpaceGroup()
                # Space Group has been forced
                # Prepare chemical composition calculation with the forced Space Group (Space Group Name)
                bSpaceGroupForced = False
                if (xsDataStringSpaceGroup is not None):
                    strSpaceGroup = xsDataStringSpaceGroup.getValue().upper(
                    ).replace(" ", "")
                    if strSpaceGroup != "":
                        self.DEBUG(
                            "EDPluginControlStrategyv1_3.preProcess: Forced Space Group Found: "
                            + strSpaceGroup)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                strSpaceGroup)
                            bSpaceGroupForced = True
                        except Exception, detail:
                            strErrorMessage = "EDPluginControlStrategyv1_3: Problem to calculate Number of symmetry operators: {0}".format(
                                detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
                if not bSpaceGroupForced:
                    # Space Group has NOT been forced
                    xsDataStringSpaceGroup = self._xsDataSampleCopy.getCrystal(
                    ).getSpaceGroup().getName()
                    if (xsDataStringSpaceGroup is not None):
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group Name)
                        strSpaceGroupName = self._xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getName().getValue()
                        self.DEBUG(
                            "EDPluginControlStrategyv1_3.preProcess: Space Group IT Name found by indexing: "
                            + strSpaceGroupName)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                strSpaceGroupName)
                        except Exception, detail:
                            strErrorMessage = "EDPluginControlStrategyv1_3: Problem to calculate Number of symmetry operators: {0}".format(
                                detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage
                    else:
                        # Prepare chemical composition calculation with the Space Group calculated by indexing (Space Group IT number)
                        iSpaceGroupITNumber = self._xsDataSampleCopy.getCrystal(
                        ).getSpaceGroup().getITNumber().getValue()
                        self.DEBUG(
                            "EDPluginControlStrategyv1_3.preProcess: Space Group IT Number Found by indexing: %d"
                            % iSpaceGroupITNumber)
                        try:
                            strNumOperators = EDUtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(
                                str(iSpaceGroupITNumber))
                        except Exception, detail:
                            strErrorMessage = "EDPluginControlStrategyv1_3: Problem to calculate Number of symmetry operators: {0}".format(
                                detail)
                            self.error(strErrorMessage)
                            self.addErrorMessage(strErrorMessage)
                            raise RuntimeError, strErrorMessage

                if (strNumOperators is not None):
                    iNumOperators = int(strNumOperators)
                else:
                    strErrorMessage = "EDPluginControlStrategyv1_3: No symmetry operators found for Space Group: {0}".format(
                        strNumOperators)
                    self.error(strErrorMessage)
                    self.addErrorMessage(strErrorMessage)
                    raise RuntimeError, strErrorMessage

                xsDataChemicalComposition = self._xsDataSampleCopy.getChemicalComposition(
                )

                if (xsDataChemicalComposition is None):
                    # create a default chemical composition and assign it to the sample
                    xsDataDefaultChemicalComposition = self.getDefaultChemicalComposition(
                        self._xsDataSampleCopy, iNumOperators)
                    self._xsDataSampleCopy.setChemicalComposition(
                        xsDataDefaultChemicalComposition)
                else:
                    # Check for Sulfur atoms, if none, add native sulfur atoms
                    xsDataUpdatedChemicalComposition = self.updateChemicalComposition(
                        xsDataChemicalComposition)
                    self._xsDataSampleCopy.setChemicalComposition(
                        xsDataUpdatedChemicalComposition)

                # create Data Input for Raddose
                from EDHandlerXSDataRaddosev10 import EDHandlerXSDataRaddosev10
                self._edHandlerXSDataRaddose = EDHandlerXSDataRaddosev10()
                xsDataBeam = self.getDataInput().getExperimentalCondition(
                ).getBeam()

                # Calculate number of images (MXSUP-1616):
                iNumberOfImages = None
                xsDataCollection = self.dataInput.dataCollection
                if xsDataCollection is not None:
                    iNumberOfImages = 0
                    for xsDataSubWedge in xsDataCollection.subWedge:
                        xsDataGoniostat = xsDataSubWedge.experimentalCondition.goniostat
                        iOscStart = xsDataGoniostat.rotationAxisStart.value
                        iOscEnd = xsDataGoniostat.rotationAxisEnd.value
                        iOscWidth = xsDataGoniostat.oscillationWidth.value
                        iNumberOfImages += int(
                            round((iOscEnd - iOscStart) / iOscWidth, 0))
                if iNumberOfImages is None:
                    iNumberOfImages = 1
                    self.WARNING(
                        "No goniostat information, number of images for RADDOSE set to 1"
                    )

                xsDataRaddoseInput = self._edHandlerXSDataRaddose.getXSDataRaddoseInput(
                    xsDataBeam, self._xsDataSampleCopy, iNumOperators,
                    iNumberOfImages)
                if xsDataRaddoseInput is not None:
                    self._edPluginRaddose.setDataInput(xsDataRaddoseInput)
                    self._edPluginRaddose.setBaseDirectory(
                        self.getWorkingDirectory())
                    self._edPluginRaddose.setBaseName(
                        self._strPluginRaddoseName)