Skip to content

Commit

Permalink
#6086 - Unable to create antisense chains for ambiguous monomers from…
Browse files Browse the repository at this point in the history
… the library (#6113)

- added antisense creation for chains with ambiguous bases
  • Loading branch information
rrodionov91 authored Dec 10, 2024
1 parent 3838d0a commit 59563ef
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 15 deletions.
14 changes: 14 additions & 0 deletions packages/ketcher-core/src/domain/constants/monomers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ export enum RnaDnaNaturalAnaloguesEnum {
URACIL = 'U',
}

export enum StandardAmbiguousRnaBase {
N = 'N',
B = 'B',
V = 'V',
D = 'D',
H = 'H',
K = 'K',
M = 'M',
W = 'W',
Y = 'Y',
R = 'R',
S = 'S',
}

export const rnaDnaNaturalAnalogues = [
RnaDnaNaturalAnaloguesEnum.ADENINE,
RnaDnaNaturalAnaloguesEnum.THYMINE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import { MACROMOLECULES_BOND_TYPES } from 'application/editor/tools/Bond';
import {
RNA_DNA_NON_MODIFIED_PART,
RnaDnaNaturalAnaloguesEnum,
StandardAmbiguousRnaBase,
} from 'domain/constants/monomers';
import { isNumber } from 'lodash';
import { Chain } from 'domain/entities/monomer-chains/Chain';
Expand Down Expand Up @@ -2621,6 +2622,17 @@ export class DrawingEntitiesManager {
[RnaDnaNaturalAnaloguesEnum.GUANINE]: RnaDnaNaturalAnaloguesEnum.CYTOSINE,
[RnaDnaNaturalAnaloguesEnum.THYMINE]: RnaDnaNaturalAnaloguesEnum.ADENINE,
[RnaDnaNaturalAnaloguesEnum.URACIL]: RnaDnaNaturalAnaloguesEnum.ADENINE,
[StandardAmbiguousRnaBase.N]: StandardAmbiguousRnaBase.N,
[StandardAmbiguousRnaBase.B]: StandardAmbiguousRnaBase.V,
[StandardAmbiguousRnaBase.D]: StandardAmbiguousRnaBase.H,
[StandardAmbiguousRnaBase.H]: StandardAmbiguousRnaBase.D,
[StandardAmbiguousRnaBase.K]: StandardAmbiguousRnaBase.M,
[StandardAmbiguousRnaBase.W]: StandardAmbiguousRnaBase.W,
[StandardAmbiguousRnaBase.Y]: StandardAmbiguousRnaBase.R,
[StandardAmbiguousRnaBase.M]: StandardAmbiguousRnaBase.K,
[StandardAmbiguousRnaBase.R]: StandardAmbiguousRnaBase.Y,
[StandardAmbiguousRnaBase.S]: StandardAmbiguousRnaBase.S,
[StandardAmbiguousRnaBase.V]: StandardAmbiguousRnaBase.B,
};
}

Expand Down Expand Up @@ -2683,15 +2695,15 @@ export class DrawingEntitiesManager {
complimentaryChainWithData.complimentaryChain.monomers.some(
(monomer) => {
return (
(monomer instanceof RNABase &&
(isRnaBaseOrAmbiguousRnaBase(monomer) &&
Boolean(getSugarFromRnaBase(monomer)) &&
monomer.hydrogenBonds.length > 0) ||
monomer.hydrogenBonds.some((hydrogenBond) => {
const anotherMonomer =
hydrogenBond.getAnotherMonomer(monomer);

return (
anotherMonomer instanceof RNABase &&
isRnaBaseOrAmbiguousRnaBase(anotherMonomer) &&
Boolean(getSugarFromRnaBase(anotherMonomer))
);
})
Expand Down Expand Up @@ -2782,6 +2794,14 @@ export class DrawingEntitiesManager {
return command;
}

private getAntisenseBaseLabel(rnaBase: RNABase | AmbiguousMonomer) {
return this.antisenseChainBasesMap[
rnaBase instanceof AmbiguousMonomer
? rnaBase.monomerItem.label
: rnaBase.monomerItem.props.MonomerNaturalAnalogCode
];
}

public createAntisenseChain() {
const editor = CoreEditor.provideEditorInstance();
const command = new Command();
Expand All @@ -2795,6 +2815,7 @@ export class DrawingEntitiesManager {
subChain.nodes.some(
(node) =>
(node instanceof Nucleotide || node instanceof Nucleoside) &&
Boolean(this.getAntisenseBaseLabel(node.rnaBase)) &&
node.monomer.selected,
),
);
Expand All @@ -2814,14 +2835,18 @@ export class DrawingEntitiesManager {
}

if (node instanceof Nucleotide || node instanceof Nucleoside) {
const antisenseBaseLabel = this.getAntisenseBaseLabel(node.rnaBase);

if (!antisenseBaseLabel) {
return;
}

const { modelChanges: addNucleotideCommand, node: addedNode } = (
node instanceof Nucleotide && node.phosphate.selected
? Nucleotide
: Nucleoside
).createOnCanvas(
this.antisenseChainBasesMap[
node.rnaBase.monomerItem.props.MonomerNaturalAnalogCode
],
antisenseBaseLabel,
node.monomer.position.add(new Vec2(0, 3)),
RNA_DNA_NON_MODIFIED_PART.SUGAR_RNA,
);
Expand Down
13 changes: 11 additions & 2 deletions packages/ketcher-core/src/domain/entities/Nucleoside.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { AmbiguousMonomer } from 'domain/entities/AmbiguousMonomer';
import { RNA_MONOMER_DISTANCE } from 'application/editor/tools/RnaPreset';
import { SugarRenderer } from 'application/render';
import { RNA_DNA_NON_MODIFIED_PART } from 'domain/constants/monomers';
import { KetMonomerClass } from 'application/formatters';

export class Nucleoside {
constructor(
Expand Down Expand Up @@ -46,8 +47,16 @@ export class Nucleoside {
isAntisense = false,
) {
const editor = CoreEditor.provideEditorInstance();
const rnaBaseLibraryItem = getRnaPartLibraryItem(editor, rnaBaseName);
const sugarLibraryItem = getRnaPartLibraryItem(editor, sugarName);
const rnaBaseLibraryItem = getRnaPartLibraryItem(
editor,
rnaBaseName,
KetMonomerClass.Base,
);
const sugarLibraryItem = getRnaPartLibraryItem(
editor,
sugarName,
KetMonomerClass.Sugar,
);

assert(sugarLibraryItem);
assert(rnaBaseLibraryItem);
Expand Down
13 changes: 11 additions & 2 deletions packages/ketcher-core/src/domain/entities/Nucleotide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { AmbiguousMonomer } from 'domain/entities/AmbiguousMonomer';
import { RNA_MONOMER_DISTANCE } from 'application/editor/tools/RnaPreset';
import { SugarRenderer } from 'application/render';
import { SNAKE_LAYOUT_CELL_WIDTH } from 'domain/entities/DrawingEntitiesManager';
import { KetMonomerClass } from 'application/formatters';

export class Nucleotide {
constructor(
Expand Down Expand Up @@ -53,12 +54,20 @@ export class Nucleotide {
sugarName: RNA_DNA_NON_MODIFIED_PART = RNA_DNA_NON_MODIFIED_PART.SUGAR_RNA,
) {
const editor = CoreEditor.provideEditorInstance();
const rnaBaseLibraryItem = getRnaPartLibraryItem(editor, rnaBaseName);
const rnaBaseLibraryItem = getRnaPartLibraryItem(
editor,
rnaBaseName,
KetMonomerClass.Base,
);
const phosphateLibraryItem = getRnaPartLibraryItem(
editor,
RNA_DNA_NON_MODIFIED_PART.PHOSPHATE,
);
const sugarLibraryItem = getRnaPartLibraryItem(editor, sugarName);
const sugarLibraryItem = getRnaPartLibraryItem(
editor,
sugarName,
KetMonomerClass.Sugar,
);

assert(sugarLibraryItem);
assert(rnaBaseLibraryItem);
Expand Down
22 changes: 16 additions & 6 deletions packages/ketcher-core/src/domain/helpers/rna.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { CoreEditor } from 'application/editor/internal';
import { SequenceType } from 'domain/entities';
import { AmbiguousMonomer, SequenceType } from 'domain/entities';
import { RNA_DNA_NON_MODIFIED_PART } from 'domain/constants/monomers';
import { MONOMER_CONST } from 'application/editor';
import { isAmbiguousMonomerLibraryItem } from 'domain/helpers/monomers';
import { KetMonomerClass } from 'application/formatters';

export function getRnaPartLibraryItem(editor: CoreEditor, rnaBaseName: string) {
return editor.monomersLibrary.find(
(libraryItem) =>
libraryItem.props.MonomerType === MONOMER_CONST.RNA &&
libraryItem.props.MonomerName === rnaBaseName,
export function getRnaPartLibraryItem(
editor: CoreEditor,
rnaBaseName: string,
monomerClass?: KetMonomerClass,
) {
return editor.monomersLibrary.find((libraryItem) =>
isAmbiguousMonomerLibraryItem(libraryItem)
? (!monomerClass ||
AmbiguousMonomer.getMonomerClass(libraryItem.monomers) ===
monomerClass) &&
libraryItem.label === rnaBaseName
: (!monomerClass || libraryItem.props.MonomerClass === monomerClass) &&
libraryItem.props.MonomerName === rnaBaseName,
);
}

Expand Down

0 comments on commit 59563ef

Please sign in to comment.