Beispiel #1
0
def test_mongostore_newer_in(mongostore):
    target = MongoStore("maggma_test", "test_target")
    target.connect()

    # make sure docs are newer in mongostore then target and check updated_keys

    target.update(
        [
            {mongostore.key: i, mongostore.last_updated_field: datetime.utcnow()}
            for i in range(10)
        ]
    )

    # Update docs in source
    mongostore.update(
        [
            {mongostore.key: i, mongostore.last_updated_field: datetime.utcnow()}
            for i in range(10)
        ]
    )

    assert len(target.newer_in(mongostore)) == 10
    assert len(target.newer_in(mongostore, exhaustive=True)) == 10
    assert len(mongostore.newer_in(target)) == 0

    target._collection.drop()
class ElasticAnalysisBuilderTest(unittest.TestCase):
    @classmethod
    def setUp(self):
        # Set up test db, set up mpsft, etc.
        self.test_tasks = MongoStore("test_emmet", "tasks")
        self.test_tasks.connect()
        docs = loadfn(test_tasks, cls=None)
        self.test_tasks.update(docs)
        self.test_elasticity = MongoStore("test_emmet", "elasticity")
        self.test_elasticity.connect()
        if PROFILE_MODE:
            self.pr = cProfile.Profile()
            self.pr.enable()
            print("\n<<<---")

    @classmethod
    def tearDown(self):
        if not DEBUG_MODE:
            self.test_elasticity.collection.drop()
            self.test_tasks.collection.drop()
        if PROFILE_MODE:
            p = Stats(self.pr)
            p.strip_dirs()
            p.sort_stats('cumtime')
            p.print_stats()
            print("\n--->>>")

    def test_builder(self):
        ec_builder = ElasticAnalysisBuilder(self.test_tasks,
                                            self.test_elasticity,
                                            incremental=False)
        ec_builder.connect()
        for t in ec_builder.get_items():
            processed = ec_builder.process_item(t)
            self.assertTrue(bool(processed))
        runner = Runner([ec_builder])
        runner.run()
        # Test warnings
        doc = ec_builder.elasticity.query_one(
            criteria={"pretty_formula": "NaN3"})
        self.assertEqual(doc['warnings'], None)
        self.assertAlmostEqual(doc['compliance_tensor'][0][0], 41.576072, 6)

    def test_grouping_functions(self):
        docs1 = list(
            self.test_tasks.query(criteria={"formula_pretty": "NaN3"}))
        docs_grouped1 = group_by_parent_lattice(docs1)
        self.assertEqual(len(docs_grouped1), 1)
        grouped_by_opt = group_deformations_by_optimization_task(docs1)
        self.assertEqual(len(grouped_by_opt), 1)
        docs2 = self.test_tasks.query(
            criteria={"task_label": "elastic deformation"})
        sgroup2 = group_by_parent_lattice(docs2)

    def test_get_distinct_rotations(self):
        struct = PymatgenTest.get_structure("Si")
        conv = SpacegroupAnalyzer(struct).get_conventional_standard_structure()
        rots = get_distinct_rotations(conv)
        ops = SpacegroupAnalyzer(conv).get_symmetry_operations()
        for op in ops:
            self.assertTrue(
                any([np.allclose(op.rotation_matrix, r) for r in rots]))
        self.assertEqual(len(rots), 48)

    def test_process_elastic_calcs(self):
        test_struct = PymatgenTest.get_structure('Sn')  # use cubic test struct
        dss = DeformedStructureSet(test_struct)

        # Construct test task set
        opt_task = {
            "output": {
                "structure": test_struct.as_dict()
            },
            "input": {
                "structure": test_struct.as_dict()
            }
        }
        defo_tasks = []
        for n, (struct, defo) in enumerate(zip(dss, dss.deformations)):
            strain = defo.green_lagrange_strain
            defo_task = {
                "output": {
                    "structure": struct.as_dict(),
                    "stress": (strain * 5).tolist()
                },
                "input": None,
                "task_id": n,
                "completed_at": datetime.utcnow()
            }
            defo_task.update({
                "transmuter": {
                    "transformation_params": [{
                        "deformation": defo
                    }]
                }
            })
            defo_tasks.append(defo_task)

        defo_tasks.pop(0)
        explicit, derived = process_elastic_calcs(opt_task, defo_tasks)
        self.assertEqual(len(explicit), 23)
        self.assertEqual(len(derived), 1)

    def test_process_elastic_calcs_toec(self):
        # Test TOEC tasks
        test_struct = PymatgenTest.get_structure('Sn')  # use cubic test struct
        strain_states = get_default_strain_states(3)
        # Default stencil in atomate, this maybe shouldn't be hard-coded
        stencil = np.linspace(-0.075, 0.075, 7)
        strains = [
            Strain.from_voigt(s * np.array(strain_state))
            for s, strain_state in product(stencil, strain_states)
        ]
        strains = [s for s in strains if not np.allclose(s, 0)]
        sym_reduced = symmetry_reduce(strains, test_struct)
        opt_task = {
            "output": {
                "structure": test_struct.as_dict()
            },
            "input": {
                "structure": test_struct.as_dict()
            }
        }
        defo_tasks = []
        for n, strain in enumerate(sym_reduced):
            defo = strain.get_deformation_matrix()
            new_struct = defo.apply_to_structure(test_struct)
            defo_task = {
                "output": {
                    "structure": new_struct.as_dict(),
                    "stress": (strain * 5).tolist()
                },
                "input": None,
                "task_id": n,
                "completed_at": datetime.utcnow()
            }
            defo_task.update({
                "transmuter": {
                    "transformation_params": [{
                        "deformation": defo
                    }]
                }
            })
            defo_tasks.append(defo_task)
        explicit, derived = process_elastic_calcs(opt_task, defo_tasks)
        self.assertEqual(len(explicit), len(sym_reduced))
        self.assertEqual(len(derived), len(strains) - len(sym_reduced))
        for calc in derived:
            self.assertTrue(
                np.allclose(calc['strain'], calc['cauchy_stress'] / -0.5))
class ElasticAggregateBuilderTest(unittest.TestCase):
    def setUp(self):
        # Empty aggregated collection
        self.test_elasticity_agg = MongoStore("test_emmet", "elasticity_agg")
        self.test_elasticity_agg.connect()

        # Generate test materials collection
        self.test_materials = MongoStore("test_emmet", "materials")
        self.test_materials.connect()
        mat_docs = []
        for n, formula in enumerate(['Si', 'BaNiO3', 'Li2O2', 'TiO2']):
            structure = PymatgenTest.get_structure(formula)
            structure.add_site_property("magmoms", [0.0] * len(structure))
            mat_docs.append({
                "task_id": "mp-{}".format(n),
                "structure": structure.as_dict(),
                "pretty_formula": formula
            })
        self.test_materials.update(mat_docs, update_lu=False)

        # Create elasticity collection and add docs
        self.test_elasticity = MongoStore("test_emmet",
                                          "elasticity",
                                          key="optimization_task_id")
        self.test_elasticity.connect()

        si = PymatgenTest.get_structure("Si")
        si.add_site_property("magmoms", [0.0] * len(si))
        et = ElasticTensor.from_voigt([[50, 25, 25, 0, 0, 0],
                                       [25, 50, 25, 0, 0, 0],
                                       [25, 25, 50, 0, 0, 0],
                                       [0, 0, 0, 75, 0,
                                        0], [0, 0, 0, 0, 75, 0],
                                       [0, 0, 0, 0, 0, 75]])
        doc = {
            "input_structure": si.copy().as_dict(),
            "order": 2,
            "magnetic_type": "non-magnetic",
            "optimization_task_id": "mp-1",
            "last_updated": datetime.utcnow(),
            "completed_at": datetime.utcnow(),
            "optimized_structure": si.copy().as_dict(),
            "pretty_formula": "Si",
            "state": "successful"
        }
        doc['elastic_tensor'] = et.voigt
        doc.update(et.property_dict)
        self.test_elasticity.update([doc])
        # Insert second doc with diff params
        si.perturb(0.005)
        doc.update({
            "optimized_structure": si.copy().as_dict(),
            "updated_at": datetime.utcnow(),
            "optimization_task_id": "mp-5"
        })
        self.test_elasticity.update([doc])
        self.builder = self.get_a_new_builder()

    def tearDown(self):
        if not DEBUG_MODE:
            self.test_elasticity.collection.drop()
            self.test_elasticity_agg.collection.drop()
            self.test_materials.collection.drop()

    def test_materials_aggregator(self):
        materials_dict = generate_formula_dict(self.test_materials)
        docs = []
        grouped_by_mpid = group_by_material_id(
            materials_dict['Si'],
            [{
                'structure': PymatgenTest.get_structure('Si').as_dict(),
                'magnetic_type': "non-magnetic"
            }])
        self.assertEqual(len(grouped_by_mpid), 1)
        materials_dict = generate_formula_dict(self.test_materials)

    def test_get_items(self):
        iterator = self.builder.get_items()
        for item in iterator:
            self.assertIsNotNone(item)

    def test_process_items(self):
        docs = list(
            self.test_elasticity.query(criteria={"pretty_formula": "Si"}))
        formula_dict = generate_formula_dict(self.test_materials)
        processed = self.builder.process_item((docs, formula_dict['Si']))
        self.assertEqual(len(processed), 1)
        self.assertEqual(len(processed[0]['all_elastic_fits']), 2)

    def test_update_targets(self):
        processed = [
            self.builder.process_item(item)
            for item in self.builder.get_items()
        ]
        self.builder.update_targets(processed)

    def test_aggregation(self):
        runner = Runner([self.builder])
        runner.run()
        all_agg_docs = list(self.test_elasticity_agg.query())
        self.assertTrue(bool(all_agg_docs))

    def get_a_new_builder(self):
        return ElasticAggregateBuilder(self.test_elasticity,
                                       self.test_materials,
                                       self.test_elasticity_agg)
Beispiel #4
0
class TestCopyBuilder(TestCase):
    @classmethod
    def setUpClass(cls):
        cls.dbname = "test_" + uuid4().hex
        s = MongoStore(cls.dbname, "test")
        s.connect()
        cls.client = s.collection.database.client

    @classmethod
    def tearDownClass(cls):
        cls.client.drop_database(cls.dbname)

    def setUp(self):
        tic = datetime.now()
        toc = tic + timedelta(seconds=1)
        keys = list(range(20))
        self.old_docs = [{"lu": tic, "k": k, "v": "old"} for k in keys]
        self.new_docs = [{"lu": toc, "k": k, "v": "new"} for k in keys[:10]]
        kwargs = dict(key="k", lu_field="lu")
        self.source = MongoStore(self.dbname, "source", **kwargs)
        self.target = MongoStore(self.dbname, "target", **kwargs)
        self.builder = CopyBuilder(self.source, self.target)
        self.source.connect()
        self.source.collection.create_index("lu")
        self.target.connect()
        self.target.collection.create_index("lu")
        self.target.collection.create_index("k")

    def tearDown(self):
        self.source.collection.drop()
        self.target.collection.drop()

    def test_get_items(self):
        self.source.collection.insert_many(self.old_docs)
        self.assertEqual(len(list(self.builder.get_items())),
                         len(self.old_docs))
        self.target.collection.insert_many(self.old_docs)
        self.assertEqual(len(list(self.builder.get_items())), 0)
        self.source.update(self.new_docs, update_lu=False)
        self.assertEqual(len(list(self.builder.get_items())),
                         len(self.new_docs))

    def test_process_item(self):
        self.source.collection.insert_many(self.old_docs)
        items = list(self.builder.get_items())
        self.assertCountEqual(items, map(self.builder.process_item, items))

    def test_update_targets(self):
        self.source.collection.insert_many(self.old_docs)
        self.source.update(self.new_docs, update_lu=False)
        self.target.collection.insert_many(self.old_docs)
        items = list(map(self.builder.process_item, self.builder.get_items()))
        self.builder.update_targets(items)
        self.assertEqual(self.target.query_one(criteria={"k": 0})["v"], "new")
        self.assertEqual(self.target.query_one(criteria={"k": 10})["v"], "old")

    def test_confirm_lu_field_index(self):
        self.source.collection.drop_index("lu_1")
        with self.assertRaises(Exception) as cm:
            self.builder.get_items()
        self.assertTrue(cm.exception.args[0].startswith("Need index"))
        self.source.collection.create_index("lu")

    def test_runner(self):
        self.source.collection.insert_many(self.old_docs)
        self.source.update(self.new_docs, update_lu=False)
        self.target.collection.insert_many(self.old_docs)
        runner = Runner([self.builder])
        runner.run()
        self.assertEqual(self.target.query_one(criteria={"k": 0})["v"], "new")
        self.assertEqual(self.target.query_one(criteria={"k": 10})["v"], "old")

    def test_query(self):
        self.builder.query = {"k": {"$gt": 5}}
        self.source.collection.insert_many(self.old_docs)
        self.source.update(self.new_docs, update_lu=False)
        runner = Runner([self.builder])
        runner.run()
        all_docs = list(self.target.query(criteria={}))
        self.assertEqual(len(all_docs), 14)
        self.assertTrue(min([d['k'] for d in all_docs]), 6)
Beispiel #5
0
class TestCopyBuilder(TestCase):
    @classmethod
    def setUpClass(cls):
        cls.dbname = "test_" + uuid4().hex
        s = MongoStore(cls.dbname, "test")
        s.connect()
        cls.client = s.collection.database.client

    @classmethod
    def tearDownClass(cls):
        cls.client.drop_database(cls.dbname)

    def setUp(self):
        tic = datetime.now()
        toc = tic + timedelta(seconds=1)
        keys = list(range(20))
        self.old_docs = [{"lu": tic, "k": k, "v": "old"} for k in keys]
        self.new_docs = [{"lu": toc, "k": k, "v": "new"} for k in keys[:10]]
        kwargs = dict(key="k", lu_field="lu")
        self.source = MongoStore(self.dbname, "source", **kwargs)
        self.target = MongoStore(self.dbname, "target", **kwargs)
        self.builder = CopyBuilder(self.source, self.target)

        self.source.connect()
        self.source.ensure_index(self.source.key)
        self.source.ensure_index(self.source.lu_field)

        self.target.connect()
        self.target.ensure_index(self.target.key)
        self.target.ensure_index(self.target.lu_field)

    def tearDown(self):
        self.source.collection.drop()
        self.target.collection.drop()

    def test_get_items(self):
        self.source.collection.insert_many(self.old_docs)
        self.assertEqual(len(list(self.builder.get_items())),
                         len(self.old_docs))
        self.target.collection.insert_many(self.old_docs)
        self.assertEqual(len(list(self.builder.get_items())), 0)
        self.source.update(self.new_docs, update_lu=False)
        self.assertEqual(len(list(self.builder.get_items())),
                         len(self.new_docs))

    def test_process_item(self):
        self.source.collection.insert_many(self.old_docs)
        items = list(self.builder.get_items())
        self.assertCountEqual(items, map(self.builder.process_item, items))

    def test_update_targets(self):
        self.source.collection.insert_many(self.old_docs)
        self.source.update(self.new_docs, update_lu=False)
        self.target.collection.insert_many(self.old_docs)
        items = list(map(self.builder.process_item, self.builder.get_items()))
        self.builder.update_targets(items)
        self.assertEqual(self.target.query_one(criteria={"k": 0})["v"], "new")
        self.assertEqual(self.target.query_one(criteria={"k": 10})["v"], "old")

    @unittest.skip(
        "Have to refactor how we force read-only so a warning will get thrown")
    def test_index_warning(self):
        """Should log warning when recommended store indexes are not present."""
        self.source.collection.drop_index([(self.source.key, 1)])
        with self.assertLogs(level=logging.WARNING) as cm:
            list(self.builder.get_items())
        self.assertIn("Ensure indices", "\n".join(cm.output))

    def test_run(self):
        self.source.collection.insert_many(self.old_docs)
        self.source.update(self.new_docs, update_lu=False)
        self.target.collection.insert_many(self.old_docs)
        self.builder.run()
        self.assertEqual(self.target.query_one(criteria={"k": 0})["v"], "new")
        self.assertEqual(self.target.query_one(criteria={"k": 10})["v"], "old")

    def test_query(self):
        self.builder.query = {"k": {"$gt": 5}}
        self.source.collection.insert_many(self.old_docs)
        self.source.update(self.new_docs, update_lu=False)
        self.builder.run()
        all_docs = list(self.target.query(criteria={}))
        self.assertEqual(len(all_docs), 14)
        self.assertTrue(min([d['k'] for d in all_docs]), 6)

    def test_delete_orphans(self):
        self.builder = CopyBuilder(self.source,
                                   self.target,
                                   delete_orphans=True)
        self.source.collection.insert_many(self.old_docs)
        self.source.update(self.new_docs, update_lu=False)
        self.target.collection.insert_many(self.old_docs)

        deletion_criteria = {"k": {"$in": list(range(5))}}
        self.source.collection.delete_many(deletion_criteria)
        self.builder.run()

        self.assertEqual(
            self.target.collection.count_documents(deletion_criteria), 0)
        self.assertEqual(self.target.query_one(criteria={"k": 5})["v"], "new")
        self.assertEqual(self.target.query_one(criteria={"k": 10})["v"], "old")

    def test_incremental_false(self):
        tic = datetime.now()
        toc = tic + timedelta(seconds=1)
        keys = list(range(20))
        earlier = [{"lu": tic, "k": k, "v": "val"} for k in keys]
        later = [{"lu": toc, "k": k, "v": "val"} for k in keys]
        self.source.collection.insert_many(earlier)
        self.target.collection.insert_many(later)
        query = {"k": {"$gt": 5}}
        self.builder = CopyBuilder(self.source,
                                   self.target,
                                   incremental=False,
                                   query=query)
        self.builder.run()
        docs = sorted(self.target.query(), key=lambda d: d["k"])
        self.assertTrue(all(d["lu"] == tic) for d in docs[5:])
        self.assertTrue(all(d["lu"] == toc) for d in docs[:5])
class JointStoreTest(unittest.TestCase):
    def setUp(self):
        self.jointstore = JointStore("maggma_test", ["test1", "test2"])
        self.jointstore.connect()
        self.jointstore.collection.drop()
        self.jointstore.collection.insert_many([{
            "task_id":
            k,
            "my_prop":
            k + 1,
            "last_updated":
            datetime.utcnow(),
            "category":
            k // 5
        } for k in range(10)])
        self.jointstore.collection.database["test2"].drop()
        self.jointstore.collection.database["test2"].insert_many([{
            "task_id":
            2 * k,
            "your_prop":
            k + 3,
            "last_updated":
            datetime.utcnow(),
            "category2":
            k // 3
        } for k in range(5)])
        self.test1 = MongoStore("maggma_test", "test1")
        self.test1.connect()
        self.test2 = MongoStore("maggma_test", "test2")
        self.test2.connect()

    def test_query(self):
        # Test query all
        docs = list(self.jointstore.query())
        self.assertEqual(len(docs), 10)
        docs_w_field = [d for d in docs if "test2" in d]
        self.assertEqual(len(docs_w_field), 5)
        docs_w_field = sorted(docs_w_field, key=lambda x: x['task_id'])
        self.assertEqual(docs_w_field[0]['test2']['your_prop'], 3)
        self.assertEqual(docs_w_field[0]['task_id'], 0)
        self.assertEqual(docs_w_field[0]['my_prop'], 1)

    def test_query_one(self):
        doc = self.jointstore.query_one()
        self.assertEqual(doc['my_prop'], doc['task_id'] + 1)
        # Test limit properties
        doc = self.jointstore.query_one(properties=['test2', 'task_id'])
        self.assertEqual(doc['test2']['your_prop'], doc['task_id'] + 3)
        self.assertIsNone(doc.get("my_prop"))
        # Test criteria
        doc = self.jointstore.query_one(criteria={"task_id": {"$gte": 10}})
        self.assertIsNone(doc)
        doc = self.jointstore.query_one(
            criteria={"test2.your_prop": {
                "$gt": 6
            }})
        self.assertEqual(doc['task_id'], 8)

        # Test merge_at_root
        self.jointstore.merge_at_root = True

        # Test merging is working properly
        doc = self.jointstore.query_one(criteria={"task_id": 2})
        self.assertEqual(doc['my_prop'], 3)
        self.assertEqual(doc['your_prop'], 4)

        # Test merging is allowing for subsequent match
        doc = self.jointstore.query_one(criteria={"your_prop": {"$gt": 6}})
        self.assertEqual(doc['task_id'], 8)

    def test_distinct(self):
        dyour_prop = self.jointstore.distinct("test2.your_prop")
        self.assertEqual(set(dyour_prop), {k + 3 for k in range(5)})
        dmy_prop = self.jointstore.distinct("my_prop")
        self.assertEqual(set(dmy_prop), {k + 1 for k in range(10)})
        dmy_prop_cond = self.jointstore.distinct(
            "my_prop", {"test2.your_prop": {
                "$gte": 5
            }})
        self.assertEqual(set(dmy_prop_cond), {5, 7, 9})

    def test_last_updated(self):
        doc = self.jointstore.query_one({"task_id": 0})
        test1doc = self.test1.query_one({"task_id": 0})
        test2doc = self.test2.query_one({"task_id": 0})
        self.assertEqual(test2doc['last_updated'], doc['last_updated'])
        self.assertNotEqual(test1doc['last_updated'], doc['last_updated'])
        # Swap the two
        test2date = test2doc['last_updated']
        test2doc['last_updated'] = test1doc['last_updated']
        test1doc['last_updated'] = test2date
        self.test1.update([test1doc], update_lu=False)
        self.test2.update([test2doc], update_lu=False)
        doc = self.jointstore.query_one({"task_id": 0})
        test1doc = self.test1.query_one({"task_id": 0})
        test2doc = self.test2.query_one({"task_id": 0})
        self.assertEqual(test1doc['last_updated'], doc['last_updated'])
        self.assertNotEqual(test2doc['last_updated'], doc['last_updated'])
        # Check also that still has a field if no task2 doc
        doc = self.jointstore.query_one({"task_id": 1})
        self.assertIsNotNone(doc['last_updated'])

    def test_groupby(self):
        docs = list(self.jointstore.groupby("category"))
        self.assertEqual(len(docs[0]['docs']), 5)
        self.assertEqual(len(docs[1]['docs']), 5)
        docs = list(self.jointstore.groupby("test2.category2"))
        docs_by_id = {get(d, '_id.test2.category2'): d['docs'] for d in docs}
        self.assertEqual(len(docs_by_id[None]), 5)
        self.assertEqual(len(docs_by_id[0]), 3)
        self.assertEqual(len(docs_by_id[1]), 2)