@Override
  protected Object privateExecuteIn(final IScope scope) throws GamaRuntimeException {
    // IGraph data = createData(scope);
    IGraph g = Cast.asGraph(scope, getFacetValue(scope, IKeyword.GRAPH));
    int thread_number =
        Cast.asInt(
            scope,
            getFacetValue(
                scope, GraphForceAtlasLayoutStatement.THREAD_NUMBER, THREAD_NUMBER_DEFAULT));
    boolean dissuade_hubs =
        Cast.asBool(
            scope,
            getFacetValue(
                scope, GraphForceAtlasLayoutStatement.DISSUADE_HUBS, DISSUADE_HUBS_DEFAULT));
    boolean linlog_mode =
        Cast.asBool(
            scope,
            getFacetValue(scope, GraphForceAtlasLayoutStatement.LINLOG_MODE, LINLOG_MODE_DEFAULT));
    boolean prevent_overlap =
        Cast.asBool(
            scope,
            getFacetValue(
                scope, GraphForceAtlasLayoutStatement.PREVENT_OVERLAP, PREVENT_OVERLAP_DEFAULT));
    double edge_weight_influence =
        Cast.asFloat(
            scope,
            getFacetValue(
                scope,
                GraphForceAtlasLayoutStatement.EDGE_WEIGHT_INFLUENCE,
                EDGE_WEIGHT_INFLUENCE_DEFAULT));
    double scaling =
        Cast.asFloat(
            scope, getFacetValue(scope, GraphForceAtlasLayoutStatement.SCALING, SCALING_DEFAULT));
    boolean stronger_gravity =
        Cast.asBool(
            scope,
            getFacetValue(
                scope, GraphForceAtlasLayoutStatement.STRONGER_GRAVITY, STRONGER_GRAVITY_DEFAULT));
    double gravity =
        Cast.asFloat(
            scope, getFacetValue(scope, GraphForceAtlasLayoutStatement.GRAVITY, GRAVITY_DEFAULT));
    double tolerance =
        Cast.asFloat(
            scope,
            getFacetValue(scope, GraphForceAtlasLayoutStatement.TOLERANCE, TOLERANCE_DEFAULT));
    boolean approximate_repulsion =
        Cast.asBool(
            scope,
            getFacetValue(
                scope,
                GraphForceAtlasLayoutStatement.APPROXIMATE_REPULSION,
                APPROXIMATE_REPULSION_DEFAULT));
    double approximation =
        Cast.asFloat(
            scope,
            getFacetValue(
                scope, GraphForceAtlasLayoutStatement.APPROXIMATION, APPROXIMATION_DEFAULT));
    int nb_steps =
        Cast.asInt(
            scope, getFacetValue(scope, GraphForceAtlasLayoutStatement.NB_STEPS, NB_STEPS_DEFAULT));
    Object bp1 = getFacetValue(scope, GraphForceAtlasLayoutStatement.BOUNDED_P1, null);
    Object bp2 = getFacetValue(scope, GraphForceAtlasLayoutStatement.BOUNDED_P2, null);
    // public static IGraph YifanHuLayout_Step_Unlimited(final IGraph g, double optimal_distance,
    // double initial_step, double step_ratio, double convergence_threshold, double
    // barnes_hut_theta) {
    initializing();
    // System.out.println("ForceAtlas2 algorithm (by step), starting.");
    // System.out.println("converting ...");
    IGraph_to_GraphModel(g);
    // System.out.println("initializing ...");
    ForceAtlas2 fa2Layout = new ForceAtlas2(new ForceAtlas2Builder());
    initializing_GraphModel(g);
    fa2Layout.resetPropertiesValues();
    fa2Layout.setGraphModel(graph_model);
    fa2Layout.setOutboundAttractionDistribution(dissuade_hubs);
    fa2Layout.setLinLogMode(linlog_mode);
    fa2Layout.setAdjustSizes(prevent_overlap);
    fa2Layout.setEdgeWeightInfluence(edge_weight_influence);
    fa2Layout.setScalingRatio(scaling);
    fa2Layout.setStrongGravityMode(stronger_gravity);
    fa2Layout.setGravity(gravity);
    fa2Layout.setJitterTolerance(tolerance);
    fa2Layout.setBarnesHutOptimize(approximate_repulsion);
    fa2Layout.setBarnesHutTheta(approximation);
    // System.out.println("working ...");
    fa2Layout.initAlgo();
    // System.out.println("working ...");
    // int nbsteps=1;
    // for (int i = 0; i < nbsteps && fa2Layout.canAlgo(); i++){
    for (int i = 0; i < nb_steps; i++) {
      fa2Layout.goAlgo();
    }
    fa2Layout.endAlgo();
    // fa2Layout.goAlgo();
    // fa2Layout.endAlgo();
    if (bp1 != null && bp2 != null) {
      ILocation p1 = Cast.asPoint(scope, bp1);
      ILocation p2 = Cast.asPoint(scope, bp2);
      Update_locations(
          g,
          FastMath.min(p1.getX(), p2.getX()),
          FastMath.min(p1.getY(), p2.getY()),
          FastMath.max(p1.getX(), p2.getX()),
          FastMath.max(p1.getY(), p2.getY()));
    } else {
      Update_locations(g);
    }

    // System.out.println("ended.");

    return g;
  }