Skip to content

Commit

Permalink
#3738 - Macro/Micro: Switching from Macromolecules view to Molecules …
Browse files Browse the repository at this point in the history
…view causes crash if custom aromatic hydrocarbon was connected with monomer (#3811)

* #3738 - Macro/Micro: Switching from Macromolecules view to Molecules view causes crash if custom aromatic hydrocarbon was connected with monomer

* added ignoring of attachment points calculating/drawing for micromolecules fragments in macro mode

---------

Co-authored-by: Roman Rodionov <roman_rodionov@epam.com>
  • Loading branch information
rrodionov91 and rrodionov91 authored Dec 28, 2023
1 parent 0dd8f67 commit 10844db
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,31 @@ export class MacromoleculesConverter {
}

private static findAttachmentPointAtom(
sgroup: SGroup,
polymerBond: PolymerBond,
monomer: BaseMonomer,
struct: Struct,
sgroup?: SGroup,
fragmentId?: number,
) {
const attachmentPointName = monomer.getAttachmentPointByBond(polymerBond);
assert(attachmentPointName);
return sgroup.atoms.find(
(atomId) =>
Number(struct.atoms.get(atomId)?.rglabel) ===
MacromoleculesConverter.convertAttachmentPointNameToNumber(
attachmentPointName,
),
);
const attachmentPointNumber =
MacromoleculesConverter.convertAttachmentPointNameToNumber(
attachmentPointName,
);

return sgroup
? sgroup.atoms.find(
(atomId) =>
Number(struct.atoms.get(atomId)?.rglabel) === attachmentPointNumber,
)
: struct.atoms.find((atomId) => {
const atom = struct.atoms.get(atomId) as Atom;
return (
atom.fragment === fragmentId &&
Number(atom.rglabel) === attachmentPointNumber
);
});
}

public static convertDrawingEntitiesToStruct(
Expand All @@ -98,13 +109,15 @@ export class MacromoleculesConverter {
reStruct?: ReStruct,
) {
const monomerToSgroup = new Map<BaseMonomer, SGroup>();
const monomerToFragmentId = new Map<BaseMonomer, number>();

drawingEntitiesManager.micromoleculesHiddenEntities.mergeInto(struct);

drawingEntitiesManager.clearMicromoleculesHiddenEntities();
drawingEntitiesManager.monomers.forEach((monomer) => {
if (monomer.monomerItem.props.isMicromoleculeFragment) {
monomer.monomerItem.struct.mergeInto(struct);
monomerToFragmentId.set(monomer, struct.frags.size - 1);
} else {
const atomIdsMap = {};
const monomerMicromolecule = this.convertMonomerToMonomerMicromolecule(
Expand Down Expand Up @@ -146,16 +159,18 @@ export class MacromoleculesConverter {
drawingEntitiesManager.polymerBonds.forEach((polymerBond) => {
assert(polymerBond.secondMonomer);
const beginAtom = this.findAttachmentPointAtom(
monomerToSgroup.get(polymerBond.firstMonomer) as SGroup,
polymerBond,
polymerBond.firstMonomer,
struct,
monomerToSgroup.get(polymerBond.firstMonomer),
monomerToFragmentId.get(polymerBond.firstMonomer),
);
const endAtom = this.findAttachmentPointAtom(
monomerToSgroup.get(polymerBond.secondMonomer) as SGroup,
polymerBond,
polymerBond.secondMonomer,
struct,
monomerToSgroup.get(polymerBond.secondMonomer),
monomerToFragmentId.get(polymerBond.secondMonomer),
);

if (!beginAtom || !endAtom) {
Expand Down Expand Up @@ -223,9 +238,9 @@ export class MacromoleculesConverter {
);
}

public static getAttachmentPointLabel(atomId: number, struct: Struct) {
public static getAttachmentPointLabel(atom: Atom) {
let attachmentPointLabel = '';
const atomRglabel = Number(struct.atoms.get(atomId)?.rglabel);
const atomRglabel = Number(atom.rglabel);
assert(Number.isInteger(atomRglabel));
for (let rgi = 0; rgi < 32; rgi++) {
if (atomRglabel & (1 << rgi)) {
Expand All @@ -240,6 +255,7 @@ export class MacromoleculesConverter {
drawingEntitiesManager: DrawingEntitiesManager,
) {
const sgroupToMonomer = new Map<SGroup, BaseMonomer>();
const fragmentIdToMonomer = new Map<number, BaseMonomer>();
const command = new Command();
struct.sgroups.forEach((sgroup) => {
if (sgroup instanceof MonomerMicromolecule) {
Expand All @@ -255,30 +271,42 @@ export class MacromoleculesConverter {
let fragmentNumber = 1;
struct.frags.forEach((_fragment, fragmentId) => {
const fragmentStruct = struct.getFragment(fragmentId, false);
command.merge(
this.convertFragmentToChem(
fragmentNumber,
fragmentStruct,
drawingEntitiesManager,
),
const monomerAddCommand = this.convertFragmentToChem(
fragmentNumber,
fragmentStruct,
drawingEntitiesManager,
);
fragmentIdToMonomer.set(
fragmentId,
monomerAddCommand.operations[0].monomer as BaseMonomer,
);
command.merge(monomerAddCommand);
fragmentNumber++;
});
struct.bonds.forEach((bond) => {
const beginAtom = struct.atoms.get(bond.begin) as Atom;
const endAtom = struct.atoms.get(bond.end) as Atom;
const beginAtomSgroup = struct.getGroupFromAtomId(bond.begin);
const endAtomSgroup = struct.getGroupFromAtomId(bond.end);
const beginAtomAttachmentPointNumber =
MacromoleculesConverter.getAttachmentPointLabel(bond.begin, struct);
MacromoleculesConverter.getAttachmentPointLabel(beginAtom);
const endAtomAttachmentPointNumber =
MacromoleculesConverter.getAttachmentPointLabel(bond.end, struct);
MacromoleculesConverter.getAttachmentPointLabel(endAtom);
if (
beginAtomAttachmentPointNumber &&
endAtomAttachmentPointNumber &&
beginAtomSgroup instanceof MonomerMicromolecule &&
endAtomSgroup instanceof MonomerMicromolecule
(beginAtomSgroup || endAtomSgroup)
) {
const firstMonomer = sgroupToMonomer.get(beginAtomSgroup);
const secondMonomer = sgroupToMonomer.get(endAtomSgroup);
// Here we take monomers from sgroupToMonomer in case of macromolecules structure and
// from fragmentIdToMonomer in case of micromolecules structure.
const firstMonomer =
beginAtomSgroup instanceof MonomerMicromolecule
? sgroupToMonomer.get(beginAtomSgroup)
: fragmentIdToMonomer.get(beginAtom.fragment);
const secondMonomer =
endAtomSgroup instanceof MonomerMicromolecule
? sgroupToMonomer.get(endAtomSgroup)
: fragmentIdToMonomer.get(endAtom.fragment);
assert(firstMonomer);
assert(secondMonomer);

Expand Down
20 changes: 9 additions & 11 deletions packages/ketcher-core/src/domain/entities/BaseMonomer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,32 @@ export abstract class BaseMonomer extends DrawingEntity {
public renderer?: BaseMonomerRenderer = undefined;
public attachmentPointsToBonds: Partial<
Record<AttachmentPointName, PolymerBond | null>
> = {
R1: null,
};
> = {};

public chosenFirstAttachmentPointForBond: string | null;
public potentialSecondAttachmentPointForBond: string | null;
public chosenSecondAttachmentPointForBond: string | null;

public potentialAttachmentPointsToBonds: {
[key: string]: PolymerBond | null | undefined;
} = {
R1: null,
};
} = {};

public attachmentPointsVisible = false;
public monomerItem: MonomerItemType;
constructor(monomerItem: MonomerItemType, _position?: Vec2) {
super(_position);

this.monomerItem = { ...monomerItem };
this.attachmentPointsToBonds = this.getAttachmentPointDict();
this.potentialAttachmentPointsToBonds = this.getAttachmentPointDict();
if (!this.monomerItem.props.isMicromoleculeFragment) {
this.attachmentPointsToBonds = this.getAttachmentPointDict();
this.potentialAttachmentPointsToBonds = this.getAttachmentPointDict();
this.monomerItem.attachmentPoints =
this.monomerItem.attachmentPoints ||
this.getMonomerDefinitionAttachmentPoints();
}
this.chosenFirstAttachmentPointForBond = null;
this.potentialSecondAttachmentPointForBond = null;
this.chosenSecondAttachmentPointForBond = null;
this.monomerItem.attachmentPoints =
this.monomerItem.attachmentPoints ||
this.getMonomerDefinitionAttachmentPoints();
}

public get label() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,12 @@ export class KetSerializer implements Serializer<Struct> {
});
drawingEntitiesManager.polymerBonds.forEach((polymerBond) => {
assert(polymerBond.secondMonomer);
if (
polymerBond.firstMonomer.monomerItem.props.isMicromoleculeFragment ||
polymerBond.secondMonomer.monomerItem.props.isMicromoleculeFragment
) {
return;
}
fileContent.root.connections.push({
connectionType: 'single',
endpoint1: {
Expand Down

0 comments on commit 10844db

Please sign in to comment.