Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 23 additions & 61 deletions devenv.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
"devenv": {
"locked": {
"dir": "src/modules",
"lastModified": 1761922975,
"lastModified": 1781800860,
"narHash": "sha256-LrEo0eC5ckMvjpBRCuk5q5/vjItKlxnb4n/clHNRZlk=",
"owner": "cachix",
"repo": "devenv",
"rev": "c9f0b47815a4895fadac87812de8a4de27e0ace1",
"rev": "d59d872d80876d9eeb3e214d3b088bc4a14a9c4f",
"type": "github"
},
"original": {
Expand All @@ -16,88 +17,49 @@
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1761588595,
"owner": "edolstra",
"repo": "flake-compat",
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"git-hooks": {
"nixpkgs": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
"nixpkgs-src": "nixpkgs-src"
},
"locked": {
"lastModified": 1760663237,
"lastModified": 1781620901,
"narHash": "sha256-UF6scQlG+6lRkZBUpn/3KNavhOo5G8kDWhjVHcno8uc=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "ca5b894d3e3e151ffc1db040b6ce4dcc75d31c37",
"repo": "devenv-nixpkgs",
"rev": "2df109b343d3c68efd752e32a444a1d9b9f89afa",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"ref": "rolling",
"repo": "devenv-nixpkgs",
"type": "github"
}
},
"nixpkgs": {
"nixpkgs-src": {
"flake": false,
"locked": {
"lastModified": 1761313199,
"owner": "cachix",
"repo": "devenv-nixpkgs",
"rev": "d1c30452ebecfc55185ae6d1c983c09da0c274ff",
"lastModified": 1781454065,
"narHash": "sha256-d2xfDjnfRuf/xYGdu9VVRHiav/2w5hDL/5cw2TuVAXw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9eac87a12312b8f60dd52e1c6e1a265f6fc7f5fc",
"type": "github"
},
"original": {
"owner": "cachix",
"ref": "rolling",
"repo": "devenv-nixpkgs",
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"devenv": "devenv",
"git-hooks": "git-hooks",
"nixpkgs": "nixpkgs",
"pre-commit-hooks": [
"git-hooks"
]
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}
}
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
<dependency>
<groupId>org.immutables</groupId>
<artifactId>value</artifactId>
<version>2.12.1</version>
<version>2.12.2</version>
<scope>provided</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -41,6 +42,7 @@
import pl.poznan.put.rnapdbee.engine.shared.multiplet.MultipletSet;
import pl.poznan.put.structure.AnalyzedBasePair;
import pl.poznan.put.structure.ImmutableAnalyzedBasePair;
import pl.poznan.put.structure.ImmutableBasePair;

// TODO: WebFlux would be really efficient with the 3D->multi 2D analysis as we there perform multiple calls to the
// adapters, it could be done in parallel and then joined up after each call is performed. We would save a tone of
Expand Down Expand Up @@ -124,7 +126,12 @@ protected BasePairAnalysis performPostAnalysisOnResponseFromAdapter(
.filter(pair -> pair.isCanonical(structureModel))
.map(pair -> BasePairDTO.ofBasePairDTOWithNameFromMap(pair,
pairIdentifiersWithTheirShortNames))
.map(basePair -> ImmutableAnalyzedBasePair.of(basePair.toBasePair(structureModel))
.map(basePair -> {
ImmutableBasePair bp = basePair.toBasePair(structureModel);
if (bp == null) {
return null;
}
return ImmutableAnalyzedBasePair.of(bp)
.withInteractionType(InteractionType.BASE_BASE)
.withSaenger(basePair.getSaengerType() != null
? SaengerType.mapToBioCommonsForm(
Expand All @@ -136,13 +143,20 @@ protected BasePairAnalysis performPostAnalysisOnResponseFromAdapter(
: LeontisWesthof.UNKNOWN)
.withBph(BPh.UNKNOWN)
.withBr(BR.UNKNOWN)
.withStackingTopology(StackingTopology.UNKNOWN))
.withStackingTopology(StackingTopology.UNKNOWN);
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
List<AnalyzedBasePair> nonCanonical = responseFromAdapter.getBasePairs().stream()
.filter(pair -> !pair.isCanonical(structureModel))
.map(pair -> BasePairDTO.ofBasePairDTOWithNameFromMap(pair,
pairIdentifiersWithTheirShortNames))
.map(basePair -> ImmutableAnalyzedBasePair.of(basePair.toBasePair(structureModel))
.map(basePair -> {
ImmutableBasePair bp = basePair.toBasePair(structureModel);
if (bp == null) {
return null;
}
return ImmutableAnalyzedBasePair.of(bp)
.withInteractionType(InteractionType.BASE_BASE)
.withSaenger(basePair.getSaengerType() != null
? SaengerType.mapToBioCommonsForm(
Expand All @@ -154,56 +168,91 @@ protected BasePairAnalysis performPostAnalysisOnResponseFromAdapter(
: LeontisWesthof.UNKNOWN)
.withBph(BPh.UNKNOWN)
.withBr(BR.UNKNOWN)
.withStackingTopology(StackingTopology.UNKNOWN))
.withStackingTopology(StackingTopology.UNKNOWN);
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
List<AnalyzedBasePair> stackings = responseFromAdapter.getStackings().stream()
.map(pair -> BasePairDTO.ofBasePairDTOWithNameFromMap(pair,
pairIdentifiersWithTheirShortNames))
.map(basePair -> ImmutableAnalyzedBasePair.of(basePair.toBasePair(structureModel))
.map(basePair -> {
ImmutableBasePair bp = basePair.toBasePair(structureModel);
if (bp == null) {
return null;
}
return ImmutableAnalyzedBasePair.of(bp)
.withInteractionType(InteractionType.STACKING)
.withSaenger(Saenger.UNKNOWN)
.withLeontisWesthof(LeontisWesthof.UNKNOWN)
.withBph(BPh.UNKNOWN)
.withBr(BR.UNKNOWN)
.withStackingTopology(mapToBioCommonsForm(basePair.getTopology())))
.withStackingTopology(mapToBioCommonsForm(basePair.getTopology()));
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
List<AnalyzedBasePair> basePhosphate = responseFromAdapter.getBasePhosphateInteractions().stream()
.map(pair -> BasePairDTO.ofBasePairDTOWithNameFromMap(pair,
pairIdentifiersWithTheirShortNames))
.map(basePair -> ImmutableAnalyzedBasePair.of(basePair.toBasePair(structureModel))
.map(basePair -> {
ImmutableBasePair bp = basePair.toBasePair(structureModel);
if (bp == null) {
return null;
}
return ImmutableAnalyzedBasePair.of(bp)
.withInteractionType(InteractionType.BASE_PHOSPHATE)
.withSaenger(Saenger.UNKNOWN)
.withLeontisWesthof(LeontisWesthof.UNKNOWN)
.withBph(BasePhosphateType.mapToBioCommonsForm(basePair.getBph()))
.withBr(BR.UNKNOWN)
.withStackingTopology(StackingTopology.UNKNOWN))
.withStackingTopology(StackingTopology.UNKNOWN);
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
List<AnalyzedBasePair> baseRibose = responseFromAdapter.getBaseRiboseInteractions().stream()
.map(pair -> BasePairDTO.ofBasePairDTOWithNameFromMap(pair,
pairIdentifiersWithTheirShortNames))
.map(basePair -> ImmutableAnalyzedBasePair.of(basePair.toBasePair(structureModel))
.map(basePair -> {
ImmutableBasePair bp = basePair.toBasePair(structureModel);
if (bp == null) {
return null;
}
return ImmutableAnalyzedBasePair.of(bp)
.withInteractionType(InteractionType.BASE_RIBOSE)
.withSaenger(Saenger.UNKNOWN)
.withLeontisWesthof(LeontisWesthof.UNKNOWN)
.withBph(BPh.UNKNOWN)
.withBr(BaseRiboseType.mapToBioCommonsForm(basePair.getBr()))
.withStackingTopology(StackingTopology.UNKNOWN))
.withStackingTopology(StackingTopology.UNKNOWN);
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
List<AnalyzedBasePair> otherInteractions = responseFromAdapter.getOther().stream()
.map(pair -> BasePairDTO.ofBasePairDTOWithNameFromMap(pair,
pairIdentifiersWithTheirShortNames))
.map(basePair -> ImmutableAnalyzedBasePair.of(basePair.toBasePair(structureModel))
.map(basePair -> {
ImmutableBasePair bp = basePair.toBasePair(structureModel);
if (bp == null) {
return null;
}
return ImmutableAnalyzedBasePair.of(bp)
.withInteractionType(InteractionType.OTHER)
.withSaenger(Saenger.UNKNOWN)
.withLeontisWesthof(LeontisWesthof.UNKNOWN)
.withBph(BPh.UNKNOWN)
.withBr(BR.UNKNOWN)
.withStackingTopology(StackingTopology.UNKNOWN))
.withStackingTopology(StackingTopology.UNKNOWN);
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
List<AnalyzedBasePair> interStrand = responseFromAdapter.getBasePairs().stream()
.map(pair -> BasePairDTO.ofBasePairDTOWithNameFromMap(pair,
pairIdentifiersWithTheirShortNames))
.map(basePair -> ImmutableAnalyzedBasePair.of(basePair.toBasePair(structureModel))
.map(basePair -> {
ImmutableBasePair bp = basePair.toBasePair(structureModel);
if (bp == null) {
return null;
}
return ImmutableAnalyzedBasePair.of(bp)
.withInteractionType(InteractionType.BASE_BASE)
.withSaenger(basePair.getSaengerType() != null
? SaengerType.mapToBioCommonsForm(
Expand All @@ -215,7 +264,9 @@ protected BasePairAnalysis performPostAnalysisOnResponseFromAdapter(
: LeontisWesthof.UNKNOWN)
.withBph(BPh.UNKNOWN)
.withBr(BR.UNKNOWN)
.withStackingTopology(StackingTopology.UNKNOWN))
.withStackingTopology(StackingTopology.UNKNOWN);
})
.filter(Objects::nonNull)
.filter(basePair -> !basePair.basePair()
.left()
.chainIdentifier()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package pl.poznan.put.rnapdbee.engine.shared.basepair.domain;

import com.fasterxml.jackson.annotation.JsonProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pl.poznan.put.pdb.PdbNamedResidueIdentifier;
import pl.poznan.put.pdb.analysis.PdbModel;
import pl.poznan.put.rnapdbee.engine.shared.basepair.boundary.ChainNumberKey;
Expand All @@ -19,6 +21,7 @@
*/
public class BasePairDTO {

private static final Logger LOGGER = LoggerFactory.getLogger(BasePairDTO.class);
private static final Set<String> CANONICAL_ONE_LETTER_NAME_SORTED_PAIRS = new HashSet<>(Arrays.asList("AU", "GU", "CG"));

@JsonProperty("nt1")
Expand Down Expand Up @@ -122,6 +125,9 @@ public static BasePairDTO ofBasePairDTOWithNameFromMap(BasePairDTO basePairDTO,
public ImmutableBasePair toBasePair(PdbModel pdbModel) {
PdbNamedResidueIdentifier left = mapResidueToPdbNamedResidueIdentifier(nt1, pdbModel);
PdbNamedResidueIdentifier right = mapResidueToPdbNamedResidueIdentifier(nt2, pdbModel);
if (left == null || right == null) {
return null;
}
return ImmutableBasePair.of(left, right);
}

Expand All @@ -130,14 +136,15 @@ private PdbNamedResidueIdentifier mapResidueToPdbNamedResidueIdentifier(Residue
return pdbModel.findResidue(residue).namedResidueIdentifier();
}

throw new IllegalStateException(String.format(
"Residue not found in model: chain='%s', number=%d, icode=%s, name='%s'. "
LOGGER.warn(
"Residue not found in model: chain='{}', number={}, icode={}, name='{}'. "
+ "This may indicate a mismatch between adapter response and parsed structure "
+ "(e.g., chain identifier normalization issue).",
residue.chainIdentifier(),
residue.residueNumber(),
residue.insertionCode().orElse("(none)"),
residue.getAuth().getName()));
residue.getAuth().getName());
return null;
}

public boolean isCanonical(PdbModel pdbModel) {
Expand All @@ -147,6 +154,9 @@ public boolean isCanonical(PdbModel pdbModel) {
if (leontisWesthofType == LeontisWesthofType.CWW) {
PdbNamedResidueIdentifier left = mapResidueToPdbNamedResidueIdentifier(nt1, pdbModel);
PdbNamedResidueIdentifier right = mapResidueToPdbNamedResidueIdentifier(nt2, pdbModel);
if (left == null || right == null) {
return false;
}
String sequence = Stream.of(left.oneLetterName(), right.oneLetterName())
.map(c -> Character.toString(c))
.map(String::toUpperCase)
Expand Down
Loading