def project(self, projected_meta=None, new_attr_dict=None, all_but_meta=None,
                projected_regs=None, new_field_dict=None, all_but_regs=None):
        """
        *Wrapper of* ``PROJECT``

        The PROJECT operator creates, from an existing dataset, a new dataset with all the samples
        (with their regions and region values) in the input one, but keeping for each sample in the input
        dataset only those metadata and/or region attributes expressed in the operator parameter list.
        Region coordinates and values of the remaining metadata and region attributes remain equal
        to those in the input dataset. Differently from the SELECT operator, PROJECT allows to:
            * Remove existing metadata and/or region attributes from a dataset;
            * Create new metadata and/or region attributes to be added to the result.

        :param projected_meta: list of metadata attributes to project on
        :param new_attr_dict: an optional dictionary of the form {'new_meta_1': function1,
               'new_meta_2': function2, ...} in which every function computes
               the new metadata attribute based on the values of the others
        :param all_but_meta: list of metadata attributes that must be excluded from the projection
        :param projected_regs: list of the region fields to select
        :param new_field_dict: an optional dictionary of the form {'new_field_1':
               function1, 'new_field_2': function2, ...} in which every function
               computes the new region field based on the values of the others
        :param all_but_regs: list of region fields that must be excluded from the projection
        :return: a new GMQLDataset
        """
        projected_meta_exists = False
        if isinstance(projected_meta, list) and \
                all([isinstance(x, str) for x in projected_meta]):
            projected_meta = Some(projected_meta)
            projected_meta_exists = True
        elif projected_meta is None:
            projected_meta = none()
        else:
            raise TypeError("projected_meta must be a list of strings or None."
                            " {} was provided".format(type(projected_meta)))

        if isinstance(new_attr_dict, dict):
            meta_ext = []
            expBuild = self.pmg.getNewExpressionBuilder(self.__index)
            for k in new_attr_dict.keys():
                item = new_attr_dict[k]
                if isinstance(k, str):
                    if isinstance(item, MetaField):
                        me = expBuild.createMetaExtension(k, item.getMetaExpression())
                    elif isinstance(item, int):
                        me = expBuild.createMetaExtension(k, expBuild.getMEType("int", str(item)))
                    elif isinstance(item, str):
                        me = expBuild.createMetaExtension(k, expBuild.getMEType("string", item))
                    elif isinstance(item, float):
                        me = expBuild.createMetaExtension(k, expBuild.getMEType("float", str(item)))
                    else:
                        raise TypeError("Type {} of item of new_attr_dict is not valid".format(type(item)))
                    meta_ext.append(me)
                else:
                    raise TypeError("The key of new_attr_dict must be a string. "
                                    "{} was provided".format(type(k)))
            meta_ext = Some(meta_ext)
        elif new_attr_dict is None:
            meta_ext = none()
        else:
            raise TypeError("new_attr_dict must be a dictionary."
                            " {} was provided".format(type(new_attr_dict)))

        if isinstance(all_but_meta, list) and \
            all([isinstance(x, str) for x in all_but_meta]):
            if not projected_meta_exists:
                all_but_meta = Some(all_but_meta)
                all_but_value = True
            else:
                raise ValueError("all_but_meta and projected_meta are mutually exclusive")
        elif all_but_meta is None:
            all_but_meta = none()
            all_but_value = False
        else:
            raise TypeError("all_but_meta must be a list of strings."
                            " {} was provided".format(type(all_but_meta)))
        projected_meta = all_but_meta if all_but_value else projected_meta

        projected_regs_exists = False
        if isinstance(projected_regs, list) and \
                all([isinstance(x, str) for x in projected_regs]):
            projected_regs = Some(projected_regs)
            projected_regs_exists = True
        elif projected_regs is None:
            projected_regs = none()
        else:
            raise TypeError("projected_regs must be a list of strings or None."
                            " {} was provided".format(type(projected_regs)))

        if isinstance(new_field_dict, dict):
            regs_ext = []
            expBuild = self.pmg.getNewExpressionBuilder(self.__index)
            for k in new_field_dict.keys():
                item = new_field_dict[k]
                if isinstance(k, str):
                    if isinstance(item, RegField):
                        re = expBuild.createRegionExtension(k, item.getRegionExpression())
                    elif isinstance(item, MetaField):
                        re = expBuild.createRegionExtension(k, item.reMetaNode)
                    elif isinstance(item, int):
                        re = expBuild.createRegionExtension(k, expBuild.getREType("float", str(item)))
                    elif isinstance(item, str):
                        re = expBuild.createRegionExtension(k, expBuild.getREType("string", item))
                    elif isinstance(item, float):
                        re = expBuild.createRegionExtension(k, expBuild.getREType("float", str(item)))
                    else:
                        raise TypeError("Type {} of item of new_field_dict is not valid".format(type(item)))
                    regs_ext.append(re)
                else:
                    raise TypeError("The key of new_field_dict must be a string. "
                                    "{} was provided".format(type(k)))
            regs_ext = Some(regs_ext)
        elif new_field_dict is None:
            regs_ext = none()
        else:
            raise TypeError("new_field_dict must be a dictionary."
                            " {} was provided".format(type(new_field_dict)))

        if isinstance(all_but_regs, list) and \
            all([isinstance(x, str) for x in all_but_regs]):
            if not projected_regs_exists:
                all_but_regs = Some(all_but_regs)
            else:
                raise ValueError("all_but_meta and projected_meta are mutually exclusive")
        elif all_but_regs is None:
            all_but_regs = none()
        else:
            raise TypeError("all_but_regs must be a list of strings."
                            " {} was provided".format(type(all_but_regs)))

        new_index = self.opmng.project(self.__index, projected_meta, meta_ext, all_but_value,
                                       projected_regs, all_but_regs, regs_ext)
        return GMQLDataset(index=new_index, location=self.location,
                           local_sources=self._local_sources, remote_sources=self._remote_sources,
                           meta_profile=self.meta_profile)