class_docstr: Class that handles hierarchical ROIs
  
  Parameters
  ----------
  k : int
    Number of ROI in the SubDomains object
  label : array of shape (domain.size), dtype=np.int_
    An array use to define which voxel belongs to which ROI.
    The label values greater than -1 correspond to subregions
    labelling. The labels are recomputed so as to be consecutive
    integers.
    The labels should not be accessed outside this class. One has to
    use the API mapping methods instead.
  features : dict {str: list of object, length=self.k}
    Describe the voxels features, grouped by ROI
  roi_features : dict {str: array-like, shape=(self.k, roi_feature_dim)
    Describe the ROI features. A special feature, `id`, is read-only and
    is used to give an unique identifier for region, which is persistent
    through the MROI objects manipulations. On should access the different
    ROI's features using ids.
  parents : np.ndarray, shape(self.k)
    self.parents[i] is the index of the parent of the i-th ROI.
  
  TODO: have the parents as a list of id rather than a list of indices.
class_docstr_tok: ["Class","that","handles","hierarchical","ROIs","Parameters","--","--","--","--","--","k",":","int","Number","of","ROI","in","the","SubDomains","object","label",":","array","of","shape","(","domain.size",")",",","dtype=np.int_","An","array","use","to","define","which","voxel","belongs","to","which","ROI",".","The","label","values","greater","than","-1","correspond","to","subregions","labelling",".","The","labels","are","recomputed","so","as","to","be","consecutive","integers",".","The","labels","should","not","be","accessed","outside","this","class",".","One","has","to","use","the","API","mapping","methods","instead",".","features",":","dict","{","str",":","list","of","object",",","length=self.k","}","Describe","the","voxels","features",",","grouped","by","ROI","roi_features",":","dict","{","str",":","array-like",",","shape=","(","self.k",",","roi_feature_dim",")","Describe","the","ROI","features",".","A","special","feature",",","`","id","`",",","is","read-only","and","is","used","to","give","an","unique","identifier","for","region",",","which","is","persistent","through","the","MROI","objects","manipulations",".","On","should","access","the","different","ROI","'s","features","using","ids",".","parents",":","np.ndarray",",","shape","(","self.k",")","self.parents","[","i","]","is","the","index","of","the","parent","of","the","i-th","ROI",".","TODO",":","have","the","parents","as","a","list","of","id","rather","than","a","list","of","indices","."]
docstr: Remove the non-valid ROIs by including them in
  their parents when it exists.
  
  Parameters
  ----------
  id_list: list of id (any hashable type)
    The id of the ROI to be merged into their parents.
    Nodes that are their own parent are unmodified.
  pull_features: list of str
    List of the ROI features that will be pooled from the children
    when they are merged into their parents. Otherwise, the receiving
    parent would keep its own ROI feature.
docstr_tok: ["Remove","the","non-valid","ROIs","by","including","them","in","their","parents","when","it","exists",".","Parameters","--","--","--","--","--","id_list",":","list","of","id","(","any","hashable","type",")","The","id","of","the","ROI","to","be","merged","into","their","parents",".","Nodes","that","are","their","own","parent","are","unmodified",".","pull_features",":","list","of","str","List","of","the","ROI","features","that","will","be","pooled","from","the","children","when","they","are","merged","into","their","parents",".","Otherwise",",","the","receiving","parent","would","keep","its","own","ROI","feature","."]
code: def merge_ascending(self, id_list, pull_features=None):
      """Remove the non-valid ROIs by including them in
      their parents when it exists.
  
      Parameters
      ----------
      id_list: list of id (any hashable type)
        The id of the ROI to be merged into their parents.
        Nodes that are their own parent are unmodified.
      pull_features: list of str
        List of the ROI features that will be pooled from the children
        when they are merged into their parents. Otherwise, the receiving
        parent would keep its own ROI feature.
      """
      if pull_features is None:
          pull_features = []
      if self.k == 0:
          return
      id_list = [k for k in self.get_id() if k in id_list]
  
      # relabel maps old labels to new labels
      relabel = np.arange(self.k)
  
      # merge nodes, one at a time
      for c_id in id_list:
          # define alias for clearer indexing
          c_pos = self.select_id(c_id)
          p_pos = self.parents[c_pos]
          p_id = self.get_id()[p_pos]
  
          if p_pos != c_pos:
              # this will be used in many places
              mask_pos = np.ones(self.k, np.bool_)
              mask_pos[c_pos] = False
  
              # set new parents
              self.parents = self.parents[mask_pos]
              self.parents[self.parents == c_pos] = p_pos
              self.parents[self.parents > c_pos] -= 1
              self.k -= 1
  
              # merge labels
              relabel[relabel == c_id] = p_id
  
              # compute new features
              for fid in list(self.features):
                  # replace feature
                  # (without the API since self is in an inconsistent state)
                  dj = self.get_feature(fid)
                  dj[p_pos] = np.hstack(
                      (
                          dj[self.select_id(c_id)],
                          dj[self.select_id(p_id)],
                      )
                  )
                  del dj[c_pos]
                  self.features[fid] = dj
  
              # compute new roi features
              for fid in list(self.roi_features):
                  dj = self.get_roi_feature(fid)
                  if fid in pull_features:
                      # modify only if `pull` requested
                      dj[p_pos] = dj[c_pos]
                  self.roi_features[fid] = dj[mask_pos]
  
      # update the labels
      self.label[self.label > -1] = relabel[self.label[self.label > -1]]
      self.recompute_labels()
  
imports: import numpy
  from nipy.algorithms.graph.field import field_from_coo_matrix_and_data
  from nipy.algorithms.graph.forest import Forest
  from nipy.algorithms.graph.graph import WeightedGraph
  from .mroi import SubDomains
label_desc: Use image node_id 7 for calling the HierarchicalROI obj's underlying member method code with example usage: obj.merge_ascending(id_list, pull_features) without return types