setupHierarchicalLayout() {
    if (
      this.options.hierarchical.enabled === true &&
      this.body.nodeIndices.length > 0
    ) {
      // get the size of the largest hubs and check if the user has defined a level for a node.
      let node, nodeId;
      let definedLevel = false;
      let undefinedLevel = false;
      this.lastNodeOnLevel = {};
      this.hierarchical = new HierarchicalStatus();

      for (nodeId in this.body.nodes) {
        if (Object.prototype.hasOwnProperty.call(this.body.nodes, nodeId)) {
          node = this.body.nodes[nodeId];
          if (node.options.level !== undefined) {
            definedLevel = true;
            this.hierarchical.levels[nodeId] = node.options.level;
          } else {
            undefinedLevel = true;
          }
        }
      }

      // if the user defined some levels but not all, alert and run without hierarchical layout
      if (undefinedLevel === true && definedLevel === true) {
        throw new Error(
          "To use the hierarchical layout, nodes require either no predefined levels" +
            " or levels have to be defined for all nodes."
        );
      } else {
        // define levels if undefined by the users. Based on hubsize.
        if (undefinedLevel === true) {
          const sortMethod = this.options.hierarchical.sortMethod;
          if (sortMethod === "hubsize") {
            this._determineLevelsByHubsize();
          } else if (sortMethod === "directed") {
            this._determineLevelsDirected();
          } else if (sortMethod === "custom") {
            this._determineLevelsCustomCallback();
          }
        }

        // fallback for cases where there are nodes but no edges
        for (const nodeId in this.body.nodes) {
          if (Object.prototype.hasOwnProperty.call(this.body.nodes, nodeId)) {
            this.hierarchical.ensureLevel(nodeId);
          }
        }
        // check the distribution of the nodes per level.
        const distribution = this._getDistribution();

        // get the parent children relations.
        this._generateMap();

        // place the nodes on the canvas.
        this._placeNodesByHierarchy(distribution);

        // condense the whitespace.
        this._condenseHierarchy();

        // shift to center so gravity does not have to do much
        this._shiftToCenter();
      }
    }
  }
This is the main function to layout the nodes in a hierarchical way.
It checks if the node details are supplied correctly
@private