def process_item(self, item): # Define quantities corresponding to materials doc fields # Attach quantities to materials item = MontyDecoder().process_decoded(item) logger.info("Populating material for %s", item['task_id']) material = Material() for mkey, property_name in self.materials_symbol_map.items(): value = get(item, mkey) if value: material.add_quantity(Quantity(property_name, value)) # Add custom things, e. g. computed entry computed_entry = get_entry(item) material.add_quantity(Quantity("computed_entry", computed_entry)) material.add_quantity( Quantity("external_identifier_mp", item['task_id'])) input_quantities = material.get_quantities() # Use graph to generate expanded quantity pool logger.info("Evaluating graph for %s", item['task_id']) graph = Graph() graph.remove_models({ "dimensionality_cheon": DEFAULT_MODEL_DICT['dimensionality_cheon'], "dimensionality_gorai": DEFAULT_MODEL_DICT['dimensionality_gorai'] }) new_material = graph.evaluate(material) # Format document and return logger.info("Creating doc for %s", item['task_id']) doc = {"inputs": [quantity.as_dict() for quantity in input_quantities]} for symbol, quantity in new_material.get_aggregated_quantities().items( ): all_qs = new_material._symbol_to_quantity[symbol] # Only add new quantities if len(all_qs) == 1 and list(all_qs)[0] in input_quantities: continue qs = [quantity.as_dict() for quantity in all_qs] sub_doc = { "quantities": qs, "mean": unumpy.nominal_values(quantity.value).tolist(), "std_dev": unumpy.std_devs(quantity.value).tolist(), "units": qs[0]['units'], "title": quantity._symbol_type.display_names[0] } doc[symbol.name] = sub_doc doc.update({ "task_id": item["task_id"], "pretty_formula": item["pretty_formula"] }) return jsanitize(doc, strict=True)
class MaterialTest(unittest.TestCase): def setUp(self): # Create some test properties and a few base objects self.q1 = Quantity( DEFAULT_SYMBOLS['bulk_modulus'], ureg.Quantity.from_tuple([200, [['gigapascals', 1]]])) self.q2 = Quantity( DEFAULT_SYMBOLS['shear_modulus'], ureg.Quantity.from_tuple([100, [['gigapascals', 1]]])) self.q3 = Quantity( DEFAULT_SYMBOLS['bulk_modulus'], ureg.Quantity.from_tuple([300, [['gigapascals', 1]]])) self.material = Material() self.graph = Graph() def test_material_setup(self): self.assertTrue( len(self.material._symbol_to_quantity) == 0, "Material not initialized properly.") def test_material_add_quantity(self): self.material.add_quantity(self.q1) self.assertEqual(len(self.material._symbol_to_quantity), 1, "Material did not add the quantity.") self.material.add_quantity(self.q2) self.assertEqual(len(self.material._symbol_to_quantity), 2, "Material did not add quantity to itself.") def test_material_remove_quantity(self): self.material.add_quantity(self.q1) self.material.add_quantity(self.q2) self.material.remove_quantity(self.q1) self.assertEqual( len(self.material._symbol_to_quantity[ DEFAULT_SYMBOLS['shear_modulus']]), 1, "Material did not remove the correct quantity.") self.material.remove_quantity(self.q2) self.assertEqual( len(self.material._symbol_to_quantity[ DEFAULT_SYMBOLS['shear_modulus']]), 0, "Material did not remove the quantity correctly.") def test_material_remove_symbol(self): self.material.add_quantity(self.q1) self.material.add_quantity(self.q2) self.material.add_quantity(self.q3) self.material.remove_symbol(DEFAULT_SYMBOLS['bulk_modulus']) self.assertTrue( DEFAULT_SYMBOLS['shear_modulus'] in self.material._symbol_to_quantity.keys(), "Material did not remove Symbol correctly.") self.assertTrue( self.q2 in self.material._symbol_to_quantity[ DEFAULT_SYMBOLS['shear_modulus']], "Material did not remove Symbol correctly.") self.assertEqual(len(self.material._symbol_to_quantity), 1, "Material did not remove Symbol correctly.") def test_get_symbols(self): self.material.add_quantity(self.q1) self.material.add_quantity(self.q2) self.material.add_quantity(self.q3) out = self.material.get_symbols() self.assertEqual(len(out), 2, "Material did not get Symbol Types correctly.") self.assertTrue(DEFAULT_SYMBOLS['bulk_modulus'] in out, "Material did not get Symbol Types correctly.") self.assertTrue(DEFAULT_SYMBOLS['shear_modulus'] in out, "Material did not get Symbol Types correctly.") def test_get_quantities(self): self.material.add_quantity(self.q1) self.material.add_quantity(self.q2) self.material.add_quantity(self.q3) out = self.material.get_quantities() self.assertTrue(all([q in out for q in [self.q1, self.q2, self.q3]]), "Material did not get Quantity objects correctly.") def test_get_aggregated_quantities(self): self.material.add_quantity(self.q1) self.material.add_quantity(self.q2) self.material.add_quantity(self.q3) agg = self.material.get_aggregated_quantities()
def process_item(self, item): # Define quantities corresponding to materials doc fields # Attach quantities to materials item = MontyDecoder().process_decoded(item) logger.info("Populating material for %s", item['task_id']) material = Material() if 'created_at' in item.keys(): date_created = item['created_at'] else: date_created = "" provenance = ProvenanceElement( source={ "source": self.source_name, "source_key": item['task_id'], "date_created": date_created }) for mkey, property_name in self.materials_symbol_map.items(): value = get(item, mkey) if value: material.add_quantity( QuantityFactory.create_quantity(property_name, value, provenance=provenance)) # Add custom things, e. g. computed entry computed_entry = get_entry(item) material.add_quantity( QuantityFactory.create_quantity("computed_entry", computed_entry, provenance=provenance)) material.add_quantity( QuantityFactory.create_quantity("external_identifier_mp", item['task_id'], provenance=provenance)) input_quantities = material.get_quantities() # Use graph to generate expanded quantity pool logger.info("Evaluating graph for %s", item['task_id']) graph = Graph() graph.remove_models({ "dimensionality_cheon": DEFAULT_MODEL_DICT['dimensionality_cheon'], "dimensionality_gorai": DEFAULT_MODEL_DICT['dimensionality_gorai'] }) new_material = graph.evaluate(material) # Format document and return logger.info("Creating doc for %s", item['task_id']) # Gives the initial inputs that were used to derive properties of a # certain material. doc = { "inputs": [StorageQuantity.from_quantity(q) for q in input_quantities] } for symbol, quantity in new_material.get_aggregated_quantities().items( ): all_qs = new_material._symbol_to_quantity[symbol] # Only add new quantities # TODO: Condition insufficiently general. # Can end up with initial quantities added as "new quantities" if len(all_qs) == 1 and list(all_qs)[0] in input_quantities: continue # Write out all quantities as dicts including the # internal ID for provenance tracing qs = [StorageQuantity.from_quantity(q).as_dict() for q in all_qs] # THE listing of all Quantities of a given symbol. sub_doc = { "quantities": qs, "mean": unumpy.nominal_values(quantity.value).tolist(), "std_dev": unumpy.std_devs(quantity.value).tolist(), "units": quantity.units.format_babel() if quantity.units else None, "title": quantity._symbol_type.display_names[0] } # Symbol Name -> Sub_Document, listing all Quantities of that type. doc[symbol.name] = sub_doc doc.update({ "task_id": item["task_id"], "pretty_formula": item["pretty_formula"] }) return jsanitize(doc, strict=True)
class MaterialTest(unittest.TestCase): def setUp(self): # Create some test properties and a few base objects self.q1 = QuantityFactory.create_quantity(DEFAULT_SYMBOLS['bulk_modulus'], ureg.Quantity.from_tuple([200, [['gigapascals', 1]]])) self.q2 = QuantityFactory.create_quantity(DEFAULT_SYMBOLS['shear_modulus'], ureg.Quantity.from_tuple([100, [['gigapascals', 1]]])) self.q3 = QuantityFactory.create_quantity(DEFAULT_SYMBOLS['bulk_modulus'], ureg.Quantity.from_tuple([300, [['gigapascals', 1]]])) self.material = Material() self.graph = Graph() def test_material_setup(self): self.assertTrue(len(self.material._symbol_to_quantity) == 0, "Material not initialized properly.") def test_material_add_quantity(self): self.material.add_quantity(self.q1) self.assertEqual(len(self.material._symbol_to_quantity), 1, "Material did not add the quantity.") self.material.add_quantity(self.q2) self.assertEqual(len(self.material._symbol_to_quantity), 2, "Material did not add quantity to itself.") def test_material_remove_quantity(self): self.material.add_quantity(self.q1) self.material.add_quantity(self.q2) self.material.remove_quantity(self.q1) self.assertEqual( len(self.material._symbol_to_quantity[DEFAULT_SYMBOLS['shear_modulus']]), 1, "Material did not remove the correct quantity.") self.material.remove_quantity(self.q2) self.assertEqual( len(self.material._symbol_to_quantity[DEFAULT_SYMBOLS['shear_modulus']]), 0, "Material did not remove the quantity correctly.") def test_material_remove_symbol(self): self.material.add_quantity(self.q1) self.material.add_quantity(self.q2) self.material.add_quantity(self.q3) self.material.remove_symbol(DEFAULT_SYMBOLS['bulk_modulus']) self.assertTrue( DEFAULT_SYMBOLS['shear_modulus'] in self.material._symbol_to_quantity.keys(), "Material did not remove Symbol correctly.") self.assertTrue( self.q2 in self.material._symbol_to_quantity[DEFAULT_SYMBOLS['shear_modulus']], "Material did not remove Symbol correctly.") self.assertEqual(len(self.material._symbol_to_quantity), 1, "Material did not remove Symbol correctly.") def test_get_symbols(self): self.material.add_quantity(self.q1) self.material.add_quantity(self.q2) self.material.add_quantity(self.q3) out = self.material.get_symbols() self.assertEqual( len(out), 2, "Material did not get Symbol Types correctly.") self.assertTrue(DEFAULT_SYMBOLS['bulk_modulus'] in out, "Material did not get Symbol Types correctly.") self.assertTrue(DEFAULT_SYMBOLS['shear_modulus'] in out, "Material did not get Symbol Types correctly.") def test_get_quantities(self): self.material.add_quantity(self.q1) self.material.add_quantity(self.q2) self.material.add_quantity(self.q3) out = self.material.get_quantities() self.assertTrue(all([q in out for q in [self.q1, self.q2, self.q3]]), "Material did not get Quantity objects correctly.") def test_get_aggregated_quantities(self): self.material.add_quantity(self.q1) self.material.add_quantity(self.q2) self.material.add_quantity(self.q3) agg = self.material.get_aggregated_quantities() # TODO: add a meaningful test here def test_add_default_quantities(self): material = Material(add_default_quantities=True) self.assertEqual(list(material['temperature'])[0], QuantityFactory.create_quantity("temperature", 300, provenance=ProvenanceElement(model='default'))) self.assertEqual(list(material['relative_permeability'])[0], QuantityFactory.create_quantity("relative_permeability", 1, provenance=ProvenanceElement(model='default')))