docs: def map(self, experiment, new_reg_fields=None, joinBy=None, refName="REF", expName="EXP"):
          """
          *Wrapper of* ``MAP``
  
          MAP is a non-symmetric operator over two datasets, respectively called
          reference and experiment. The operation computes, for each sample in 
          the experiment dataset, aggregates over the values of the experiment 
          regions that intersect with a region in a reference sample, for each 
          region of each sample in the reference dataset; we say that experiment 
          regions are mapped to the reference regions.
          The number of generated output samples is the Cartesian product of the samples 
          in the two input datasets; each output sample has the same regions as the related 
          input reference sample, with their attributes and values, plus the attributes 
          computed as aggregates over experiment region values. Output sample metadata 
          are the union of the related input sample metadata, whose attribute names are 
          prefixed with their input dataset name. 
          For each reference sample, the MAP operation produces a matrix like structure,
          called genomic space, where each experiment sample is associated with a row, 
          each reference region with a column, and each matrix row is a vector of numbers
          - the aggregates computed during MAP execution. When the features of the reference 
          regions are unknown, the MAP helps in extracting the most interesting regions 
          out of many candidates. 
          
          :param experiment: a GMQLDataset
          :param new_reg_fields: an optional dictionary of the form 
                 {'new_field_1': AGGREGATE_FUNCTION(field), ...}
                                  
          :param joinBy: optional list of metadata
          :param refName: name that you want to assign to the reference dataset
          :param expName: name that you want to assign to the experiment dataset
          :return: a new GMQLDataset
  
          In the following example, we map the regions of Example_Dataset_2 on the ones of Example_Dataset_1 and for
          each region of Example_Dataset_1 we ouput the average Pvalue and number of mapped regions of Example_Dataset_2.
          In addition we specify that the output region fields and metadata attributes will have the `D1` and `D2` suffixes
          respectively for attributes and fields belonging the Example_Dataset_1 and Example_Dataset_2::
  
              import gmql as gl
  
              d1 = gl.get_example_dataset("Example_Dataset_1")
              d2 = gl.get_example_dataset("Example_Dataset_2")
  
              result = d1.map(experiment=d2, refName="D1", expName="D2",
                              new_reg_fields={"avg_pValue": gl.AVG("pvalue")})
  
          """
          if isinstance(experiment, GMQLDataset):
              other_idx = experiment.__index
          else:
              raise TypeError("experiment must be a GMQLDataset. "
                              "{} was provided".format(type(experiment)))
  
          aggregates = []
          if isinstance(new_reg_fields, dict):
              expBuild = self.pmg.getNewExpressionBuilder(experiment.__index)
              for k in new_reg_fields.keys():
                  if isinstance(k, str):
                      item = new_reg_fields[k]
                      if isinstance(item, (SUM, MIN, MAX, AVG, BAG, BAGD,
                                           MEDIAN, COUNT)):
                          op_name = item.get_aggregate_name()
                          op_argument = item.get_argument()
                          if op_argument is None:
                              op_argument = none()
                          else:
                              op_argument = Some(op_argument)
                          regsToReg = expBuild.getRegionsToRegion(op_name, k, op_argument)
                          aggregates.append(regsToReg)
                      else:
                          raise TypeError("The items in new_reg_fields must be Aggregates (SUM, MIN, MAX, AVG, BAG, BAGD, "
                                          "MEDIAN, COUNT)"
                                          " {} was provided".format(type(item)))
                  else:
                      raise TypeError("The key of new_reg_fields must be a string. "
                                      "{} was provided".format(type(k)))
          elif new_reg_fields is None:
              pass
          else:
              raise TypeError("new_reg_fields must be a list of dictionary. "
                              "{} was provided".format(type(new_reg_fields)))
  
          if isinstance(joinBy, list) and \
              all([isinstance(x, str) for x in joinBy]):
              metaJoinCondition = Some(self.opmng.getMetaJoinCondition(joinBy))
          elif joinBy is None:
              metaJoinCondition = none()
          else:
              raise TypeError("joinBy must be a list of strings. "
                              "{} was found".format(type(joinBy)))
  
          if not isinstance(expName, str):
              raise TypeError("expName must be a string. {} was provided".format(type(expName)))
  
          if not isinstance(refName, str):
              raise TypeError("refName must be a string. {} was provided".format(type(expName)))
  
          new_index = self.opmng.map(self.__index, other_idx, metaJoinCondition,
                                     aggregates, refName, expName)
          new_local_sources, new_remote_sources = self.__combine_sources(self, experiment)
          new_location = self.__combine_locations(self, experiment)
          return GMQLDataset(index=new_index, location=new_location,
                             local_sources=new_local_sources,
                             remote_sources=new_remote_sources,
                             meta_profile=self.meta_profile)