Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ import {
Render,
} from 'application/render';
import {
type Struct,
Atom,
Bond,
Pool,
RGroupAttachmentPoint,
SGroup,
SUPERATOM_CLASS,
Struct,
Vec2,
} from 'domain/entities';
import { restruct } from '../../../mock-data';
import { mockFn } from 'jest-mock-extended';
import type { RenderOptions } from 'application/render/render.types';
import { RenderStruct } from 'application/render/renderStruct';

describe('resgroup should draw brackets with attachment points correctly', () => {
const mockBonds = [
Expand Down Expand Up @@ -106,8 +109,9 @@ describe('resgroup should draw brackets with attachment points correctly', () =>
height: 100,
} as RenderOptions;
const render = new Render(document as unknown as HTMLElement, option);
render.ctab = restruct as unknown as ReStruct;
restruct.render = render as any;
const reStruct = restruct as unknown as ReStruct;
render.ctab = reStruct;
reStruct.render = render;
sGroup = new SGroup('MUL');
reSgroup = new ReSGroup(sGroup);
sGroup.isNotContractible = mockFn().mockReturnValue(false);
Expand Down Expand Up @@ -144,7 +148,7 @@ describe('resgroup should draw brackets with attachment points correctly', () =>
restruct.rgroupAttachmentPoints.set(1, reRGroupAttachmentPoint);
restruct.molecule.getRGroupAttachmentPointsByAtomId =
mockFn().mockReturnValue([0, 1]);
reSgroup.draw(restruct, sGroup);
reSgroup.draw(restruct as unknown as ReStruct, sGroup);
expect(attachmentsSpy).toHaveBeenCalled();
});

Expand All @@ -169,3 +173,50 @@ describe('resgroup should draw brackets with attachment points correctly', () =>
expect(attachmentsSpy).toHaveBeenCalled();
});
});

describe('resgroup should draw nucleotide component S-groups', () => {
it('should draw nucleotide component brackets and class label', () => {
const option = {
microModeScale: 20,
width: 100,
height: 100,
} as RenderOptions;
const render = new Render(document as unknown as HTMLElement, option);
const reStruct = restruct as unknown as ReStruct;
render.ctab = reStruct;
reStruct.render = render;

const sGroup = new SGroup('nucleotideComponent');
const reSgroup = new ReSGroup(sGroup);
const atomIdWithAttachmentPoint = 2;
sGroup.data.class = SUPERATOM_CLASS.BASE;
SGroup.addAtom(
sGroup,
atomIdWithAttachmentPoint,
restruct.molecule as unknown as Struct,
);

reSgroup.draw(reStruct, sGroup);

expect(
render.paper.canvas.querySelector('[data-label-text="Base"]'),
).toBeTruthy();
});
});

describe('RenderStruct.prepareStruct in macromolecules mode', () => {
it('should preserve S-groups for macromolecules rendering', () => {
const struct = new Struct();
const atomId = struct.atoms.add(new Atom({ label: 'C' }));
const sGroup = new SGroup('GEN');
SGroup.addAtom(sGroup, atomId, struct);
sGroup.id = struct.sgroups.add(sGroup);

const preparedStruct = RenderStruct.prepareStruct(struct, true);
const preparedSGroup = preparedStruct.sgroups.get(sGroup.id);

expect(preparedStruct.sgroups.size).toBe(1);
expect(preparedSGroup?.type).toBe(sGroup.type);
expect(preparedSGroup?.atoms).toEqual(sGroup.atoms);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
RxnArrow,
RxnPlus,
SimpleObject,
SGroup,
Struct,
Text,
Vec2,
} from 'domain/entities';
Expand Down Expand Up @@ -267,6 +269,24 @@ describe('serialize (ToKet)', () => {
expect(spy.mock.results[2].value.sgroups[5].subscript).toEqual('n');
expect(spy.mock.results[2].value.sgroups[5].connectivity).toEqual('HT');
});
it('serializes and deserializes nucleotide component S-groups', () => {
const struct = new Struct();
const sgroup = new SGroup('nucleotideComponent');
sgroup.atoms = [0];
sgroup.data.class = 'BASE';
struct.sgroups.add(sgroup);

const serialized = moleculeToKet.moleculeToKet(struct);
expect(serialized.sgroups[0]).toEqual({
type: 'nucleotideComponent',
atoms: [0],
class: 'BASE',
});

const deserialized = moleculeToStruct.sgroupToStruct(serialized.sgroups[0]);
expect(deserialized.type).toEqual('nucleotideComponent');
expect(deserialized.data.class).toEqual('BASE');
});
it('rgroupToKet', () => {
const spy = jest.spyOn(rgroupToKet, 'rgroupToKet');
const result = JSON.parse(ket.serialize(contentRgroupStruct)).rg14;
Expand Down
10 changes: 8 additions & 2 deletions packages/ketcher-core/src/application/render/renderStruct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ export class RenderStruct {
* for S-Groups we want to show expanded structure
* without brackets
*/
static prepareStruct(struct: Struct) {
static prepareStruct(struct: Struct, preserveSgroups = false) {
if (struct.sgroups.size > 0) {
const newStruct = struct.clone();
convertAllSGroupAttachmentPointsToRGroupAttachmentPoints(newStruct);
if (preserveSgroups) {
return newStruct;
}
if (!newStruct.sgroups.get(0)?.isSuperatomWithoutLabel) {
newStruct.sgroups.delete(0);
}
Expand Down Expand Up @@ -78,7 +81,10 @@ export class RenderStruct {
return;
}

const preparedStruct = this.prepareStruct(struct.clone());
const preparedStruct = this.prepareStruct(
struct.clone(),
window.isPolymerEditorTurnedOn,
);
preparedStruct.initHalfBonds();
preparedStruct.initNeighbors();
preparedStruct.setImplicitHydrogen();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,14 @@ class ReSGroup extends ReObject {
SGroupdrawBracketsOptions.superatomClass = sgroup.data.class;
break;
}
case 'nucleotideComponent': {
SGroupdrawBracketsOptions.lowerIndexText =
SUPERATOM_CLASS_TEXT[sgroup.data.class];
SGroupdrawBracketsOptions.upperIndexText = null;
SGroupdrawBracketsOptions.indexAttribute = { 'font-style': 'italic' };
SGroupdrawBracketsOptions.superatomClass = sgroup.data.class;
break;
}
case 'DAT': {
set = drawGroupDat(remol, sgroup);
break;
Expand All @@ -166,6 +174,7 @@ class ReSGroup extends ReObject {
'GEN',
'COP',
'queryComponent',
'nucleotideComponent',
];
if (
sgroupTypesWithBrackets.includes(sgroup.type) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ export function sgroupToStruct(source) {
);
break;
}
case 'nucleotideComponent': {
ifDef(sgroup.data, 'class', source.class);
break;
}
case 'DAT': {
ifDef(sgroup.data, 'absolute', source.placement);
ifDef(sgroup.data, 'attached', source.display);
Expand Down
11 changes: 10 additions & 1 deletion packages/ketcher-core/src/domain/serializers/ket/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,16 @@
},
"type": {
"type": "string",
"enum": ["GEN", "MUL", "SRU", "SUP", "DAT", "queryComponent", "COP"]
"enum": [
"GEN",
"MUL",
"SRU",
"SUP",
"DAT",
"queryComponent",
"nucleotideComponent",
"COP"
]
}
},
"if": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ function sgroupToKet(struct: Struct, source: SGroup) {
);
break;
}
case 'nucleotideComponent': {
ifDef(result, 'class', source.data.class);
break;
}
case 'DAT': {
const data = source.data;
ifDef(result, 'placement', data.absolute, true);
Expand Down