コード例 #1
0
    def composition_filter(self, fes):
        """
        Valid url parameter inputs:
           # 1. ?composition=Fe2O3
            2. ?composition=Fe-O
            3. ?composition={Fe,Ni}O
            4. ?composition={3d}2O3
        """
        request = self.request

        comp = request.GET.get('composition', False)
        if not comp:
            return fes

        if '{' and '}' in comp:
            c_dict_lst = parse_formula_regex(comp)
            f_lst = []
            for cd in c_dict_lst:
                f = ' '.join(['%s%g' % (k, cd[k]) for k in sorted(cd.keys())])
                f_lst.append(f)
            fes = fes.filter(composition__formula__in=f_lst)
        else:
            c_lst = comp.strip().split('-')
            cs = Composition.get_list(c_lst)
            if len(cs) == 1:
                c = cs[0]
            else:
                c = cs
            fes = fes.filter(composition=c)

        return fes
コード例 #2
0
    def evaluate(self, parse_Tree):
        if isinstance(parse_Tree, Tree):
            children = parse_Tree.children
            if len(children) == 1:
                return self.evaluate(children[0])
            elif len(children) == 2:
                op_fn = self.evaluate(children[0])
                return op_fn(self.evaluate(children[1]))
            elif len(children) == 3:
                if parse_Tree.data == "comparison":
                    db_prop = self.evaluate(children[0])
                    op_fn = self.evaluate(children[1])

                    if db_prop == "element":
                        return op_fn(self.db_keys[db_prop],
                                     self.evaluate(children[2]) + "_")

                    elif db_prop == "chemical_formula":
                        c_dict_lst = parse_formula_regex(
                            self.evaluate(children[2]))
                        f_lst = []
                        for cd in c_dict_lst:
                            f = " ".join([
                                "%s%g" % (k, cd[k]) for k in sorted(cd.keys())
                            ])
                            f_lst.append(f)
                        return op_fn(self.db_keys[db_prop], f_lst)

                    else:
                        if db_prop in list(self.db_keys.keys()):
                            _child_value = self.evaluate(children[2]).replace(
                                '"', "")
                            return op_fn(self.db_keys[db_prop], _child_value)
                        else:
                            error_msg = "Unknown property is queried : " + (
                                db_prop)
                            # print(error_msg)
                            return None

                else:
                    op_fn = self.evaluate(children[1])
                    return op_fn(self.evaluate(children[0]),
                                 self.evaluate(children[2]))
            else:
                error_msg = "Not compatible format. Tree has >3 children"
                # print(error_msg)
                return error_msg

        elif isinstance(parse_Tree, Token):
            if parse_Tree.type == "VALUE":
                return parse_Tree.value
            elif parse_Tree.type in ["NOT", "CONJUNCTION", "OPERATOR"]:
                return self.opers[parse_Tree.value]
        else:
            error_msg = "Not a Lark Tree or Token. Check the parser implementation"
            # print(error_msg)
            return  # (error_msg)
コード例 #3
0
    def evaluate(self, parse_Tree):
        if isinstance(parse_Tree, Tree):
            children = parse_Tree.children
            if len(children) == 1:
                return self.evaluate(children[0])
            elif len(children) == 2:
                op_fn = self.evaluate(children[0])
                return op_fn(self.evaluate(children[1]))
            elif len(children) == 3:
                if parse_Tree.data == 'comparison':
                    db_prop = self.evaluate(children[0])
                    op_fn = self.evaluate(children[1])

                    if db_prop == 'element':
                        return op_fn(self.db_keys[db_prop],
                                     self.evaluate(children[2]) + '_')

                    elif db_prop == 'chemical_formula':
                        c_dict_lst = parse_formula_regex(
                            self.evaluate(children[2]))
                        f_lst = []
                        for cd in c_dict_lst:
                            f = ' '.join([
                                '%s%g' % (k, cd[k]) for k in sorted(cd.keys())
                            ])
                            f_lst.append(f)
                        return op_fn(self.db_keys[db_prop], f_lst)

                    else:
                        if db_prop in self.db_keys.keys():
                            _child_value = self.evaluate(children[2]).replace(
                                '"', '')
                            return op_fn(self.db_keys[db_prop], _child_value)
                        else:
                            error_msg = "Unknown property is queried : " + (
                                db_prop)
                            #print(error_msg)
                            return None

                else:
                    op_fn = self.evaluate(children[1])
                    return op_fn(self.evaluate(children[0]),
                                 self.evaluate(children[2]))
            else:
                error_msg = "Not compatible format. Tree has >3 children"
                #print(error_msg)
                return (error_msg)

        elif isinstance(parse_Tree, Token):
            if parse_Tree.type == 'VALUE':
                return parse_Tree.value
            elif parse_Tree.type in ['NOT', 'CONJUNCTION', 'OPERATOR']:
                return self.opers[parse_Tree.value]
        else:
            error_msg = "Not a Lark Tree or Token. Check the parser implementation"
            #print(error_msg)
            return  #(error_msg)
コード例 #4
0
ファイル: entry_list_view.py プロジェクト: hegdevinayi/qmpy
    def composition_filter(self, entries):
        """
        Valid url parameter inputs:
            1. ?composition=Fe2O3
            2. ?composition=Fe-O
            3. ?composition={Fe,Ni}O
            4. ?composition={3d}2O3
            5. ?composition=include_(Fe,Mn)-O : (Fe OR Mn) AND O
            6. ?composition=include_Cl,O-H : Cl OR O AND H 
            6. ?composition=include_H-{3d} : 3d elements AND H
        """
        request = self.request

        comp = request.GET.get("composition", False)
        if not comp:
            return entries

        if not "include_" in comp:
            if "{" and "}" in comp:
                c_dict_lst = parse_formula_regex(comp)
                f_lst = []
                for cd in c_dict_lst:
                    f = " ".join(
                        ["%s%g" % (k, cd[k]) for k in sorted(cd.keys())])
                    f_lst.append(f)
                entries = entries.filter(composition__formula__in=f_lst)
            else:
                c_lst = comp.strip().split("-")
                cs = Composition.get_list(c_lst)
                if len(cs) == 1:
                    c = cs[0]
                else:
                    c = cs
                entries = entries.filter(composition=c)

        else:
            comp_in = comp.replace("include_", "")
            # t = Token(comp_in)
            # q = t.evaluate()
            q = query_to_Q(comp_in)
            entries = entries.filter(q)

        # comp_ex = request.GET.get('composition_exclude', False)
        # if comp_ex:
        #    cex_lst = Composition.get(comp_ex).comp.keys()
        #    while cex_lst:
        #        tmp_ex = cex_lst.pop()
        #        entries = entries.exclude(composition__element_set=tmp_ex)

        return entries
コード例 #5
0
    def composition_filter(self, fes):
        """
        Valid url parameter inputs:
           # 1. ?composition=Fe2O3
            2. ?composition=Fe-O
            3. ?composition={Fe,Ni}O
            4. ?composition={3d}2O3
        """
        request = self.request

        comp = request.GET.get("composition", False)
        if not comp:
            return fes

        if "{" and "}" in comp:
            c_dict_lst = parse_formula_regex(comp)
            f_lst = []
            for cd in c_dict_lst:
                f = " ".join(["%s%g" % (k, cd[k]) for k in sorted(cd.keys())])
                f_lst.append(f)
            fes = fes.filter(composition__formula__in=f_lst)
        elif "-" in comp:
            c_lst = comp.strip().split("-")
            dim = len(c_lst)
            q_lst = [
                Q(composition__element_list__contains=s + "_") for s in c_lst
            ]
            combined_q = reduce(operator.or_, q_lst)
            combined_q = reduce(
                operator.and_,
                [combined_q, Q(composition__ntypes__lte=dim)])

            ex_q_lst = [
                Q(composition__element_list__contains=e.symbol + "_")
                for e in Element.objects.exclude(symbol__in=c_lst)
            ]
            combined_q_not = reduce(operator.or_, ex_q_lst)

            fes = fes.filter(combined_q).exclude(combined_q_not)
        else:
            c = Composition.get(comp)
            fes = fes.filter(composition=c)

        return fes
コード例 #6
0
    def property_first_comparison(self, children):
        """
        This function is automatically called by the Transformer when it encounters a Tree
        with Tree.data = property_first_comparison

        As of now, all the supported value comparisons in OQMD's optimade implementation are
        property-first comparisons. Because of that, this function is called by each filter
        element

        Format of property-first comparison: "property operator value(s)"

        Example:
            stability < 0.05   :  Here, `stability` is the property, `<` is the operator,
                                  and `0.05` is the value
        """
        _property = children[0].children[0].value
        try:
            a = self.property_dict[_property]
        except:
            self.handle_error("T1", "Cannot resolve the property name",
                              _property)
            return

        if children[1] is None:
            self.handle_error(
                "T1", "Accompanying Operator or Value cannot be parsed",
                a.name)
            return

        operation_fn = children[1][0]
        b = children[1][1]

        if not (a.is_queryable and a.db_value):
            self.handle_error("T1", "Cannot be queried in filter", a.name)
            return

        if a.is_chem_form:
            c_dict_lst = parse_formula_regex(b)
            if len(c_dict_lst) == 1 and len(c_dict_lst[0].keys()) == 0:
                self.handle_error(
                    "T1", "Chemical formula {} cannot be parsed".format(b),
                    a.name)
                return
            b = [
                " ".join(["%s%g" % (k, cd[k]) for k in sorted(cd.keys())])
                for cd in c_dict_lst
            ]

        if operation_fn in self.logic_functions:
            if not a.is_logic_operable:
                self.handle_error(
                    "T1", "Cannot be queried with operators <,>,<=,>=", a.name)
                return
        try:
            return operation_fn(a, b)
        except ParseError as err:
            raise err
        except:
            self.handle_error("T1",
                              "Unknown error while converting to Django Q",
                              a.name)