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)
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)
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
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)
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))
def setUp(self): settings.initialize() self.phase = Phase(R=0, G=1)
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