docs: private Clustering<OPTICSModel> extractClusters(ClusterOrder clusterOrderResult, Relation<?> relation, double ixi, int minpts) {
      ArrayDBIDs clusterOrder = clusterOrderResult.ids;
      DoubleDataStore reach = clusterOrderResult.reachability;
  
      DBIDArrayIter tmp = clusterOrder.iter();
      DBIDVar tmp2 = DBIDUtil.newVar();
      double mib = 0.0;
      List<SteepArea> salist = keepsteep ? new ArrayList<SteepArea>() : null;
      List<SteepDownArea> sdaset = new ArrayList<>();
      final Clustering<OPTICSModel> clustering = new Clustering<>("OPTICS Xi-Clusters", "optics");
      HashSet<Cluster<OPTICSModel>> curclusters = new HashSet<>();
      HashSetModifiableDBIDs unclaimedids = DBIDUtil.newHashSet(relation.getDBIDs());
  
      FiniteProgress scanprog = LOG.isVerbose() ? new FiniteProgress("OPTICS Xi cluster extraction", clusterOrder.size(), LOG) : null;
      for(SteepScanPosition scan = new SteepScanPosition(clusterOrderResult); scan.hasNext();) {
        if(scanprog != null) {
          scanprog.setProcessed(scan.index, LOG);
        }
        // Update maximum-inbetween
        mib = MathUtil.max(mib, scan.getReachability());
        // The last point cannot be the start of a steep area.
        if(!scan.next.valid()) {
          break;
        }
        // Xi-steep down area
        if(scan.steepDown(ixi)) {
          // Update mib values with current mib and filter
          updateFilterSDASet(mib, sdaset, ixi);
          final double startval = scan.getReachability();
          mib = 0.;
          int startsteep = scan.index, endsteep = scan.index;
          for(scan.next(); scan.hasNext(); scan.next()) {
            // still steep - continue.
            if(scan.steepDown(ixi)) {
              endsteep = scan.index;
              continue;
            }
            // Not going downward at all - stop here.
            // Always stop looking after minpts "flat" steps.
            if(!scan.steepDown(1.0) || scan.index - endsteep > minpts) {
              break;
            }
          }
          final SteepDownArea sda = new SteepDownArea(startsteep, endsteep, startval, 0);
          if(LOG.isDebuggingFinest()) {
            LOG.debugFinest("New steep down area: " + sda.toString());
          }
          sdaset.add(sda);
          if(salist != null) {
            salist.add(sda);
          }
          continue;
        }
        // Xi-steep up area
        if(scan.steepUp(ixi)) {
          // Update mib values with current mib and filter
          updateFilterSDASet(mib, sdaset, ixi);
          final SteepUpArea sua;
          // Compute steep-up area
          {
            int startsteep = scan.index, endsteep = scan.index;
            mib = scan.getReachability();
            double esuccr = scan.getNextReachability();
            // Find end of steep-up-area, eventually updating mib again
            while(!Double.isInfinite(esuccr) && scan.hasNext()) {
              scan.next();
              // still steep - continue.
              if(scan.steepUp(ixi)) {
                endsteep = scan.index;
                mib = scan.getReachability();
                esuccr = scan.getNextReachability();
                continue;
              }
              // Not going upward - stop here.
              // Stop looking after minpts non-up steps.
              if(!scan.steepUp(1.0) || scan.index - endsteep > minpts) {
                break;
              }
            }
            if(Double.isInfinite(esuccr)) {
              scan.next();
            }
            sua = new SteepUpArea(startsteep, endsteep, esuccr);
            if(LOG.isDebuggingFinest()) {
              LOG.debugFinest("New steep up area: " + sua.toString());
            }
            if(salist != null) {
              salist.add(sua);
            }
          }
          // Validate and computer clusters
          // LOG.debug("SDA size:"+sdaset.size()+" "+sdaset);
          ListIterator<SteepDownArea> sdaiter = sdaset.listIterator(sdaset.size());
          // Iterate backwards for correct hierarchy generation.
          while(sdaiter.hasPrevious()) {
            SteepDownArea sda = sdaiter.previous();
            if(LOG.isDebuggingFinest()) {
              LOG.debugFinest("Comparing: eU=" + mib + " SDA: " + sda.toString());
            }
            // Condition 3b: end-of-steep-up > maximum-in-between lower
            if(mib * ixi < sda.getMib()) {
              if(LOG.isDebuggingFinest()) {
                LOG.debugFinest("mib * ixi = " + mib * ixi + " >= sda.getMib() = " + sda.getMib());
              }
              continue;
            }
            // By default, clusters cover both the steep up and steep down area
            int cstart = sda.getStartIndex(),
                cend = MathUtil.min(sua.getEndIndex(), clusterOrder.size() - 1);
            // However, we sometimes have to adjust this (Condition 4):
            {
              // Case b)
              if(sda.getMaximum() * ixi >= sua.getMaximum()) {
                while(cstart < cend && //
                    reach.doubleValue(tmp.seek(cstart + 1)) > sua.getMaximum()) {
                  cstart++;
                }
              }
              // Case c)
              else if(sua.getMaximum() * ixi >= sda.getMaximum()) {
                while(cend > cstart && //
                    reach.doubleValue(tmp.seek(cend - 1)) > sda.getMaximum()) {
                  cend--;
                }
              }
              // Case a) is the default
            }
            // MST-based filtering technique of Schubert:
            // ensure that the predecessor is in the current cluster.
            // This filter removes common artifacts from the Xi method
            if(!nocorrect) {
              double startval = clusterOrderResult.reachability.doubleValue(tmp.seek(cstart));
              simplify: while(cend > cstart) {
                tmp.seek(cend);
                // If the reachability is less than the first points', then there
                // must be some point inbetween that "reached" the current point.
                if(clusterOrderResult.reachability.doubleValue(tmp) < startval) {
                  break simplify;
                }
                clusterOrderResult.predecessor.assignVar(tmp, tmp2);
                // "Slow" search for predecessor:
                for(int i = cstart; i < cend; i++) {
                  if(DBIDUtil.equal(tmp2, tmp.seek(i))) {
                    break simplify;
                  }
                }
                // Not found, prune the last point
                if(LOG.isDebuggingFinest()) {
                  LOG.debugFinest("Pruned one point by predecessor rule.");
                }
                --cend;
              }
            }
            // Condition 3a: obey minpts
            if(cend - cstart + 1 < minpts) {
              if(LOG.isDebuggingFinest()) {
                LOG.debugFinest("MinPts not satisfied.");
              }
              continue;
            }
            // Build the cluster
            ModifiableDBIDs dbids = DBIDUtil.newArray();
            for(int idx = cstart; idx <= cend; idx++) {
              tmp.seek(idx);
              // Collect only unclaimed IDs.
              if(unclaimedids.remove(tmp)) {
                dbids.add(tmp);
              }
            }
            if(LOG.isDebuggingFine()) {
              LOG.debugFine("Found cluster with " + dbids.size() + " new objects, length " + (cend - cstart + 1));
            }
            OPTICSModel model = new OPTICSModel(cstart, cend);
            Cluster<OPTICSModel> cluster = new Cluster<>("Cluster_" + cstart + "_" + cend, dbids, model);
            // Build the hierarchy
            for(Iterator<Cluster<OPTICSModel>> iter = curclusters.iterator(); iter.hasNext();) {
              Cluster<OPTICSModel> clus = iter.next();
              OPTICSModel omodel = clus.getModel();
              if(model.getStartIndex() <= omodel.getStartIndex() && omodel.getEndIndex() <= model.getEndIndex()) {
                clustering.addChildCluster(cluster, clus);
                iter.remove(); // Not a top-level cluster
              }
            }
            curclusters.add(cluster);
          }
          continue;
        }
        // Flat - advance anyway.
        scan.next();
      }
      if(scanprog != null) {
        scanprog.setProcessed(clusterOrder.size(), LOG);
      }
      if(!unclaimedids.isEmpty()) {
        boolean noise = reach.doubleValue(tmp.seek(clusterOrder.size() - 1)) >= Double.POSITIVE_INFINITY;
        Cluster<OPTICSModel> allcluster = new Cluster<>(noise ? "Noise" : "Cluster", unclaimedids, noise, new OPTICSModel(0, clusterOrder.size() - 1));
        for(Cluster<OPTICSModel> cluster : curclusters) {
          clustering.addChildCluster(allcluster, cluster);
        }
        clustering.addToplevelCluster(allcluster);
      }
      else {
        for(Cluster<OPTICSModel> cluster : curclusters) {
          clustering.addToplevelCluster(cluster);
        }
      }
      clustering.addChildResult(clusterOrderResult);
      if(salist != null) {
        clusterOrderResult.addChildResult(new SteepAreaResult(salist));
      }
      return clustering;
    }