docs: @Override
    public void initializeFromFile(TreeIndexHeader hdr, PageFile<N> file) {
      XTreeHeader header = (XTreeHeader) hdr;
      super.dirCapacity = header.getDirCapacity();
      super.leafCapacity = header.getLeafCapacity();
      super.dirMinimum = header.getDirMinimum();
      super.leafMinimum = header.getLeafMinimum();
      settings.min_fanout = header.getMin_fanout();
      this.num_elements = header.getNumberOfElements();
      this.dimensionality = header.getDimensionality();
      settings.max_overlap = header.getMaxOverlap();
      long superNodeOffset = header.getSupernode_offset();
  
      if(getLogger().isDebugging()) {
        getLogger().debugFine(new StringBuilder(200).append(getClass()).append("\n file = ").append(file.getClass()).toString());
      }
  
      // reset page id maintenance
      file.setNextPageID((int) (superNodeOffset / header.getPageSize()));
  
      // read supernodes (if there are any)
      if(superNodeOffset > 0) {
        RandomAccessFile ra_file = ((PersistentPageFile<?>) file).getFile();
        long offset = header.getReservedPages() * file.getPageSize() + superNodeOffset;
        int bs = 0 // omit this: 4 // EMPTY_PAGE or FILLED_PAGE ?
            + 4 // id
            + 1 // isLeaf
            + 1 // isSupernode
            + 4 // number of entries
            + 4; // capacity
        byte[] buffer = new byte[bs];
        try {
          // go to supernode region
          ra_file.seek(offset);
          while(ra_file.getFilePointer() + file.getPageSize() <= ra_file.length()) {
            // file.countRead();
            ra_file.read(buffer);
            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(buffer));
            int id = ois.readInt();
            ois.readBoolean(); // iLeaf
            boolean supernode = ois.readBoolean();
            if(!supernode) {
              throw new IllegalStateException("Non-supernode at supernode position '" + superNodeOffset + "'");
            }
            int numEntries = ois.readInt();
            int capacity = ois.readInt();
            ois.close();
            N page;
            try {
              page = getNodeClass().newInstance();
            }
            catch(IllegalAccessException e) {
              throw new AbortException("AccessException instantiating a supernode", e);
            }
            catch(InstantiationException e) {
              throw new AbortException("InstantiationException instantiating a supernode", e);
            }
            // file.countRead();
            ra_file.seek(offset);
            byte[] superbuffer = new byte[file.getPageSize() * (int) Math.ceil((double) capacity / dirCapacity)];
            // increase offset for the next position seek
            offset += superbuffer.length;
            ra_file.read(superbuffer);
            ois = new ObjectInputStream(new ByteArrayInputStream(buffer));
            try {
              // read from file and add to supernode map
              page.readSuperNode(ois, this);
            }
            catch(ClassNotFoundException e) {
              throw new AbortException("ClassNotFoundException when loading a supernode", e);
            }
            assert numEntries == page.getNumEntries();
            assert capacity == page.getCapacity();
            assert id == page.getPageID();
          }
        }
        catch(IOException e) {
          throw new RuntimeException("IOException caught when loading tree from file." + e);
        }
      }
  
      super.initialized = true;
  
      // compute height
      super.height = computeHeight();
  
      if(getLogger().isDebugging()) {
        getLogger().debugFine(new StringBuilder(100).append(getClass()).append("\n height = ").append(height).toString());
      }
    }