docs: def _iterate(self, pipeline, to_process_array, subject_inds, visit_inds):
          """
          Generate nodes that iterate over subjects and visits in the study that
          need to be processed by the pipeline
  
          Parameters
          ----------
          pipeline : Pipeline
              The pipeline to add iter_nodes for
          to_process_array : 2-D numpy.array[bool]
              A two-dimensional boolean array, where rows correspond to
              subjects and columns correspond to visits in the repository. True
              values represent a combination of subject & visit ID to process
              the session for
          subject_inds : dct[str, int]
              A mapping of subject ID to row index in the 'to_process' array
          visit_inds : dct[str, int]
              A mapping of visit ID to column index in the 'to_process' array
  
          Returns
          -------
          iter_nodes : dict[str, Node]
              A dictionary containing the nodes to iterate over all subject/visit
              IDs to process for each input frequency
          """
          # Check to see whether the subject/visit IDs to process (as specified
          # by the 'to_process' array) can be factorized into indepdent nodes,
          # i.e. all subjects to process have the same visits to process and
          # vice-versa.
          factorizable = True
          if len(list(pipeline.iterators())) == 2:
              nz_rows = to_process_array[to_process_array.any(axis=1), :]
              ref_row = nz_rows[0, :]
              factorizable = all((r == ref_row).all() for r in nz_rows)
          # If the subject/visit IDs to process cannot be factorized into
          # indepedent iterators, determine which to make make dependent on the
          # other in order to avoid/minimise duplicatation of download attempts
          dependent = None
          if not factorizable:
              input_freqs = list(pipeline.input_frequencies)
              # By default pick iterator the one with the most IDs to
              # iterate to be the dependent in order to reduce the number of
              # nodes created and any duplication of download attempts across
              # the nodes (if both 'per_visit' and 'per_subject' inputs are
              # required
              num_subjs, num_visits = nz_rows[:, nz_rows.any(axis=0)].shape
              if num_subjs > num_visits:
                  dependent = self.study.SUBJECT_ID
              else:
                  dependent = self.study.VISIT_ID
              if 'per_visit' in input_freqs:
                  if 'per_subject' in input_freqs:
                      logger.warning(
                          "Cannot factorize sessions to process into independent"
                          " subject and visit iterators and both 'per_visit' and"
                          " 'per_subject' inputs are used by pipeline therefore"
                          " per_{} inputs may be cached twice".format(
                              dependent[:-3]))
                  else:
                      dependent = self.study.SUBJECT_ID
              elif 'per_subject' in input_freqs:
                  dependent = self.study.VISIT_ID
          # Invert the index dictionaries to get index-to-ID maps
          inv_subj_inds = {v: k for k, v in subject_inds.items()}
          inv_visit_inds = {v: k for k, v in visit_inds.items()}
          # Create iterator for subjects
          iter_nodes = {}
          if self.study.SUBJECT_ID in pipeline.iterators():
              fields = [self.study.SUBJECT_ID]
              if dependent == self.study.SUBJECT_ID:
                  fields.append(self.study.VISIT_ID)
              # Add iterator node named after subject iterator
              subj_it = pipeline.add(self.study.SUBJECT_ID,
                                     IdentityInterface(fields))
              if dependent == self.study.SUBJECT_ID:
                  # Subjects iterator is dependent on visit iterator (because of
                  # non-factorizable IDs)
                  subj_it.itersource = ('{}_{}'.format(pipeline.name,
                                                       self.study.VISIT_ID),
                                        self.study.VISIT_ID)
                  subj_it.iterables = [(
                      self.study.SUBJECT_ID,
                      {inv_visit_inds[n]: [inv_subj_inds[m]
                                           for m in col.nonzero()[0]]
                       for n, col in enumerate(to_process_array.T)})]
              else:
                  subj_it.iterables = (
                      self.study.SUBJECT_ID,
                      [inv_subj_inds[n]
                       for n in to_process_array.any(axis=1).nonzero()[0]])
              iter_nodes[self.study.SUBJECT_ID] = subj_it
          # Create iterator for visits
          if self.study.VISIT_ID in pipeline.iterators():
              fields = [self.study.VISIT_ID]
              if dependent == self.study.VISIT_ID:
                  fields.append(self.study.SUBJECT_ID)
              # Add iterator node named after visit iterator
              visit_it = pipeline.add(self.study.VISIT_ID,
                                      IdentityInterface(fields))
              if dependent == self.study.VISIT_ID:
                  visit_it.itersource = ('{}_{}'.format(pipeline.name,
                                                        self.study.SUBJECT_ID),
                                         self.study.SUBJECT_ID)
                  visit_it.iterables = [(
                      self.study.VISIT_ID,
                      {inv_subj_inds[m]:[inv_visit_inds[n]
                                         for n in row.nonzero()[0]]
                       for m, row in enumerate(to_process_array)})]
              else:
                  visit_it.iterables = (
                      self.study.VISIT_ID,
                      [inv_visit_inds[n]
                       for n in to_process_array.any(axis=0).nonzero()[0]])
              iter_nodes[self.study.VISIT_ID] = visit_it
          if dependent == self.study.SUBJECT_ID:
              pipeline.connect(visit_it, self.study.VISIT_ID,
                               subj_it, self.study.VISIT_ID)
          if dependent == self.study.VISIT_ID:
              pipeline.connect(subj_it, self.study.SUBJECT_ID,
                               visit_it, self.study.SUBJECT_ID)
          return iter_nodes