From f7e78c120da5ffac33c78b36088fba8654ee1416 Mon Sep 17 00:00:00 2001 From: Aleksei Proskurnov Date: Fri, 31 Jan 2025 14:55:19 +0100 Subject: [PATCH] Two sense to antisense connection order problem --- .../monomer-chains/ChainsCollection.ts | 113 ++++++++++++++---- 1 file changed, 91 insertions(+), 22 deletions(-) diff --git a/packages/ketcher-core/src/domain/entities/monomer-chains/ChainsCollection.ts b/packages/ketcher-core/src/domain/entities/monomer-chains/ChainsCollection.ts index 0339be368c..3a0125507d 100644 --- a/packages/ketcher-core/src/domain/entities/monomer-chains/ChainsCollection.ts +++ b/packages/ketcher-core/src/domain/entities/monomer-chains/ChainsCollection.ts @@ -104,7 +104,10 @@ export class ChainsCollection { }); }); }); + this.chains = [...reorderedChains.values()]; + + this.reorderChainsPutSenseChainOrderInAccordanceAntisenseConnection(); } public add(chain: Chain) { @@ -370,6 +373,90 @@ export class ChainsCollection { return undefined; } + private getComplimentaryChainIfNucleotide(node: SubChainNode) { + const monomerToChain = this.monomerToChain; + + const { monomer, complimentaryMonomer } = + this.getFirstAntisenseMonomerInNode(node) || {}; + const complimentaryNode = + complimentaryMonomer && this.monomerToNode.get(complimentaryMonomer); + const complimentaryChain = + complimentaryMonomer && monomerToChain.get(complimentaryMonomer); + + const isRnaMonomer = + isRnaBaseOrAmbiguousRnaBase(monomer) && + Boolean(getSugarFromRnaBase(monomer)); + const isRnaComplimentaryMonomer = + isRnaBaseOrAmbiguousRnaBase(complimentaryMonomer) && + Boolean(getSugarFromRnaBase(complimentaryMonomer)); + + if ( + !complimentaryNode || + !complimentaryChain || + !isRnaMonomer || + !isRnaComplimentaryMonomer + ) { + return null; + } + return { complimentaryChain, complimentaryNode }; + } + + private reorderChainsPutSenseChainOrderInAccordanceAntisenseConnection() { + const handledChain = new Set(); + const reorderedSenseForSequentialAntisenseChains: Chain[] = new Array( + this.chains.length, + ); + this.chains.forEach((chain) => { + if (!handledChain.has(chain)) { + reorderedSenseForSequentialAntisenseChains[handledChain.size] = chain; + handledChain.add(chain); + } + + if (chain.isAntisense) { + return; + } + + chain.forEachNode(({ node: sNode }) => { + const { + complimentaryChain: antisenseChain, + complimentaryNode: antisenseNode, + } = this.getComplimentaryChainIfNucleotide(sNode) ?? {}; + if (!antisenseChain) { + return; + } + + let isFindCur = false; + antisenseChain.forEachNode(({ node: aNode }) => { + if (aNode === antisenseNode) { + isFindCur = true; + } + if (!isFindCur) { + const { complimentaryChain: anotherSenseChain } = + this.getComplimentaryChainIfNucleotide(aNode) ?? {}; + if (anotherSenseChain && !handledChain.has(anotherSenseChain)) { + const curChainIdx = + reorderedSenseForSequentialAntisenseChains.findIndex( + (v) => v === chain, + ); + let last = anotherSenseChain; + for ( + let i = curChainIdx; + i < reorderedSenseForSequentialAntisenseChains.length; + i++ + ) { + const tmp = reorderedSenseForSequentialAntisenseChains[i]; + reorderedSenseForSequentialAntisenseChains[i] = last; + last = tmp; + } + handledChain.add(anotherSenseChain); + } + } + }); + }); + }); + this.chains = [...reorderedSenseForSequentialAntisenseChains]; + } + // for example // 1 x x x // | @@ -385,32 +472,14 @@ export class ChainsCollection { const res: GrouppedChain[] = [{ group: 0, chain: c }]; const handledChains = new Set([c]); - const monomerToChain = this.monomerToChain; while (chains.length) { const { group, chain } = chains.pop() as GrouppedChain; chain.forEachNode(({ node }) => { - const { monomer, complimentaryMonomer } = - this.getFirstAntisenseMonomerInNode(node) || {}; - const complimentaryNode = - complimentaryMonomer && this.monomerToNode.get(complimentaryMonomer); - const complimentaryChain = - complimentaryMonomer && monomerToChain.get(complimentaryMonomer); - - const isRnaMonomer = - isRnaBaseOrAmbiguousRnaBase(monomer) && - Boolean(getSugarFromRnaBase(monomer)); - const isRnaComplimentaryMonomer = - isRnaBaseOrAmbiguousRnaBase(complimentaryMonomer) && - Boolean(getSugarFromRnaBase(complimentaryMonomer)); - - if ( - !complimentaryNode || - !complimentaryChain || - !isRnaMonomer || - !isRnaComplimentaryMonomer || - handledChains.has(complimentaryChain) - ) { + const { complimentaryChain } = + this.getComplimentaryChainIfNucleotide(node) ?? {}; + + if (!complimentaryChain || handledChains.has(complimentaryChain)) { return; }