internal DataViewRow GetStatefulRows(DataViewRow input, IRowToRowMapper mapper, IEnumerable <DataViewSchema.Column> activeColumns, List <StatefulRow> rows) { Contracts.CheckValue(input, nameof(input)); Contracts.CheckValue(activeColumns, nameof(activeColumns)); IRowToRowMapper[] innerMappers = new IRowToRowMapper[0]; if (mapper is CompositeRowToRowMapper compositeMapper) { innerMappers = compositeMapper.InnerMappers; } var activeIndices = new HashSet <int>(activeColumns.Select(c => c.Index)); if (innerMappers.Length == 0) { bool differentActive = false; for (int c = 0; c < input.Schema.Count; ++c) { bool wantsActive = activeIndices.Contains(c); bool isActive = input.IsColumnActive(input.Schema[c]); differentActive |= wantsActive != isActive; if (wantsActive && !isActive) { throw Contracts.ExceptParam(nameof(input), $"Mapper required column '{input.Schema[c].Name}' active but it was not."); } } var row = mapper.GetRow(input, activeColumns); if (row is StatefulRow statefulRow) { rows.Add(statefulRow); } return(row); } // For each of the inner mappers, we will be calling their GetRow method, but to do so we need to know // what we need from them. The last one will just have the input, but the rest will need to be // computed based on the dependencies of the next one in the chain. var deps = new IEnumerable <DataViewSchema.Column> [innerMappers.Length]; deps[deps.Length - 1] = activeColumns; for (int i = deps.Length - 1; i >= 1; --i) { deps[i - 1] = innerMappers[i].GetDependencies(deps[i]); } DataViewRow result = input; for (int i = 0; i < innerMappers.Length; ++i) { result = GetStatefulRows(result, innerMappers[i], deps[i], rows); if (result is StatefulRow statefulResult) { rows.Add(statefulResult); } } return(result); }
internal DataViewRow GetStatefulRows(DataViewRow input, IRowToRowMapper mapper, Func <int, bool> active, List <StatefulRow> rows) { Contracts.CheckValue(input, nameof(input)); Contracts.CheckValue(active, nameof(active)); IRowToRowMapper[] innerMappers = new IRowToRowMapper[0]; if (mapper is CompositeRowToRowMapper compositeMapper) { innerMappers = compositeMapper.InnerMappers; } if (innerMappers.Length == 0) { bool differentActive = false; for (int c = 0; c < input.Schema.Count; ++c) { bool wantsActive = active(c); bool isActive = input.IsColumnActive(c); differentActive |= wantsActive != isActive; if (wantsActive && !isActive) { throw Contracts.ExceptParam(nameof(input), $"Mapper required column '{input.Schema[c].Name}' active but it was not."); } } var row = mapper.GetRow(input, active); if (row is StatefulRow statefulRow) { rows.Add(statefulRow); } return(row); } // For each of the inner mappers, we will be calling their GetRow method, but to do so we need to know // what we need from them. The last one will just have the input, but the rest will need to be // computed based on the dependencies of the next one in the chain. var deps = new Func <int, bool> [innerMappers.Length]; deps[deps.Length - 1] = active; for (int i = deps.Length - 1; i >= 1; --i) { var inputCols = innerMappers[i].OutputSchema.Where(c => deps[i](c.Index)); var cols = innerMappers[i].GetDependencies(inputCols).ToArray(); deps[i - 1] = c => cols.Length > 0 ? cols.Any(col => col.Index == c) : false; } DataViewRow result = input; for (int i = 0; i < innerMappers.Length; ++i) { result = GetStatefulRows(result, innerMappers[i], deps[i], rows); if (result is StatefulRow statefulResult) { rows.Add(statefulResult); } } return(result); }
internal virtual void PredictionEngineCore(IHostEnvironment env, DataViewConstructionUtils.InputRow <TSrc> inputRow, IRowToRowMapper mapper, bool ignoreMissingColumns, SchemaDefinition inputSchemaDefinition, SchemaDefinition outputSchemaDefinition, out Action disposer, out IRowReadableAs <TDst> outputRow) { var cursorable = TypedCursorable <TDst> .Create(env, new EmptyDataView(env, mapper.Schema), ignoreMissingColumns, outputSchemaDefinition); var outputRowLocal = mapper.GetRow(_inputRow, col => true, out disposer); outputRow = cursorable.GetRow(outputRowLocal); }
internal IRow GetStatefulRows(IRow input, IRowToRowMapper mapper, Func <int, bool> active, List <IStatefulRow> rows, out Action disposer) { Contracts.CheckValue(input, nameof(input)); Contracts.CheckValue(active, nameof(active)); disposer = null; IRowToRowMapper[] innerMappers = new IRowToRowMapper[0]; if (mapper is CompositeRowToRowMapper) { innerMappers = ((CompositeRowToRowMapper)mapper).InnerMappers; } if (innerMappers.Length == 0) { bool differentActive = false; for (int c = 0; c < input.Schema.ColumnCount; ++c) { bool wantsActive = active(c); bool isActive = input.IsColumnActive(c); differentActive |= wantsActive != isActive; if (wantsActive && !isActive) { throw Contracts.ExceptParam(nameof(input), $"Mapper required column '{input.Schema.GetColumnName(c)}' active but it was not."); } } var row = mapper.GetRow(input, active, out disposer); if (row is IStatefulRow) { rows.Add((IStatefulRow)row); } return(row); } // For each of the inner mappers, we will be calling their GetRow method, but to do so we need to know // what we need from them. The last one will just have the input, but the rest will need to be // computed based on the dependencies of the next one in the chain. var deps = new Func <int, bool> [innerMappers.Length]; deps[deps.Length - 1] = active; for (int i = deps.Length - 1; i >= 1; --i) { deps[i - 1] = innerMappers[i].GetDependencies(deps[i]); } IRow result = input; for (int i = 0; i < innerMappers.Length; ++i) { Action localDisp; result = GetStatefulRows(result, innerMappers[i], deps[i], rows, out localDisp); if (result is IStatefulRow) { rows.Add((IStatefulRow)result); } if (localDisp != null) { if (disposer == null) { disposer = localDisp; } else { disposer = localDisp + disposer; } // We want the last disposer to be called first, so the order of the addition here is important. } } return(result); }
/// <summary> /// Extension method. /// </summary> /// <param name="rowMapper"></param> /// <param name="input"></param> /// <param name="activeColumns"></param> /// <returns></returns> public static DataViewRow GetRow(this IRowToRowMapper rowMapper, DataViewRow input, params DataViewSchema.Column[] activeColumns) => rowMapper.GetRow(input, activeColumns);