ArcGIS Pro 3.7 API Reference Guide
ArcGIS.Core.Data.Knowledge.Analytics Namespace / KnowledgeGraphFilteredFindPathsResults Class / ExtractPathsEntitiesAndRelationships Method
This can be null. When null, all paths are used. When non-null, only paths with indices in filterPathIndices are used.
Valid path indices verify: 0 <= index < 'CountPaths'
Example

In This Topic
    ExtractPathsEntitiesAndRelationships Method
    In This Topic
    Computes the entities and relationships associated to all or some of the result paths.
    Syntax
    Public Function ExtractPathsEntitiesAndRelationships( _
       ByVal filterPathIndices As SortedSet(Of ULong) _
    ) As PathsEntitiesAndRelationships
    public PathsEntitiesAndRelationships ExtractPathsEntitiesAndRelationships( 
       SortedSet<ulong> filterPathIndices
    )

    Parameters

    filterPathIndices
    This can be null. When null, all paths are used. When non-null, only paths with indices in filterPathIndices are used.
    Valid path indices verify: 0 <= index < 'CountPaths'

    Return Value

    Exceptions
    ExceptionDescription
     
    Remarks
    This method can throw exceptions if errors are found in the result paths Note: ExtractPathsEntitiesAndRelationships(null) will use all paths otherwise just the paths indentified by the path indices in filterPathIndices are used.
    Example
    Create Link Chart from FFP Results
    {
      //using ArcGIS.Core.Data.Knowledge.Extensions;
    
      await QueuedTask.Run(async () =>
      {
        var ffp_config = new CIMFilteredFindPathsConfiguration();
        ffp_config.Name = "Create Link Chart from FFP Results";
        //set up config
        //...
    
        var results = kg.RunFilteredFindPaths(ffp_config);
    
        var pathsEntitiesAndRelationships = results.ExtractPathsEntitiesAndRelationships(null);
    
        //Create a KG layer id set
        var kgLayerIdSet = KnowledgeGraphLayerIDSet.FromKnowledgeGraphIDSet(
          pathsEntitiesAndRelationships.ToKnowledgeGraphIDSet(
            KGResultContentFromFFP.EntitiesAndRelationships));
    
        //Create a brand new link chart with the results and show it
        var linkChart = MapFactory.Instance.CreateLinkChart("KG Intro", kg, kgLayerIdSet);
    
        var mapPane = await FrameworkApplication.Panes.CreateMapPaneAsync(linkChart);
        var linkChartView = mapPane.MapView;
    
        //Change layout algo to match the default used by the UI after FFP
        await linkChartView.SetLinkChartLayoutAsync(
          KnowledgeLinkChartLayoutAlgorithm.Hierarchical_TopToBottom);
    
        //Set root nodes - they correspond to the origin nodes of the result paths
        var kgLayerIdSetForRootNodes = KnowledgeGraphLayerIDSet.FromKnowledgeGraphIDSet(
          pathsEntitiesAndRelationships.ToKnowledgeGraphIDSet(
            KGResultContentFromFFP.OnlyPathsOriginEntities));
    
        //To correctly identify the ids in the link chart we must change the ids
        //from Geodatabase oids returned in the KnowledgeGraphLayerIDSet to the
        //temporary/synthetic oids used by layers in the link chart...
        var kg_layer = linkChart.GetLayersAsFlattenedList().OfType<KnowledgeGraphLayer>().First();
        var mapMembers = kg_layer.GetMapMembersAsFlattenedList();
        var oidDict = kgLayerIdSetForRootNodes.ToOIDDictionary();
        var mmDict = new Dictionary<MapMember, List<long>>();
        foreach (var kvp in oidDict)
        {
          var named_type = kvp.Key;
          foreach (var mm in mapMembers)
          {
            if (mm is LinkChartFeatureLayer fl_lc && fl_lc.IsEntity)
            {
              if (fl_lc.GetTypeName().ToLower() == named_type.ToLower())
              {
                var lc_oids = new List<long>();
                //these oids are from the geodatabase
                var oid_field = $"{fl_lc.GetTypeName()}.objectid";
                var id_list = string.Join(',', kvp.Value.ToArray());
                var where = $"{fl_lc.GetTypeName()}.objectid IN ({id_list})";
    
                var qf = new ArcGIS.Core.Data.QueryFilter()
                {
                  WhereClause = where,
                  SubFields = $"LC.OID,{oid_field}"//the 'LC.OID' oids are the ones
                                                   //we need for the mapmember id set
                                                   //in the link chart
                };
                var rc = fl_lc.Search(qf);
                var oid_idx = rc.FindField(oid_field);
                while (rc.MoveNext())
                {
                  var oid = (long)rc.Current[oid_idx];
                  var lc_oid = rc.Current.GetObjectID();
                  lc_oids.Add(lc_oid);
                }
                rc.Dispose();
                mmDict[fl_lc] = lc_oids;
                break;
              }
            }
          }
        }
    
        var mmIdSet = MapMemberIDSet.FromDictionary(mmDict);
        linkChartView.SetRootNodes(mmIdSet);
      });
    }
    Append to Link Chart from FFP Results
    {
      //using ArcGIS.Core.Data.Knowledge.Extensions;
    
      var linkChartView = MapView.Active;
    
      await QueuedTask.Run(async () =>
      {
        var ffp_config = new CIMFilteredFindPathsConfiguration();
        ffp_config.Name = "Append to Link Chart from FFP Results";
        //set up config
        //...
    
        var results = kg.RunFilteredFindPaths(ffp_config);
    
        var pathsEntitiesAndRelationships = results.ExtractPathsEntitiesAndRelationships(null);
    
        //Create a KG layer id set
        var kgLayerIdSet = KnowledgeGraphLayerIDSet.FromKnowledgeGraphIDSet(
          pathsEntitiesAndRelationships.ToKnowledgeGraphIDSet(
            KGResultContentFromFFP.EntitiesAndRelationships));
    
        var map = linkChartView.Map;
    
        if (!map.CanAppendToLinkChart(kgLayerIdSet))
          return;//not compatible
    
        map.AppendToLinkChart(kgLayerIdSet);
        //switch layout algo
        var algo = linkChartView.GetLinkChartLayout();
        if (algo != KnowledgeLinkChartLayoutAlgorithm.Hierarchical_TopToBottom)
        {
          //Change layout algo to match the default used by the UI after FFP
          await linkChartView.SetLinkChartLayoutAsync(
            KnowledgeLinkChartLayoutAlgorithm.Hierarchical_TopToBottom);
        }
    
        //To set link chart root nodes see 'Create Link Chart from FFP Results'
      });
    }
    List out FFP Results Origin, Destination, Other Entities
    {
      //using ArcGIS.Core.Data.Knowledge.Extensions;
    
      await QueuedTask.Run(async () =>
      {
        var ffp_config = new CIMFilteredFindPathsConfiguration();
        ffp_config.Name = "List out FFP Results Origin, Destination, Other Entities";
        //set up config
        //...
    
        var results = kg.RunFilteredFindPaths(ffp_config);
    
        if (results.CountPaths == 0)
        {
          System.Diagnostics.Debug.WriteLine("FFP returned no paths");
          return;
        }
    
        //print out paths by increasing length, min cost, max cost
        var path_by_len_indices = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingPathLength
                                    .Select(idx => idx.index);
        var path_by_min_cost = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingMinPathCost
                                    .Select(idx => idx.index);
        var path_by_max_cost = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingMaxPathCost
                                    .Select(idx => idx.index);
    
        var x = 0;
        StringBuilder sb = new StringBuilder();
    
        foreach (var path_indeces in new List<IEnumerable<long>> {
        path_by_len_indices,
        path_by_min_cost,
        path_by_max_cost})
        {
          if (x == 0)
            sb.AppendLine($"Entities by length: {path_by_len_indices.Count()}");
          else if (x == 1)
            sb.AppendLine($"Entities by min cost: {path_by_min_cost.Count()}");
          else if (x == 2)
            sb.AppendLine($"Entities by max cost: {path_by_max_cost.Count()}");
          x++;
          foreach (var path_idx in path_indeces)
          {
            var path = (ResultPath)results.MaterializePath(path_idx);
            sb.AppendLine(
              $"Path[{path_idx}] length: {path.Length}, min: {path.MinCost} max: {path.MaxCost}");
    
            var sorted_set = new SortedSet<ulong>();
            sorted_set.Add((ulong)path_idx);
            var per = results.ExtractPathsEntitiesAndRelationships(sorted_set);
    
            var origin_dest_uids = new List<string>();
            var sep = "";
    
            sb.Append(" Origin EntitiesUIDs: ");
            foreach (var idx in per.PathsOriginEntitiesUIDsIndexes)
            {
              //See 'List out FFP Results by Path Length, Min Cost, Max Cost' for
              //FormatID method above
              var uid = FormatID(per.EntitiesUIDs[idx].ToString());
              origin_dest_uids.Add(uid);
    
              var origin =
                $"{sep}{per.EntityTypeNames[per.EntityTypes[idx]]}:{uid}";
              sep = ", ";
              sb.Append($"{origin}");
            }
            sb.AppendLine("");
    
            sep = "";
            sb.Append(" Destination EntitiesUIDs: ");
            foreach (var idx in per.PathsDestinationEntitiesUIDsIndexes)
            {
              var uid = FormatID(per.EntitiesUIDs[idx].ToString());
              origin_dest_uids.Add(uid);
    
              var dest =
                $"{sep}{per.EntityTypeNames[per.EntityTypes[idx]]}:{uid}";
              sep = ", ";
              sb.Append($"{dest}");
            }
            sb.AppendLine("");
    
            sep = "";
            var idx2 = 0;
            sb.Append(" Other EntitiesUIDs: ");
            bool wereAnyOthers = false;
            foreach (var raw_uid in per.EntitiesUIDs)
            {
              var uid = FormatID(raw_uid.ToString());
              if (!origin_dest_uids.Contains(uid))
              {
                var other =
                $"{sep}{per.EntityTypeNames[per.EntityTypes[idx2]]}:{uid}";
                sep = ", ";
                sb.Append($"{other}");
                wereAnyOthers = true;
              }
              idx2++;
            }
            if (!wereAnyOthers)
              sb.Append(" <<none>>");
    
            //sb.AppendLine("");
    
            var entity_str = sb.ToString();
            System.Diagnostics.Debug.WriteLine(entity_str);
    
            sb.Clear();
            sep = "";
          }
        }
    
      });
    }
    List out FFP Results Relationships
    {
      //using ArcGIS.Core.Data.Knowledge.Extensions;
    
      await QueuedTask.Run(async () =>
      {
        var ffp_config = new CIMFilteredFindPathsConfiguration();
        ffp_config.Name = "List out FFP Results Relationships";
        //set up config
        //...
    
        var results = kg.RunFilteredFindPaths(ffp_config);
    
        if (results.CountPaths == 0)
        {
          System.Diagnostics.Debug.WriteLine("FFP returned no paths");
          return;
        }
    
        //print out paths by increasing length, min cost, max cost
        var path_by_len_indices = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingPathLength
                                    .Select(idx => idx.index);
        var path_by_min_cost = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingMinPathCost
                                    .Select(idx => idx.index);
        var path_by_max_cost = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingMaxPathCost
                                    .Select(idx => idx.index);
    
        var x = 0;
        StringBuilder sb = new StringBuilder();
    
        foreach (var path_indeces in new List<IEnumerable<long>> {
        path_by_len_indices,
        path_by_min_cost,
        path_by_max_cost})
        {
          if (x == 0)
            sb.AppendLine($"Relationships by length: {path_by_len_indices.Count()}");
          else if (x == 1)
            sb.AppendLine($"Relationships by min cost: {path_by_min_cost.Count()}");
          else if (x == 2)
            sb.AppendLine($"Relationships by max cost: {path_by_max_cost.Count()}");
          x++;
          foreach (var path_idx in path_indeces)
          {
            var path = (ResultPath)results.MaterializePath(path_idx);
            sb.AppendLine(
              $"Path[{path_idx}] length: {path.Length}, min: {path.MinCost} max: {path.MaxCost}");
    
            var sorted_set = new SortedSet<ulong>();
            sorted_set.Add((ulong)path_idx);
            var per = results.ExtractPathsEntitiesAndRelationships(sorted_set);
    
            var idx = 0;
            foreach (var rel_uid in per.RelationshipsUIDs)
            {
              sb.Append($" RelationshipsUIDs[{idx}]: ");
    
              var uid = FormatID(rel_uid.ToString());
              var rel_info =
                $"{per.RelationshipTypeNames[per.RelationshipTypes[idx]]}:{uid}";
              sb.Append($"{rel_info}\r\n");
              //From entity:
              var entity_idx = per.RelationshipsFrom[idx];
              var origin_uid = FormatID(per.EntitiesUIDs[entity_idx].ToString());
              var origin = $"{per.EntityTypeNames[per.EntityTypes[entity_idx]]}:{origin_uid}";
              sb.Append($"   RelationshipsFrom: {origin}\r\n");
              //To entity
              entity_idx = per.RelationshipsTo[idx];
              var dest_uid = FormatID(per.EntitiesUIDs[entity_idx].ToString());
              var dest = $"{per.EntityTypeNames[per.EntityTypes[entity_idx]]}:{dest_uid}";
              sb.Append($"   RelationshipsTo: {dest}\r\n");
              idx++;
            }
    
            var rel_str = sb.ToString();
            System.Diagnostics.Debug.WriteLine(rel_str);
            sb.Clear();
          }
        }
    
      });
    }
    
    string FormatID(string id)
    {
      id = id.ToUpperInvariant();
      if (!id.StartsWith('{'))
        id = '{' + id;
      if (!id.EndsWith('}'))
        id += '}';
      return id;
    }
    Requirements

    Target Platforms: Windows 11 Home, Pro, Enterprise (64 bit)

    ArcGIS Pro version: 3.6 or higher.
    See Also