def _calculate_area_density_from_density(self):
     """Calculates area density (atom/cm^2) using number density and thickness."""
     if self._density_type == 'Mass Density':
         builder = MaterialBuilder().setFormula(self._chemical_formula)
         mat = builder.setMassDensity(self._density).build()
         self._density = mat.numberDensity
     self._area_density = self._density * self._thickness
 def _set_material(self, ws_name, chemical_formula, density_type, density):
     """
     Sets the sample material for a given workspace
     @param ws_name              :: name of the workspace to set sample material for
     @param chemical_formula     :: Chemical formula of sample
     @param density_type         :: 'Mass Density' or 'Number Density'
     @param density              :: Density of sample
     @return pointer to the workspace with sample material set
             AND
             number density of the sample material
     """
     set_material_alg = self.createChildAlgorithm('SetSampleMaterial')
     if density_type == 'Mass Density':
         set_material_alg.setProperty('SampleMassDensity', density)
         builder = MaterialBuilder()
         mat = builder.setFormula(chemical_formula).setMassDensity(
             density).build()
         number_density = mat.numberDensity
     else:
         number_density = density
     set_material_alg.setProperty('InputWorkspace', ws_name)
     set_material_alg.setProperty('ChemicalFormula', chemical_formula)
     set_material_alg.setProperty('SampleNumberDensity', number_density)
     set_material_alg.execute()
     return number_density
 def _set_material(self, ws_name, chemical_formula, density_type, density):
     """
     Sets the sample material for a given workspace
     @param ws_name              :: name of the workspace to set sample material for
     @param chemical_formula     :: Chemical formula of sample
     @param density_type         :: 'Mass Density' or 'Number Density'
     @param density              :: Density of sample
     @return pointer to the workspace with sample material set
             AND
             number density of the sample material
     """
     set_material_alg = self.createChildAlgorithm('SetSampleMaterial')
     if density_type == 'Mass Density':
         set_material_alg.setProperty('SampleMassDensity', density)
         builder = MaterialBuilder()
         mat = builder.setFormula(chemical_formula).setMassDensity(density).build()
         number_density = mat.numberDensity
     else:
         number_density = density
     set_material_alg.setProperty('InputWorkspace', ws_name)
     set_material_alg.setProperty('ChemicalFormula', chemical_formula)
     set_material_alg.setProperty('SampleNumberDensity', number_density)
     set_material_alg.execute()
     ws = set_material_alg.getProperty('InputWorkspace').value
     return ws, number_density
    def _sample(self):
        set_material_alg = self.createChildAlgorithm('SetSampleMaterial')
        logger.information('Sample chemical formula : %s ' % (self._sample_chemical_formula))
        if self._sample_density_type == 'Mass Density':
            logger.information('Sample Mass density : %f' % (self._sample_density))
            set_material_alg.setProperty('SampleMassDensity', self._sample_density)
            builder = MaterialBuilder()
            mat = builder.setFormula(self._sample_chemical_formula).setMassDensity(self._sample_density).build()
            self._sample_number_density = mat.numberDensity
            logger.information('Sample Number density : %f' % (self._sample_number_density))
        else:
            self._sample_number_density = self._sample_density
            logger.information('Sample Number density : %f' % (self._sample_number_density))
            set_material_alg.setProperty('SampleNumberDensity', self._sample_number_density)
        set_material_alg.setProperty('InputWorkspace', self._sample_ws_name)
        set_material_alg.setProperty('ChemicalFormula', self._sample_chemical_formula)
        set_material_alg.execute()
        sam_material = mtd[self._sample_ws_name].sample().getMaterial()
        # Sample cross section
        self._sigc = sam_material.cohScatterXSection()
        self._sigi = sam_material.incohScatterXSection()
        self._sigt = sam_material.totalScatterXSection()
        self._siga_in = sam_material.absorbXSection()
        self._siga = self._siga_in

        self._sigss = self._sofq*self._sigc + self._sigi    #q_dependent total scatt X-sect
        self._sigss = np.log(self._sigss)                   #interpolation later on
        self._sofq = np.log(self._sofq/self._sigt)          #S(Q) normalised
Example #5
0
def _create_profile_strs_and_mass_list(profile_flags):
    """
    Create a string suitable for the algorithms out of the mass profile flags
    and a list of mass values
    :param profile_flags: A list of dict objects for the mass profile flags
    :return: A tuple of list of masses, a string to pass to the algorithm and
             a dictionary containing a map from mass index to a symbol - where
             chemical formula was used to define a mass.
    """
    material_builder = MaterialBuilder()
    mass_values, profiles = [], []
    all_mass_values, all_profiles = [], []
    for idx, mass_prop in enumerate(profile_flags):
        function_name = ("function=%s," % mass_prop.pop('function'))
        function_props = [
            "{0}={1}".format(key, value) for key, value in mass_prop.items()
        ]
        function_props = ("%s,%s" % (function_name,
                                     (','.join(function_props))))

        mass_value = mass_prop.pop('value', None)
        if mass_value is None:
            symbol = mass_prop.pop('symbol', None)

            if symbol is None:
                raise RuntimeError(
                    'Invalid mass specified - ' + str(mass_prop) +
                    " - either 'value' or 'symbol' must be given.")

            try:
                if symbol == 'H':
                    mass = material_builder.setFormula(
                        symbol).build().relativeMolecularMass()
                    all_mass_values.append(mass)
                    all_profiles.append(function_props)
                    continue

                mass_value = material_builder.setFormula(
                    symbol).build().relativeMolecularMass()
            except BaseException as exc:
                raise RuntimeError('Error when parsing mass - ' +
                                   str(mass_prop) + ": " + "\n" + str(exc))

        all_mass_values.append(mass_value)
        mass_values.append(mass_value)
        all_profiles.append(function_props)
        profiles.append(function_props)

    profiles = ";".join(profiles)
    all_profiles = ";".join(all_profiles)
    return mass_values, profiles, all_mass_values, all_profiles
 def test_build_material(self):
     builder = MaterialBuilder()
     material = builder.setName('Bizarre oxide').setFormula('Al2 O3').setNumberDensity(0.23).build()
     self.assertEqual(material.name(), 'Bizarre oxide')
     formula = material.chemicalFormula()
     self.assertEqual(len(formula), 2)
     atoms = formula[0]
     multiplicities = formula[1]
     self.assertEqual(len(atoms), 2)
     self.assertEqual(atoms[0].symbol, 'Al')
     self.assertEqual(atoms[1].symbol, 'O')
     self.assertEqual(len(multiplicities), 2)
     self.assertEqual(multiplicities[0], 2)
     self.assertEqual(multiplicities[1], 3)
     self.assertEqual(material.numberDensity, 0.23)
 def test_build_material(self):
     builder = MaterialBuilder()
     material = builder.setName('Bizarre oxide').setFormula(
         'Al2 O3').setNumberDensity(0.23).build()
     self.assertEqual(material.name(), 'Bizarre oxide')
     formula = material.chemicalFormula()
     self.assertEqual(len(formula), 2)
     atoms = formula[0]
     multiplicities = formula[1]
     self.assertEqual(len(atoms), 2)
     self.assertEqual(atoms[0].symbol, 'Al')
     self.assertEqual(atoms[1].symbol, 'O')
     self.assertEqual(len(multiplicities), 2)
     self.assertEqual(multiplicities[0], 2)
     self.assertEqual(multiplicities[1], 3)
     self.assertEqual(material.numberDensity, 0.23)
Example #8
0
 def _calculate_packing_fraction(self):
     try:
         self._content.packingfraction_edit.setText('{:.5f}'.format(MaterialBuilder().setFormula(
             self._content.sampleformula_edit.text()).setNumberDensity(
                 float(self._content.numberdensity_edit.text())).setMassDensity(
                     float(self._content.massdensity_edit.text())).build().packingFraction))
     except ValueError:  # boost.python.ArgumentError are not catchable
         self._content.packingfraction_edit.setText(str(1))
Example #9
0
def _create_profile_strs_and_mass_list(profile_flags):
    """
    Create a string suitable for the algorithms out of the mass profile flags
    and a list of mass values
    :param profile_flags: A list of dict objects for the mass profile flags
    :return: A tuple of list of masses, a string to pass to the algorithm and
             a dictionary containing a map from mass index to a symbol - where
             chemical formula was used to define a mass.
    """
    material_builder = MaterialBuilder()
    mass_values, profiles = [], []
    all_mass_values, all_profiles = [], []
    for idx, mass_prop in enumerate(profile_flags):
        function_name = ("function=%s," % mass_prop.pop('function'))
        function_props = ["{0}={1}".format(key, value) for key, value in mass_prop.items()]
        function_props = ("%s,%s" % (function_name, (','.join(function_props))))

        mass_value = mass_prop.pop('value', None)
        if mass_value is None:
            symbol = mass_prop.pop('symbol', None)

            if symbol is None:
                raise RuntimeError('Invalid mass specified - ' + str(mass_prop)
                                   + " - either 'value' or 'symbol' must be given.")

            try:
                if symbol == 'H':
                    mass = material_builder.setFormula(symbol).build().relativeMolecularMass()
                    all_mass_values.append(mass)
                    all_profiles.append(function_props)
                    continue

                mass_value = material_builder.setFormula(symbol).build().relativeMolecularMass()
            except BaseException as exc:
                raise RuntimeError('Error when parsing mass - ' + str(mass_prop) + ": "
                                   + "\n" + str(exc))

        all_mass_values.append(mass_value)
        mass_values.append(mass_value)
        all_profiles.append(function_props)
        profiles.append(function_props)

    profiles = ";".join(profiles)
    all_profiles = ";".join(all_profiles)
    return mass_values, profiles, all_mass_values, all_profiles
 def test_number_density_units(self):
     builder = MaterialBuilder()
     builder.setName('Bizarre oxide').setFormula('Al2 O3').setNumberDensity(
         0.23)
     builder.setNumberDensityUnit(NumberDensityUnit.FormulaUnits)
     material = builder.build()
     self.assertEqual(material.numberDensity, 0.23 * (2. + 3.))
Example #11
0
 def test_number_density_units(self):
     builder = MaterialBuilder()
     builder.setName(NAME).setFormula(FORMULA).setNumberDensity(NUMBER_DENSITY)
     builder.setNumberDensityUnit(NumberDensityUnit.FormulaUnits)
     material = builder.build()
     self.assertEqual(material.numberDensity, NUMBER_DENSITY * (2. + 3.))
     self.assertEqual(material.numberDensityEffective, NUMBER_DENSITY * (2. + 3.))
     self.assertEqual(material.packingFraction, 1.)
Example #12
0
 def _validate_formula(self):
     try:
         if self._content.sampleformula_edit.text().strip() != '':
             MaterialBuilder().setFormula(self._content.sampleformula_edit.text().strip())
         self._content.sampleformula_edit.setToolTip("")
         self._content.sampleformula_edit.setStyleSheet("QLineEdit{}")
     except ValueError as e:
         self._content.sampleformula_edit.setToolTip(
             str(e).replace("MaterialBuilder::setFormula() - ", ""))
         self._content.sampleformula_edit.setStyleSheet("QLineEdit{background:salmon;}")
Example #13
0
    def test_build_material(self):
        builder = MaterialBuilder()
        material = builder.setName(NAME).setFormula(FORMULA).setNumberDensity(NUMBER_DENSITY).build()
        self.assertEqual(material.name(), NAME)
        self.assertEqual(material.numberDensity, NUMBER_DENSITY)
        self.assertEqual(material.numberDensityEffective, NUMBER_DENSITY)
        self.assertEqual(material.packingFraction, 1.)

        formula = material.chemicalFormula()
        self.assertEqual(len(formula), 2)
        atoms = formula[0]
        multiplicities = formula[1]
        self.assertEqual(len(atoms), 2)
        self.assertEqual(atoms[0].symbol, 'Al')
        self.assertEqual(atoms[1].symbol, 'O')
        self.assertEqual(len(multiplicities), 2)
        self.assertEqual(multiplicities[0], 2)
        self.assertEqual(multiplicities[1], 3)
        self.assertEqual(material.numberDensity, NUMBER_DENSITY)
Example #14
0
def fit_tof(runs, flags, iterations=1, convergence_threshold=None):
    # Retrieve vesuvio input data
    vesuvio_loader = VesuvioLoadHelper(
        flags['diff_mode'], flags['fit_mode'], flags['ip_file'],
        flags.get('bin_parameters', None),
        _extract_bool_from_flags('load_log_files', flags))
    vesuvio_input = VesuvioTOFFitInput(runs, flags.get('container_runs', None),
                                       flags.get('spectra', None),
                                       vesuvio_loader)

    if flags.get('ms_enabled', True):
        hydrogen_constraints = flags['ms_flags'].pop("HydrogenConstraints",
                                                     None)
        ms_helper = VesuvioMSHelper(**flags['ms_flags'])

        if hydrogen_constraints is not None:
            ms_helper.add_hydrogen_constraints(hydrogen_constraints)
    else:
        ms_helper = VesuvioMSHelper()

    intensity_string = _create_intensity_constraint_str(
        flags['intensity_constraints'])

    fit_helper = VesuvioTOFFitHelper(
        _create_background_str(flags.get('background', None)),
        intensity_string, _create_user_defined_ties_str(flags['masses']),
        flags.get('max_fit_iterations', 5000), flags['fit_minimizer'])

    corrections_helper = VesuvioCorrectionsHelper(
        _extract_bool_from_flags('gamma_correct', flags, False),
        _extract_bool_from_flags('ms_enabled', flags),
        flags.get('fixed_gamma_scaling', 0.0),
        flags.get('fixed_container_scaling', 0.0), intensity_string)

    create_mass_profile = _mass_profile_generator(MaterialBuilder())
    profiles = [create_mass_profile(profile) for profile in flags['masses']]
    mass_profile_collection = MassProfileCollection2D.from_collection(
        MassProfileCollection(profiles), vesuvio_input.spectra_number)

    fit_namer = VesuvioFitNamer.from_vesuvio_input(vesuvio_input,
                                                   flags['fit_mode'])

    vesuvio_fit_routine = VesuvioTOFFitRoutine(ms_helper, fit_helper,
                                               corrections_helper,
                                               mass_profile_collection,
                                               fit_namer)
    vesuvio_output, result, exit_iteration = vesuvio_fit_routine(
        vesuvio_input, iterations, convergence_threshold,
        _extract_bool_from_flags('output_verbose_corrections', flags, False),
        _extract_bool_from_flags('calculate_caad', flags, False))
    result = result if len(result) > 1 else result[0]
    return result, vesuvio_output.fit_parameters_workspace, vesuvio_output.chi2_values, exit_iteration
    def PyExec(self):
        from IndirectCommon import getEfixed

        self._setup()

        # Set up progress reporting
        n_prog_reports = 2
        if self._can_ws_name is not None:
            n_prog_reports += 1
        prog = Progress(self, 0.0, 1.0, n_prog_reports)

        efixed = getEfixed(self._sample_ws_name)

        sample_wave_ws = '__sam_wave'
        ConvertUnits(InputWorkspace=self._sample_ws_name,
                     OutputWorkspace=sample_wave_ws,
                     Target='Wavelength',
                     EMode='Indirect',
                     EFixed=efixed,
                     EnableLogging=False)

        sample_thickness = self._sample_outer_radius - self._sample_inner_radius
        logger.information('Sample thickness: ' + str(sample_thickness))

        prog.report('Calculating sample corrections')
        if self._sample_density_type == 'Mass Density':
            builder = MaterialBuilder()
            mat = builder.setFormula(
                self._sample_chemical_formula).setMassDensity(
                    self._sample_density).build()
            self._sample_density = mat.numberDensity
        SetSampleMaterial(sample_wave_ws,
                          ChemicalFormula=self._sample_chemical_formula,
                          SampleNumberDensity=self._sample_density)
        AnnularRingAbsorption(
            InputWorkspace=sample_wave_ws,
            OutputWorkspace=self._ass_ws,
            SampleHeight=3.0,
            SampleThickness=sample_thickness,
            CanInnerRadius=self._can_inner_radius,
            CanOuterRadius=self._can_outer_radius,
            SampleChemicalFormula=self._sample_chemical_formula,
            SampleNumberDensity=self._sample_density,
            NumberOfWavelengthPoints=10,
            EventsPerPoint=self._events)

        group = self._ass_ws

        if self._can_ws_name is not None:
            can1_wave_ws = '__can1_wave'
            can2_wave_ws = '__can2_wave'
            ConvertUnits(InputWorkspace=self._can_ws_name,
                         OutputWorkspace=can1_wave_ws,
                         Target='Wavelength',
                         EMode='Indirect',
                         EFixed=efixed,
                         EnableLogging=False)
            if self._can_scale != 1.0:
                logger.information('Scaling container by: ' +
                                   str(self._can_scale))
                Scale(InputWorkspace=can1_wave_ws,
                      OutputWorkspace=can1_wave_ws,
                      Factor=self._can_scale,
                      Operation='Multiply')
            CloneWorkspace(InputWorkspace=can1_wave_ws,
                           OutputWorkspace=can2_wave_ws,
                           EnableLogging=False)

            can_thickness_1 = self._sample_inner_radius - self._can_inner_radius
            can_thickness_2 = self._can_outer_radius - self._sample_outer_radius
            logger.information('Container thickness: %f & %f' %
                               (can_thickness_1, can_thickness_2))

            if self._use_can_corrections:
                prog.report('Calculating container corrections')
                Divide(LHSWorkspace=sample_wave_ws,
                       RHSWorkspace=self._ass_ws,
                       OutputWorkspace=sample_wave_ws)

                if self._can_density_type == 'Mass Density':
                    builder = MaterialBuilder()
                    mat = builder.setFormula(
                        self._can_chemical_formula).setMassDensity(
                            self._can_density).build()
                    self._can_density = mat.numberDensity
                SetSampleMaterial(can1_wave_ws,
                                  ChemicalFormula=self._can_chemical_formula,
                                  SampleNumberDensity=self._can_density)

                AnnularRingAbsorption(
                    InputWorkspace=can1_wave_ws,
                    OutputWorkspace='__Acc1',
                    SampleHeight=3.0,
                    SampleThickness=can_thickness_1,
                    CanInnerRadius=self._can_inner_radius,
                    CanOuterRadius=self._sample_outer_radius,
                    SampleChemicalFormula=self._can_chemical_formula,
                    SampleNumberDensity=self._can_density,
                    NumberOfWavelengthPoints=10,
                    EventsPerPoint=self._events)

                SetSampleMaterial(can2_wave_ws,
                                  ChemicalFormula=self._can_chemical_formula,
                                  SampleNumberDensity=self._can_density)
                AnnularRingAbsorption(
                    InputWorkspace=can2_wave_ws,
                    OutputWorkspace='__Acc2',
                    SampleHeight=3.0,
                    SampleThickness=can_thickness_2,
                    CanInnerRadius=self._sample_inner_radius,
                    CanOuterRadius=self._can_outer_radius,
                    SampleChemicalFormula=self._can_chemical_formula,
                    SampleNumberDensity=self._can_density,
                    NumberOfWavelengthPoints=10,
                    EventsPerPoint=self._events)

                Multiply(LHSWorkspace='__Acc1',
                         RHSWorkspace='__Acc2',
                         OutputWorkspace=self._acc_ws,
                         EnableLogging=False)
                DeleteWorkspace('__Acc1', EnableLogging=False)
                DeleteWorkspace('__Acc2', EnableLogging=False)

                Divide(LHSWorkspace=can1_wave_ws,
                       RHSWorkspace=self._acc_ws,
                       OutputWorkspace=can1_wave_ws)
                Minus(LHSWorkspace=sample_wave_ws,
                      RHSWorkspace=can1_wave_ws,
                      OutputWorkspace=sample_wave_ws)
                group += ',' + self._acc_ws

            else:
                prog.report('Calculating can scaling')
                Minus(LHSWorkspace=sample_wave_ws,
                      RHSWorkspace=can1_wave_ws,
                      OutputWorkspace=sample_wave_ws)
                Divide(LHSWorkspace=sample_wave_ws,
                       RHSWorkspace=self._ass_ws,
                       OutputWorkspace=sample_wave_ws)

            DeleteWorkspace(can1_wave_ws, EnableLogging=False)
            DeleteWorkspace(can2_wave_ws, EnableLogging=False)

        else:
            Divide(LHSWorkspace=sample_wave_ws,
                   RHSWorkspace=self._ass_ws,
                   OutputWorkspace=sample_wave_ws)

        ConvertUnits(InputWorkspace=sample_wave_ws,
                     OutputWorkspace=self._output_ws,
                     Target='DeltaE',
                     EMode='Indirect',
                     EFixed=efixed,
                     EnableLogging=False)
        DeleteWorkspace(sample_wave_ws, EnableLogging=False)

        prog.report('Recording sample logs')
        sample_log_workspaces = [self._output_ws, self._ass_ws]
        sample_logs = [('sample_shape', 'annulus'),
                       ('sample_filename', self._sample_ws_name),
                       ('sample_inner', self._sample_inner_radius),
                       ('sample_outer', self._sample_outer_radius),
                       ('can_inner', self._can_inner_radius),
                       ('can_outer', self._can_outer_radius)]

        if self._can_ws_name is not None:
            sample_logs.append(('container_filename', self._can_ws_name))
            sample_logs.append(('container_scale', self._can_scale))
            if self._use_can_corrections:
                sample_log_workspaces.append(self._acc_ws)
                sample_logs.append(('container_thickness_1', can_thickness_1))
                sample_logs.append(('container_thickness_2', can_thickness_2))

        log_names = [item[0] for item in sample_logs]
        log_values = [item[1] for item in sample_logs]

        for ws_name in sample_log_workspaces:
            AddSampleLogMultiple(Workspace=ws_name,
                                 LogNames=log_names,
                                 LogValues=log_values,
                                 EnableLogging=False)

        self.setProperty('OutputWorkspace', self._output_ws)

        # Output the Ass workspace if it is wanted, delete if not
        if self._abs_ws == '':
            DeleteWorkspace(self._ass_ws, EnableLogging=False)
            if self._can_ws_name is not None and self._use_can_corrections:
                DeleteWorkspace(self._acc_ws, EnableLogging=False)
        else:
            GroupWorkspaces(InputWorkspaces=group,
                            OutputWorkspace=self._abs_ws,
                            EnableLogging=False)
            self.setProperty('CorrectionsWorkspace', self._abs_ws)
    def PyExec(self):
        from IndirectCommon import getEfixed

        self._setup()

        # Set up progress reporting
        n_prog_reports = 2
        if self._can_ws_name is not None:
            n_prog_reports += 1
        prog = Progress(self, 0.0, 1.0, n_prog_reports)

        efixed = getEfixed(self._sample_ws)

        sample_wave_ws = "__sam_wave"
        ConvertUnits(
            InputWorkspace=self._sample_ws,
            OutputWorkspace=sample_wave_ws,
            Target="Wavelength",
            EMode="Indirect",
            EFixed=efixed,
            EnableLogging=False,
        )

        if self._sample_density_type == "Mass Density":
            builder = MaterialBuilder()
            mat = builder.setFormula(self._sample_chemical_formula).setMassDensity(self._sample_density).build()
            self._sample_density = mat.numberDensity
        SetSampleMaterial(
            sample_wave_ws, ChemicalFormula=self._sample_chemical_formula, SampleNumberDensity=self._sample_density
        )

        prog.report("Calculating sample corrections")
        FlatPlateAbsorption(
            InputWorkspace=sample_wave_ws,
            OutputWorkspace=self._ass_ws,
            SampleHeight=self._sample_height,
            SampleWidth=self._sample_width,
            SampleThickness=self._sample_thickness,
            ElementSize=self._element_size,
            EMode="Indirect",
            EFixed=efixed,
            NumberOfWavelengthPoints=10,
        )

        group = self._ass_ws

        if self._can_ws_name is not None:
            can_wave_ws = "__can_wave"
            ConvertUnits(
                InputWorkspace=self._can_ws_name,
                OutputWorkspace=can_wave_ws,
                Target="Wavelength",
                EMode="Indirect",
                EFixed=efixed,
                EnableLogging=False,
            )
            if self._can_scale != 1.0:
                logger.information("Scaling container by: " + str(self._can_scale))
                Scale(
                    InputWorkspace=can_wave_ws,
                    OutputWorkspace=can_wave_ws,
                    Factor=self._can_scale,
                    Operation="Multiply",
                )

            if self._use_can_corrections:
                prog.report("Calculating container corrections")
                Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)

                if self._sample_density_type == "Mass Density":
                    builder = MaterialBuilder()
                    mat = builder.setFormula(self._can_chemical_formula).setMassDensity(self._can_density).build()
                    self._can_density = mat.numberDensity
                SetSampleMaterial(
                    can_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density
                )

                FlatPlateAbsorption(
                    InputWorkspace=can_wave_ws,
                    OutputWorkspace=self._acc_ws,
                    SampleHeight=self._sample_height,
                    SampleWidth=self._sample_width,
                    SampleThickness=self._can_front_thickness + self._can_back_thickness,
                    ElementSize=self._element_size,
                    EMode="Indirect",
                    EFixed=efixed,
                    NumberOfWavelengthPoints=10,
                )

                Divide(LHSWorkspace=can_wave_ws, RHSWorkspace=self._acc_ws, OutputWorkspace=can_wave_ws)
                Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can_wave_ws, OutputWorkspace=sample_wave_ws)
                group += "," + self._acc_ws

            else:
                prog.report("Calculating container scaling")
                Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can_wave_ws, OutputWorkspace=sample_wave_ws)
                Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)

            DeleteWorkspace(can_wave_ws, EnableLogging=False)

        else:
            Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)

        ConvertUnits(
            InputWorkspace=sample_wave_ws,
            OutputWorkspace=self._output_ws,
            Target="DeltaE",
            EMode="Indirect",
            EFixed=efixed,
            EnableLogging=False,
        )
        DeleteWorkspace(sample_wave_ws, EnableLogging=False)

        prog.report("Recording sample logs")
        sample_log_workspaces = [self._output_ws, self._ass_ws]
        sample_logs = [
            ("sample_shape", "flatplate"),
            ("sample_filename", self._sample_ws),
            ("sample_height", self._sample_height),
            ("sample_width", self._sample_width),
            ("sample_thickness", self._sample_thickness),
            ("element_size", self._element_size),
        ]

        if self._can_ws_name is not None:
            sample_logs.append(("container_filename", self._can_ws_name))
            sample_logs.append(("container_scale", self._can_scale))
            if self._use_can_corrections:
                sample_log_workspaces.append(self._acc_ws)
                sample_logs.append(("container_front_thickness", self._can_front_thickness))
                sample_logs.append(("container_back_thickness", self._can_back_thickness))

        log_names = [item[0] for item in sample_logs]
        log_values = [item[1] for item in sample_logs]

        for ws_name in sample_log_workspaces:
            AddSampleLogMultiple(Workspace=ws_name, LogNames=log_names, LogValues=log_values, EnableLogging=False)

        self.setProperty("OutputWorkspace", self._output_ws)

        # Output the Ass workspace if it is wanted, delete if not
        if self._abs_ws == "":
            DeleteWorkspace(self._ass_ws, EnableLogging=False)
            if self._can_ws_name is not None and self._use_can_corrections:
                DeleteWorkspace(self._acc_ws, EnableLogging=False)
        else:
            GroupWorkspaces(InputWorkspaces=group, OutputWorkspace=self._abs_ws, EnableLogging=False)
            self.setProperty("CorrectionsWorkspace", self._abs_ws)
 def test_number_density_units(self):
     builder = MaterialBuilder()
     builder.setName('Bizarre oxide').setFormula('Al2 O3').setNumberDensity(0.23)
     builder.setNumberDensityUnit(NumberDensityUnit.FormulaUnits)
     material = builder.build()
     self.assertEqual(material.numberDensity, 0.23 * (2. + 3.))
    def PyExec(self):
        from IndirectCommon import getEfixed

        self._setup()

        # Set up progress reporting
        n_prog_reports = 2
        if self._can_ws_name is not None:
            n_prog_reports += 1
        prog = Progress(self, 0.0, 1.0, n_prog_reports)

        efixed = getEfixed(self._sample_ws_name)

        sample_wave_ws = '__sam_wave'
        ConvertUnits(InputWorkspace=self._sample_ws_name, OutputWorkspace=sample_wave_ws,
                     Target='Wavelength', EMode='Indirect', EFixed=efixed, EnableLogging=False)

        sample_thickness = self._sample_outer_radius - self._sample_inner_radius
        logger.information('Sample thickness: ' + str(sample_thickness))

        prog.report('Calculating sample corrections')
        if self._sample_density_type == 'Mass Density':
            builder = MaterialBuilder()
            mat = builder.setFormula(self._sample_chemical_formula).setMassDensity(self._sample_density).build()
            self._sample_density = mat.numberDensity
        SetSampleMaterial(sample_wave_ws, ChemicalFormula=self._sample_chemical_formula, SampleNumberDensity=self._sample_density)
        AnnularRingAbsorption(InputWorkspace=sample_wave_ws,
                              OutputWorkspace=self._ass_ws,
                              SampleHeight=3.0,
                              SampleThickness=sample_thickness,
                              CanInnerRadius=self._can_inner_radius,
                              CanOuterRadius=self._can_outer_radius,
                              SampleChemicalFormula=self._sample_chemical_formula,
                              SampleNumberDensity=self._sample_density,
                              NumberOfWavelengthPoints=10,
                              EventsPerPoint=self._events)

        group = self._ass_ws

        if self._can_ws_name is not None:
            can1_wave_ws = '__can1_wave'
            can2_wave_ws = '__can2_wave'
            ConvertUnits(InputWorkspace=self._can_ws_name, OutputWorkspace=can1_wave_ws,
                         Target='Wavelength', EMode='Indirect', EFixed=efixed, EnableLogging=False)
            if self._can_scale != 1.0:
                logger.information('Scaling container by: ' + str(self._can_scale))
                Scale(InputWorkspace=can1_wave_ws, OutputWorkspace=can1_wave_ws, Factor=self._can_scale, Operation='Multiply')
            CloneWorkspace(InputWorkspace=can1_wave_ws, OutputWorkspace=can2_wave_ws, EnableLogging=False)

            can_thickness_1 = self._sample_inner_radius - self._can_inner_radius
            can_thickness_2 = self._can_outer_radius - self._sample_outer_radius
            logger.information('Container thickness: %f & %f' % (can_thickness_1, can_thickness_2))

            if self._use_can_corrections:
                prog.report('Calculating container corrections')
                Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)

                if self._can_density_type == 'Mass Density':
                    builder = MaterialBuilder()
                    mat = builder.setFormula(self._can_chemical_formula).setMassDensity(self._can_density).build()
                    self._can_density = mat.numberDensity
                SetSampleMaterial(can1_wave_ws, ChemicalFormula=self._can_chemical_formula,
                                  SampleNumberDensity=self._can_density)

                AnnularRingAbsorption(InputWorkspace=can1_wave_ws,
                                      OutputWorkspace='__Acc1',
                                      SampleHeight=3.0,
                                      SampleThickness=can_thickness_1,
                                      CanInnerRadius=self._can_inner_radius,
                                      CanOuterRadius=self._sample_outer_radius,
                                      SampleChemicalFormula=self._can_chemical_formula,
                                      SampleNumberDensity=self._can_density,
                                      NumberOfWavelengthPoints=10,
                                      EventsPerPoint=self._events)

                SetSampleMaterial(can2_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density)
                AnnularRingAbsorption(InputWorkspace=can2_wave_ws,
                                      OutputWorkspace='__Acc2',
                                      SampleHeight=3.0,
                                      SampleThickness=can_thickness_2,
                                      CanInnerRadius=self._sample_inner_radius,
                                      CanOuterRadius=self._can_outer_radius,
                                      SampleChemicalFormula=self._can_chemical_formula,
                                      SampleNumberDensity=self._can_density,
                                      NumberOfWavelengthPoints=10,
                                      EventsPerPoint=self._events)

                Multiply(LHSWorkspace='__Acc1', RHSWorkspace='__Acc2', OutputWorkspace=self._acc_ws, EnableLogging=False)
                DeleteWorkspace('__Acc1', EnableLogging=False)
                DeleteWorkspace('__Acc2', EnableLogging=False)

                Divide(LHSWorkspace=can1_wave_ws, RHSWorkspace=self._acc_ws, OutputWorkspace=can1_wave_ws)
                Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can1_wave_ws, OutputWorkspace=sample_wave_ws)
                group += ',' + self._acc_ws

            else:
                prog.report('Calculating can scaling')
                Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can1_wave_ws, OutputWorkspace=sample_wave_ws)
                Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)

            DeleteWorkspace(can1_wave_ws, EnableLogging=False)
            DeleteWorkspace(can2_wave_ws, EnableLogging=False)

        else:
            Divide(LHSWorkspace=sample_wave_ws,
                   RHSWorkspace=self._ass_ws,
                   OutputWorkspace=sample_wave_ws)

        ConvertUnits(InputWorkspace=sample_wave_ws,
                     OutputWorkspace=self._output_ws,
                     Target='DeltaE',
                     EMode='Indirect',
                     EFixed=efixed,
                     EnableLogging=False)
        DeleteWorkspace(sample_wave_ws, EnableLogging=False)

        prog.report('Recording sample logs')
        sample_log_workspaces = [self._output_ws, self._ass_ws]
        sample_logs = [('sample_shape', 'annulus'),
                       ('sample_filename', self._sample_ws_name),
                       ('sample_inner', self._sample_inner_radius),
                       ('sample_outer', self._sample_outer_radius),
                       ('can_inner', self._can_inner_radius),
                       ('can_outer', self._can_outer_radius)]

        if self._can_ws_name is not None:
            sample_logs.append(('container_filename', self._can_ws_name))
            sample_logs.append(('container_scale', self._can_scale))
            if self._use_can_corrections:
                sample_log_workspaces.append(self._acc_ws)
                sample_logs.append(('container_thickness_1', can_thickness_1))
                sample_logs.append(('container_thickness_2', can_thickness_2))

        log_names = [item[0] for item in sample_logs]
        log_values = [item[1] for item in sample_logs]

        for ws_name in sample_log_workspaces:
            AddSampleLogMultiple(Workspace=ws_name, LogNames=log_names, LogValues=log_values, EnableLogging=False)

        self.setProperty('OutputWorkspace', self._output_ws)

        # Output the Ass workspace if it is wanted, delete if not
        if self._abs_ws == '':
            DeleteWorkspace(self._ass_ws, EnableLogging=False)
            if self._can_ws_name is not None and self._use_can_corrections:
                DeleteWorkspace(self._acc_ws, EnableLogging=False)
        else:
            GroupWorkspaces(InputWorkspaces=group, OutputWorkspace=self._abs_ws, EnableLogging=False)
            self.setProperty('CorrectionsWorkspace', self._abs_ws)
Example #19
0
    def test_packing_fraction(self):
        builder = MaterialBuilder().setName(NAME).setFormula(FORMULA)

        # setting nothing should be an error
        try:
            material = builder.build()
            raise AssertionError('Should throw an exception')
        except RuntimeError as e:
            assert 'number density' in str(e)

        builder = MaterialBuilder().setName(NAME).setFormula(FORMULA).setNumberDensity(NUMBER_DENSITY)

        # only with number density
        material = builder.build()
        self.assertEqual(material.name(), NAME)
        self.assertEqual(material.numberDensity, material.numberDensityEffective)
        self.assertEqual(material.packingFraction, 1.0)
        self.assertEqual(material.numberDensity, NUMBER_DENSITY)

        # with number density and packing fraction
        material = builder.setPackingFraction(0.5).build()
        self.assertEqual(material.name(), NAME)
        self.assertEqual(material.numberDensity, NUMBER_DENSITY)
        self.assertEqual(material.numberDensityEffective, NUMBER_DENSITY * 0.5)
        self.assertEqual(material.packingFraction, 0.5)

        # start a brand new material builder
        builder = MaterialBuilder().setName(NAME).setFormula(FORMULA).setMassDensity(MASS_DENSITY)

        # only with mass density
        material = builder.build()
        self.assertEqual(material.name(), NAME)
        self.assertEqual(material.numberDensity, material.numberDensityEffective)
        self.assertEqual(material.packingFraction, 1.0)
        self.assertAlmostEqual(material.numberDensityEffective, NUMBER_DENSITY * PACKING_OBS, delta=1e-4)

        # with mass density and number density
        material = builder.setNumberDensity(NUMBER_DENSITY).build()
        self.assertEqual(material.name(), NAME)
        self.assertEqual(material.numberDensity, NUMBER_DENSITY)
        self.assertAlmostEqual(material.numberDensityEffective, NUMBER_DENSITY * PACKING_OBS, delta=1e-4)
        self.assertAlmostEqual(material.packingFraction, PACKING_OBS, delta=1e-4)

        # setting all 3 should be an error
        try:
            material = builder.setPackingFraction(0.5).setNumberDensity(NUMBER_DENSITY).setMassDensity(MASS_DENSITY).build()
            raise AssertionError('Should throw an exception')
        except RuntimeError as e:
            assert 'number density' in str(e)
Example #20
0
    def PyExec(self):
        from IndirectCommon import getEfixed

        self._setup()

        # Set up progress reporting
        n_prog_reports = 2
        if self._can_ws_name is not None:
            n_prog_reports += 1
        prog = Progress(self, 0.0, 1.0, n_prog_reports)

        efixed = getEfixed(self._sample_ws)

        sample_wave_ws = '__sam_wave'
        ConvertUnits(InputWorkspace=self._sample_ws, OutputWorkspace=sample_wave_ws,
                     Target='Wavelength', EMode='Indirect', EFixed=efixed, EnableLogging = False)

        if self._sample_density_type == 'Mass Density':
            builder = MaterialBuilder()
            mat = builder.setFormula(self._sample_chemical_formula).setMassDensity(self._sample_density).build()
            self._sample_density = mat.numberDensity
        SetSampleMaterial(sample_wave_ws, ChemicalFormula=self._sample_chemical_formula, SampleNumberDensity=self._sample_density)

        prog.report('Calculating sample corrections')
        FlatPlateAbsorption(InputWorkspace=sample_wave_ws,
                            OutputWorkspace=self._ass_ws,
                            SampleHeight=self._sample_height,
                            SampleWidth=self._sample_width,
                            SampleThickness=self._sample_thickness,
                            ElementSize=self._element_size,
                            EMode='Indirect',
                            EFixed=efixed,
                            NumberOfWavelengthPoints=10)

        group = self._ass_ws

        if self._can_ws_name is not None:
            can_wave_ws = '__can_wave'
            ConvertUnits(InputWorkspace=self._can_ws_name, OutputWorkspace=can_wave_ws,
                         Target='Wavelength', EMode='Indirect', EFixed=efixed, EnableLogging = False)
            if self._can_scale != 1.0:
                logger.information('Scaling container by: ' + str(self._can_scale))
                Scale(InputWorkspace=can_wave_ws, OutputWorkspace=can_wave_ws, Factor=self._can_scale, Operation='Multiply')

            if self._use_can_corrections:
                prog.report('Calculating container corrections')
                Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)

                if self._sample_density_type == 'Mass Density':
                    builder = MaterialBuilder()
                    mat = builder.setFormula(self._can_chemical_formula).setMassDensity(self._can_density).build()
                    self._can_density = mat.numberDensity
                SetSampleMaterial(can_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density)

                FlatPlateAbsorption(InputWorkspace=can_wave_ws,
                                    OutputWorkspace=self._acc_ws,
                                    SampleHeight=self._sample_height,
                                    SampleWidth=self._sample_width,
                                    SampleThickness=self._can_front_thickness + self._can_back_thickness,
                                    ElementSize=self._element_size,
                                    EMode='Indirect',
                                    EFixed=efixed,
                                    NumberOfWavelengthPoints=10)

                Divide(LHSWorkspace=can_wave_ws, RHSWorkspace=self._acc_ws, OutputWorkspace=can_wave_ws)
                Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can_wave_ws, OutputWorkspace=sample_wave_ws)
                group += ',' + self._acc_ws

            else:
                prog.report('Calculating container scaling')
                Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can_wave_ws, OutputWorkspace=sample_wave_ws)
                Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)

            DeleteWorkspace(can_wave_ws, EnableLogging = False)

        else:
            Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)

        ConvertUnits(InputWorkspace=sample_wave_ws, OutputWorkspace=self._output_ws,
                     Target='DeltaE', EMode='Indirect', EFixed=efixed, EnableLogging = False)
        DeleteWorkspace(sample_wave_ws, EnableLogging = False)

        prog.report('Recording sample logs')
        sample_log_workspaces = [self._output_ws, self._ass_ws]
        sample_logs = [('sample_shape', 'flatplate'),
                       ('sample_filename', self._sample_ws),
                       ('sample_height', self._sample_height),
                       ('sample_width', self._sample_width),
                       ('sample_thickness', self._sample_thickness),
                       ('element_size', self._element_size)]

        if self._can_ws_name is not None:
            sample_logs.append(('container_filename', self._can_ws_name))
            sample_logs.append(('container_scale', self._can_scale))
            if self._use_can_corrections:
                sample_log_workspaces.append(self._acc_ws)
                sample_logs.append(('container_front_thickness', self. _can_front_thickness))
                sample_logs.append(('container_back_thickness', self. _can_back_thickness))

        log_names = [item[0] for item in sample_logs]
        log_values = [item[1] for item in sample_logs]

        for ws_name in sample_log_workspaces:
            AddSampleLogMultiple(Workspace=ws_name, LogNames=log_names, LogValues=log_values, EnableLogging = False)

        self.setProperty('OutputWorkspace', self._output_ws)

        # Output the Ass workspace if it is wanted, delete if not
        if self._abs_ws == '':
            DeleteWorkspace(self._ass_ws, EnableLogging = False)
            if self._can_ws_name is not None and self._use_can_corrections:
                DeleteWorkspace(self._acc_ws, EnableLogging = False)
        else:
            GroupWorkspaces(InputWorkspaces=group, OutputWorkspace=self._abs_ws, EnableLogging = False)
            self.setProperty('CorrectionsWorkspace', self._abs_ws)
Example #21
0
def generate_ts_pdf(run_number,
                    focus_file_path,
                    sample_details,
                    merge_banks=False,
                    q_lims=None,
                    cal_file_name=None,
                    delta_r=None,
                    delta_q=None,
                    pdf_type="G(r)",
                    lorch_filter=None,
                    freq_params=None,
                    debug=False):
    if sample_details is None:
        raise RuntimeError(
            "A SampleDetails object was not set. Please create a SampleDetails object and set the "
            "relevant properties it. Then set the new sample by calling set_sample_details()"
        )
    focused_ws = _obtain_focused_run(run_number, focus_file_path)
    focused_ws = mantid.ConvertUnits(InputWorkspace=focused_ws,
                                     Target="MomentumTransfer",
                                     EMode='Elastic')

    raw_ws = mantid.Load(Filename='POLARIS' + str(run_number))
    sample_geometry_json = sample_details.generate_sample_geometry()
    sample_material_json = sample_details.generate_sample_material()

    self_scattering_correction = mantid.TotScatCalculateSelfScattering(
        InputWorkspace=raw_ws,
        CalFileName=cal_file_name,
        SampleGeometry=sample_geometry_json,
        SampleMaterial=sample_material_json)

    ws_group_list = []
    for i in range(self_scattering_correction.getNumberHistograms()):
        ws_name = 'correction_' + str(i)
        mantid.ExtractSpectra(InputWorkspace=self_scattering_correction,
                              OutputWorkspace=ws_name,
                              WorkspaceIndexList=[i])
        ws_group_list.append(ws_name)
    self_scattering_correction = mantid.GroupWorkspaces(
        InputWorkspaces=ws_group_list)
    self_scattering_correction = mantid.RebinToWorkspace(
        WorkspaceToRebin=self_scattering_correction,
        WorkspaceToMatch=focused_ws)
    if not compare_ws_compatibility(focused_ws, self_scattering_correction):
        raise RuntimeError(
            "To use create_total_scattering_pdf you need to run focus with "
            "do_van_normalisation=true first.")
    focused_ws = mantid.Subtract(LHSWorkspace=focused_ws,
                                 RHSWorkspace=self_scattering_correction)
    if debug:
        dcs_corrected = mantid.CloneWorkspace(InputWorkspace=focused_ws)

    # convert diff cross section to S(Q) - 1
    material_builder = MaterialBuilder()
    sample = material_builder.setFormula(
        sample_details.material_object.chemical_formula).build()
    sample_total_scatter_cross_section = sample.totalScatterXSection()
    sample_coh_scatter_cross_section = sample.cohScatterXSection()
    focused_ws = focused_ws - sample_total_scatter_cross_section / (4 *
                                                                    math.pi)
    focused_ws = focused_ws * 4 * math.pi / sample_coh_scatter_cross_section
    if debug:
        s_of_q_minus_one = mantid.CloneWorkspace(InputWorkspace=focused_ws)

    if delta_q:
        focused_ws = mantid.Rebin(InputWorkspace=focused_ws, Params=delta_q)
    if merge_banks:
        q_min, q_max = _load_qlims(q_lims)
        merged_ws = mantid.MatchAndMergeWorkspaces(InputWorkspaces=focused_ws,
                                                   XMin=q_min,
                                                   XMax=q_max,
                                                   CalculateScale=False)
        fast_fourier_filter(merged_ws,
                            rho0=sample_details.material_object.number_density,
                            freq_params=freq_params)
        pdf_output = mantid.PDFFourierTransform(
            Inputworkspace="merged_ws",
            InputSofQType="S(Q)-1",
            PDFType=pdf_type,
            Filter=lorch_filter,
            DeltaR=delta_r,
            rho0=sample_details.material_object.number_density)
    else:
        for ws in focused_ws:
            fast_fourier_filter(
                ws,
                rho0=sample_details.material_object.number_density,
                freq_params=freq_params)
        pdf_output = mantid.PDFFourierTransform(
            Inputworkspace='focused_ws',
            InputSofQType="S(Q)-1",
            PDFType=pdf_type,
            Filter=lorch_filter,
            DeltaR=delta_r,
            rho0=sample_details.material_object.number_density)
        pdf_output = mantid.RebinToWorkspace(WorkspaceToRebin=pdf_output,
                                             WorkspaceToMatch=pdf_output[4],
                                             PreserveEvents=True)
    if not debug:
        common.remove_intermediate_workspace('self_scattering_correction')
    # Rename output ws
    if 'merged_ws' in locals():
        mantid.RenameWorkspace(InputWorkspace='merged_ws',
                               OutputWorkspace=run_number + '_merged_Q')
    mantid.RenameWorkspace(InputWorkspace='focused_ws',
                           OutputWorkspace=run_number + '_focused_Q')
    target_focus_ws_name = run_number + '_focused_Q_'
    target_pdf_ws_name = run_number + '_pdf_R_'
    if isinstance(focused_ws, WorkspaceGroup):
        for i in range(len(focused_ws)):
            if str(focused_ws[i]) != (target_focus_ws_name + str(i + 1)):
                mantid.RenameWorkspace(InputWorkspace=focused_ws[i],
                                       OutputWorkspace=target_focus_ws_name +
                                       str(i + 1))
    mantid.RenameWorkspace(InputWorkspace='pdf_output',
                           OutputWorkspace=run_number + '_pdf_R')
    if isinstance(pdf_output, WorkspaceGroup):
        for i in range(len(pdf_output)):
            if str(pdf_output[i]) != (target_pdf_ws_name + str(i + 1)):
                mantid.RenameWorkspace(InputWorkspace=pdf_output[i],
                                       OutputWorkspace=target_pdf_ws_name +
                                       str(i + 1))
    return pdf_output