docs: def index(self):
          """ Index all files/directories below the current BIDSNode. """
  
          config_list = self.config
          layout = self.layout
  
          for (dirpath, dirnames, filenames) in os.walk(self.path):
  
              # If layout configuration file exists, delete it
              layout_file = self.layout.config_filename
              if layout_file in filenames:
                  filenames.remove(layout_file)
  
              for f in filenames:
  
                  abs_fn = os.path.join(self.path, f)
  
                  # Skip files that fail validation, unless forcibly indexing
                  if not self.force_index and not layout._validate_file(abs_fn):
                      continue
  
                  bf = BIDSFile(abs_fn, self)
  
                  # Extract entity values
                  match_vals = {}
                  for e in self.available_entities.values():
                      m = e.match_file(bf)
                      if m is None and e.mandatory:
                          break
                      if m is not None:
                          match_vals[e.name] = (e, m)
  
                  # Create Entity <=> BIDSFile mappings
                  if match_vals:
                      for name, (ent, val) in match_vals.items():
                          bf.entities[name] = val
                          ent.add_file(bf.path, val)
  
                  self.files.append(bf)
                  # Also add to the Layout's master list
                  self.layout.files[bf.path] = bf
  
              root_node = self if self.root is None else self.root
  
              for d in dirnames:
  
                  d = os.path.join(dirpath, d)
  
                  # Derivative directories must always be added separately and
                  # passed as their own root, so terminate if passed.
                  if d.startswith(os.path.join(self.layout.root, 'derivatives')):
                      continue
  
                  # Skip directories that fail validation, unless force_index
                  # is defined, in which case we have to keep scanning, in the
                  # event that a file somewhere below the current level matches.
                  # Unfortunately we probably can't do much better than this
                  # without a lot of additional work, because the elements of
                  # .force_index can be SRE_Patterns that match files below in
                  # unpredictable ways.
                  if check_path_matches_patterns(d, self.layout.force_index):
                      self.force_index = True
                  else:
                      valid_dir = layout._validate_dir(d)
                      # Note the difference between self.force_index and
                      # self.layout.force_index.
                      if not valid_dir and not self.layout.force_index:
                          continue
  
                  child_class = self._get_child_class(d)
                  # TODO: filter the config files based on include/exclude rules
                  child = child_class(d, config_list, root_node, self,
                                      force_index=self.force_index)
  
                  if self.force_index or valid_dir:
                      self.children.append(child)
  
              # prevent subdirectory traversal
              break