diff --git a/src/PKSim.Core/Mappers/ProcessToProcessBuilderMapper.cs b/src/PKSim.Core/Mappers/ProcessToProcessBuilderMapper.cs index 4fad1e9fb..38ffcb9ba 100644 --- a/src/PKSim.Core/Mappers/ProcessToProcessBuilderMapper.cs +++ b/src/PKSim.Core/Mappers/ProcessToProcessBuilderMapper.cs @@ -12,6 +12,7 @@ using PKSim.Core.Repositories; using PKSim.Core.Services; using static PKSim.Core.CoreConstants.Compartment; +using static PKSim.Core.CoreConstants.Organ; namespace PKSim.Core.Mappers { @@ -187,7 +188,7 @@ public IReactionBuilder InductionReactionFrom(InteractionProcess interactionProc reaction.AddProduct(new ReactionPartnerBuilder(protein.Name, 1)); //Induction occurs only in Intracellular and Interstitial - reaction.ContainerCriteria.Add(new InContainerCondition(CoreConstants.Organ.TISSUE_ORGAN)); + reaction.ContainerCriteria.Add(new InContainerCondition(TISSUE_ORGAN)); reaction.ContainerCriteria.Add(new NotMatchTagCondition(PLASMA)); reaction.ContainerCriteria.Add(new NotMatchTagCondition(BLOOD_CELLS)); reaction.ContainerCriteria.Add(new NotMatchTagCondition(ENDOSOME)); @@ -359,8 +360,9 @@ private IReadOnlyCollection allInducedProcessesFor(IndividualTra inducedProcessCache.Add(inducedProcess); } - inducedProcess.AddSourceOrgan(transportTemplate.SourceOrgan); - inducedProcess.AddTargetOrgan(transportTemplate.TargetOrgan); + // For lumen transport. The source organ or target organ is in fact defined as a compartment + inducedProcess.AddSourceOrgan(transportTemplate.SourceOrgan.IsLumen() ? transportTemplate.SourceCompartment : transportTemplate.SourceOrgan); + inducedProcess.AddTargetOrgan(transportTemplate.TargetOrgan.IsLumen() ? transportTemplate.TargetCompartment : transportTemplate.TargetOrgan); } } @@ -369,19 +371,36 @@ private IReadOnlyCollection allInducedProcessesFor(IndividualTra private void updateTransporterTagsFor(ITransportBuilder transporterBuilder, InducedProcess inducedProcess) { - var allSourceTags = transporterBuilder.SourceCriteria.OfType() - .Select(x => x.Tag).ToList(); + var sourceCriteria = transporterBuilder.SourceCriteria; + var allSourceTags = sourceCriteria.OfType().Select(x => x.Tag).ToList(); + var (sourceIsLumen, sourceIsMucosa) = (allSourceTags.Contains(LUMEN), allSourceTags.Contains(MUCOSA)); - //More than one tag coming from the database => This is a specific transport and we do not need to do anything - if (allSourceTags.Count > 1) - return; + var targetCriteria = transporterBuilder.TargetCriteria; + var allTargetTags = targetCriteria.OfType().Select(x => x.Tag).ToList(); + var (targetIsLumen, targetIsMucosa) = (allTargetTags.Contains(LUMEN), allTargetTags.Contains(MUCOSA)); + + var isLumen = sourceIsLumen || targetIsLumen; + var isMucosa = sourceIsMucosa || targetIsMucosa; - foreach (var organName in inducedProcess.OrgansToExclude) + if (isLumen && isMucosa) { - transporterBuilder.SourceCriteria.Add(new NotMatchTagCondition(organName)); + //We just want to remove GI segments from the include list as we know, that the transport is between Lumen and Mucosa in this case + var segmentToDeletes = inducedProcess.OrgansToExclude.Intersect(LumenSegmentsDuodenumToRectum).ToList(); + var criteria = sourceIsLumen ? sourceCriteria : targetCriteria; + addAsNotMatchToCriteria(criteria, segmentToDeletes); + return; } + + // This is a specific transport and we do not need to do anything + if (allSourceTags.Count > 1) + return; + + addAsNotMatchToCriteria(sourceCriteria, inducedProcess.OrgansToExclude); } + private void addAsNotMatchToCriteria(DescriptorCriteria criteria, IEnumerable list) + => list.Each(x => criteria.Add(new NotMatchTagCondition(x))); + private ITransportBuilder activeTransportFrom(CompoundProcess process, InducedProcess inducedProcess, IFormulaCache formulaCache) { //retrieve process for the simulation and create a clone diff --git a/tests/PKSim.Tests/Data/Mucosa_MultipleTransportDirections.pksim5 b/tests/PKSim.Tests/Data/Mucosa_MultipleTransportDirections.pksim5 new file mode 100644 index 000000000..d84d1a14e Binary files /dev/null and b/tests/PKSim.Tests/Data/Mucosa_MultipleTransportDirections.pksim5 differ diff --git a/tests/PKSim.Tests/IntegrationTests/ProcessToProcessBuilderMapperSpecs.cs b/tests/PKSim.Tests/IntegrationTests/ProcessToProcessBuilderMapperSpecs.cs new file mode 100644 index 000000000..fa8308bff --- /dev/null +++ b/tests/PKSim.Tests/IntegrationTests/ProcessToProcessBuilderMapperSpecs.cs @@ -0,0 +1,40 @@ +using System.Linq; +using OSPSuite.BDDHelper; +using OSPSuite.BDDHelper.Extensions; +using OSPSuite.Core.Domain; +using PKSim.Core.Mappers; +using PKSim.Core.Model; +using PKSim.Infrastructure; + +namespace PKSim.IntegrationTests +{ + public abstract class concern_for_ProcessToProcessBuilderMapper : ContextWithLoadedProject + { + public override void GlobalContext() + { + base.GlobalContext(); + LoadProject("Mucosa_MultipleTransportDirections"); + } + } + + public class When_creating_a_simulation_using_transport_in_multiple_mucosa_directions : concern_for_ProcessToProcessBuilderMapper + { + private Simulation _simulation; + + protected override void Context() + { + base.Context(); + var ind = FindByName("I1"); + var comp = FindByName("C1"); + var prot = FindByName("IV"); + _simulation = DomainFactoryForSpecs.CreateSimulationWith(ind, comp, prot); + } + + [Observation] + public void should_not_create_too_many_transporters() + { + var transportInLumenToMucosa = _simulation.Model.Neighborhoods.EntityAt("Lumen_lil_LowerIleum_cell", "C1", "T1-a"); + transportInLumenToMucosa.GetChildren(x => x.ContainerType == ContainerType.Transport).Count().ShouldBeEqualTo(1); + } + } +} \ No newline at end of file