Пример #1
0
 def _refinement_setup(self):
     # TODO maybe add some more variation in the type of Phases?
     specimen = Specimen(name="Test Specimen", parent=self.project)
     self.project.specimens.append(specimen)
     phase1 = Phase(name="Test Phase1", parent=self.project)
     self.project.phases.append(phase1)
     phase2 = Phase(name="Test Phase2", parent=self.project)
     self.project.phases.append(phase2)
     self.mixture.add_specimen_slot(specimen, 0.5, 0)
     self.mixture.add_phase_slot("Test Phase1", 0.5)
     self.mixture.add_phase_slot("Test Phase2", 0.5)
     self.mixture.set_phase(0, 0, phase1)
     self.mixture.set_phase(0, 1, phase2)
Пример #2
0
    def test_import_export(self):
        from io import BytesIO
        phases = [Phase(R=0, G=1), Phase(R=1, G=2)]
        fn = BytesIO()
        Phase.save_phases(phases, filename=fn)
        loaded_phases = list(JSONPhaseParser.parse(fn))

        def strip_uuid(data):
            new_data = []
            for line in data.split('\n'):
                if "uuid" not in line:
                    new_data.append(line)
            return "\n".join(new_data)

        outp1 = [strip_uuid(phase.dump_object()) for phase in phases]
        outp2 = [strip_uuid(phase.dump_object()) for phase in loaded_phases]
        self.assertEqual(outp1, outp2)
Пример #3
0
    def phaseworker(in_queue, save_queue, stop):
        """
            Parses Phase descriptions into actual objects and passes them
            to the save_queue.
            'stop' should be a threading.Event() that should be toggled
            once all elements have been Queued.
            This way, the worker will only stop once the Queue is really empty,
            and not when it's processing faster than the Queue can be filled. 
        """
        while True:
            try:
                phases_path, phase_descr = in_queue.get(timeout=0.5)
                project = Project()
                phase_lookup = {}
                component_lookup = {}

                for phase_kwargs, code, comp_props in phase_descr:

                    # create phase:
                    G = len(code) / code_length
                    based_on = None
                    if "based_on" in phase_kwargs:
                        based_on = phase_lookup.get(phase_kwargs.pop("based_on"), None)
                    phase = Phase(G=G, parent=project, **phase_kwargs)
                    phase.based_on = based_on
                    phase_lookup[phase.name] = phase

                    # derive upper and lower limits for the codes using code lengths:
                    limits = list(zip(
                        list(range(0, len(code), code_length)),
                        list(range(code_length, len(code) + 1, code_length))
                    ))

                    # create components:
                    phase.components[:] = []
                    for ll, ul in limits:
                        part = code[ll: ul]
                        for component in Component.load_components(aliases[part] % (settings.DATA_REG.get_directory_path("DEFAULT_COMPONENTS") + "/"), parent=phase):
                            component.resolve_json_references()
                            phase.components.append(component)
                            props = comp_props.get(part, {})
                            for prop, value in props.items():
                                if prop == 'linked_with':
                                    value = component_lookup[value]
                                setattr(component, prop, value)

                            component_lookup[part] = component

                # put phases on the save queue:
                phases_path = phases_path % (settings.DATA_REG.get_directory_path("DEFAULT_PHASES") + "/")
                save_queue.put((phases_path, list(phase_lookup.values())))
                # Flag this as finished
                in_queue.task_done()
            except queue.Empty:
                if not stop.is_set():
                    continue
                else:
                    return
Пример #4
0
    def test_unset_phase(self):
        specimen = Specimen(name="Test Specimen", parent=self.project)
        self.project.specimens.append(specimen)
        self.mixture.add_specimen_slot(specimen, 0.5, 0)
        self.mixture.add_phase_slot("Test Phase1", 0.5)

        dummy = Phase(name="Test Phase", parent=self.project)
        self.project.phases.append(dummy)
        self.mixture.set_phase(0, 0, dummy)
        self.mixture.unset_phase(dummy)
        self.assertEqual(self.mixture.phase_matrix[0, 0], None)
Пример #5
0
    def test_R_G(self):
        self.assertIsNotNone(Phase(R=0, G=1))
        self.assertIsNotNone(Phase(R=0, G=2))
        self.assertIsNotNone(Phase(R=0, G=3))
        self.assertIsNotNone(Phase(R=0, G=4))
        self.assertIsNotNone(Phase(R=0, G=5))
        self.assertIsNotNone(Phase(R=0, G=6))

        self.assertIsNotNone(Phase(R=1, G=2))
        self.assertIsNotNone(Phase(R=1, G=3))
        self.assertIsNotNone(Phase(R=1, G=4))

        self.assertIsNotNone(Phase(R=2, G=2))
        self.assertIsNotNone(Phase(R=2, G=3))

        self.assertIsNotNone(Phase(R=3, G=2))
Пример #6
0
 def setUp(self):
     settings.initialize()
     self.phase = Phase(R=0, G=1)
Пример #7
0
def create_project_from_sybilla_xml(filename, **kwargs):
    """
        Creates a new project structure from a Sybilla XML file.
        Some information (e.g. the actual XRD pattern) is not present and will
        still need to be imported manually.
    """

    tree = ET.parse(filename)
    root = tree.getroot()
    basename = os.path.basename(filename)

    # Create the project:
    if "name" in kwargs: kwargs.pop("name")
    if "layout_mode" in kwargs: kwargs.pop("layout_mode")
    project = Project(name=basename, layout_mode="FULL", **kwargs)

    # Add a specimen:
    specimen = Specimen(name=basename, parent=project)
    project.specimens.append(specimen)

    # Add a mixture:
    mixture = Mixture(name=basename, auto_run=False, parent=project)
    mixture.add_specimen_slot(specimen, 1.0, 0.0)
    project.mixtures.append(mixture)

    with project.data_changed.ignore():
        with mixture.data_changed.ignore():

            for child in root:
                if child.tag == "basic_params":
                    # Goniometer parameters:
                    step_size = safe_float(child.attrib['step_size'])
                    wavelength = safe_float(child.attrib['lambda']) / 10.0
                    steps = int(1 +
                                (specimen.goniometer.max_2theta -
                                 specimen.goniometer.min_2theta) / step_size)

                    specimen.goniometer.min_2theta = safe_float(
                        child.attrib['min2theta'])
                    specimen.goniometer.max_2theta = safe_float(
                        child.attrib['max2theta'])
                    specimen.goniometer.steps = steps
                    specimen.goniometer.wavelength = wavelength
                elif child.tag == "diffractometer":
                    # Some more goniometer parameters, and specimen parameters:
                    specimen.goniometer.radius = safe_float(
                        child.attrib['gonio_radius'])
                    specimen.goniometer.divergence = safe_float(
                        child.attrib['diverg_slit'])
                    specimen.goniometer.soller1 = safe_float(
                        child.attrib['Soller1'])
                    specimen.goniometer.soller2 = safe_float(
                        child.attrib['Soller2'])
                    specimen.sample_length = safe_float(
                        child.attrib['sample_length'])
                elif child.tag == "content":
                    # Content tag contains 'Mixture' data
                    for xmlPhaseContent in child:
                        name = xmlPhaseContent.attrib['name']
                        fraction = safe_float(
                            xmlPhaseContent.attrib['content']) / 100.
                        mixture.add_phase_slot(name, fraction)
                elif child.tag == "mixture":
                    # Mixture tag corresponds with the phases in the project level,
                    # not an actual Mixture object:
                    for xmlPhase in child:
                        name = xmlPhase.attrib['name']
                        sigma = xmlPhase.attrib['sigma_star']
                        csds = safe_float(
                            xmlPhase.find('distribution').attrib['Tmean'])
                        G = 1
                        R = 0
                        W = [
                            1.0,
                        ]
                        if xmlPhase.attrib['type'] != 'mono':
                            prob = xmlPhase.find('probability')
                            G = int(prob.attrib['no_of_comp'])
                            R = int(prob.attrib['R'])

                        # create phase and add to project:
                        phase = Phase(name=name,
                                      sigma_star=sigma,
                                      G=G,
                                      R=R,
                                      parent=project)
                        phase.CSDS_distribution.average = csds
                        project.phases.append(phase)

                        # set probability:
                        if R == 0 and G != 1:
                            xmlW = prob.find('W')
                            W = np.array([
                                float(
                                    int(
                                        safe_float(xmlW.attrib[
                                            string.ascii_lowercase[i]]) *
                                        1000.)) / 1000. for i in range(G)
                            ])
                            for i in range(G - 1):
                                setattr(phase.probabilities, "F%d" % (i + 1),
                                        W[i] / np.sum(W[i:]))
                        if R == 1 and G == 2:
                            pass  # TODO
                        # ... TODO other probs

                        # parse components:
                        for i, layer in enumerate(
                                xmlPhase.findall("./layer_and_edge/layer")):

                            component = phase.components[i]
                            component.name = layer.attrib['name']

                            component.d001 = safe_float(
                                layer.attrib['d_spacing']) / 10.0
                            component.default_c = safe_float(
                                layer.attrib['d_spacing']) / 10.0
                            component.delta_c = safe_float(
                                layer.attrib['d_spacing_delta']) / 10.0

                            component.ucp_b.value = 0.9

                            component.ucp_a.factor = 0.57735
                            component.ucp_a.prop = (component, 'cell_b')
                            component.ucp_a.enabled = True

                            atom_type_map = {
                                # "NH4": "FIXME"
                                "K": "K1+",
                                "O": "O1-",
                                "Si": "Si2+",
                                "OH": "OH1-",
                                "Fe": "Fe1.5+",
                                "Al": "Al1.5+",
                                "Mg": "Mg1+",
                                "H2O": "H2O",
                                "Gly": "Glycol",
                                "Ca": "Ca2+",
                                "Na": "Na1+",
                            }

                            # add atoms:
                            fe_atom = None
                            encountered_oxygen = False
                            for atom in layer.findall("atom"):
                                atom_type_name = atom_type_map.get(
                                    atom.attrib['type'], None)
                                if atom_type_name:
                                    if atom_type_name == "O1-":
                                        # From this point we're dealing with layer atoms
                                        encountered_oxygen = True
                                    atom = Atom(
                                        name=atom.attrib['type'],
                                        default_z=safe_float(
                                            atom.attrib['position']) / 10.0,
                                        pn=safe_float(atom.attrib['content']),
                                        atom_type_name=atom_type_name,
                                        parent=component)
                                    if encountered_oxygen:
                                        component.layer_atoms.append(atom)
                                    else:
                                        component.interlayer_atoms.append(atom)
                                    atom.resolve_json_references()
                                    # Assume this is the octahedral iron...
                                    if encountered_oxygen and atom_type_name == "Fe1.5+":
                                        fe_atom = atom

                            # Set the atom relation
                            if fe_atom is not None:
                                component.ucp_b.constant = 0.9
                                component.ucp_b.factor = 0.0043
                                component.ucp_b.prop = (fe_atom, 'pn')
                                component.ucp_b.enabled = True

                pass  # end of if
            pass  # end of for

            # Map phases onto mixture names:
            for phase in project.phases:
                for slot, phase_name in enumerate(mixture.phases):
                    if phase.name == phase_name:
                        mixture.set_phase(0, slot, phase)

    return project