Skip to content

Commit

Permalink
#5556 - Allow import and export of sequences with three letter amino …
Browse files Browse the repository at this point in the history
…acid codes (#5889)
  • Loading branch information
rrodionov91 authored Oct 31, 2024
1 parent 500aee0 commit d851892
Show file tree
Hide file tree
Showing 124 changed files with 94 additions and 32 deletions.
2 changes: 1 addition & 1 deletion ketcher-autotests/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const config: PlaywrightTestConfig = {
},
],
['line'],
['./reporters/TimeReporter.ts'],
// ['./reporters/TimeReporter.ts'],
],
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ test.describe('Import-Saving .idt Files', () => {
const expectedValues = [
'Ket',
'MDL Molfile V3000',
'Sequence',
'Sequence (1-letter code)',
'Sequence (3-letter code)',
'FASTA',
'IDT',
'SVG Document',
Expand Down Expand Up @@ -979,7 +980,10 @@ test.describe('Import-Saving .idt Files', () => {
await takeEditorScreenshot(page);
});

const testFormats: Array<'FASTA' | 'Sequence'> = ['FASTA', 'Sequence'];
const testFormats: Array<'FASTA' | 'Sequence (1-letter code)'> = [
'FASTA',
'Sequence (1-letter code)',
];

for (const format of testFormats) {
test(`Verify error message when saving macromolecules with unresolved monomers to non-IDT/KET format ${format}`, async () => {
Expand Down
Diff not rendered.
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ test.describe('Import-Saving .seq Files', () => {
}) => {
await openFileAndAddToCanvasMacro('KET/rna-a.ket', page);
await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await page
.getByTestId('dropdown-select')
.getByRole('combobox')
Expand All @@ -204,7 +204,7 @@ test.describe('Import-Saving .seq Files', () => {
}) => {
await openFileAndAddToCanvasMacro('KET/rna-and-peptide.ket', page);
await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');

await takeEditorScreenshot(page);
});
Expand All @@ -215,7 +215,7 @@ test.describe('Import-Saving .seq Files', () => {
}) => {
await openFileAndAddToCanvasMacro('KET/chems-not-connected.ket', page);
await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');

await takeEditorScreenshot(page);
});
Expand Down Expand Up @@ -282,7 +282,7 @@ test.describe('Import-Saving .seq Files', () => {
await takeEditorScreenshot(page);

await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await takeEditorScreenshot(page);

await pressButton(page, 'Cancel');
Expand Down Expand Up @@ -311,7 +311,7 @@ test.describe('Import-Saving .seq Files', () => {
await takeEditorScreenshot(page);

await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await takeEditorScreenshot(page);

test.fixme(
Expand Down Expand Up @@ -348,7 +348,7 @@ test.describe('Import-Saving .seq Files', () => {
await takeEditorScreenshot(page);

await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await takeEditorScreenshot(page);

test.fixme(
Expand Down Expand Up @@ -385,7 +385,7 @@ test.describe('Import-Saving .seq Files', () => {
await takeEditorScreenshot(page);

await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await takeEditorScreenshot(page);

test.fixme(
Expand Down Expand Up @@ -421,7 +421,7 @@ test.describe('Import-Saving .seq Files', () => {
await takeEditorScreenshot(page);

await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await takeEditorScreenshot(page);

await pressButton(page, 'Cancel');
Expand Down Expand Up @@ -450,7 +450,7 @@ test.describe('Import-Saving .seq Files', () => {
await takeEditorScreenshot(page);

await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await takeEditorScreenshot(page);

test.fixme(
Expand Down Expand Up @@ -486,7 +486,7 @@ test.describe('Import-Saving .seq Files', () => {
await takeEditorScreenshot(page);

await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await takeEditorScreenshot(page);

await pressButton(page, 'Cancel');
Expand Down Expand Up @@ -515,7 +515,7 @@ test.describe('Import-Saving .seq Files', () => {
await takeEditorScreenshot(page);

await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await takeEditorScreenshot(page);

test.fixme(
Expand Down Expand Up @@ -551,7 +551,7 @@ test.describe('Import-Saving .seq Files', () => {
await takeEditorScreenshot(page);

await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await takeEditorScreenshot(page);

await pressButton(page, 'Cancel');
Expand Down Expand Up @@ -580,7 +580,7 @@ test.describe('Import-Saving .seq Files', () => {
await takeEditorScreenshot(page);

await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'Sequence');
await chooseFileFormat(page, 'Sequence (1-letter code)');
await takeEditorScreenshot(page);

test.fixme(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ test.describe('Import/export sequence:', () => {
const expectedValues = [
'Ket',
'MDL Molfile V3000',
'Sequence',
'Sequence (1-letter code)',
'Sequence (3-letter code)',
'FASTA',
'IDT',
];
Expand Down
1 change: 1 addition & 0 deletions ketcher-autotests/tests/utils/macromolecules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export async function chooseFileFormat(
| 'MDL Molfile V3000'
| 'FASTA'
| 'Sequence'
| 'Sequence (1-letter code)'
| 'IDT'
| 'HELM'
| 'SVG Document',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const macromoleculesFilesInputFormats = {
rna: 'chemical/x-rna-sequence',
dna: 'chemical/x-dna-sequence',
peptide: 'chemical/x-peptide-sequence',
peptide3Letter: 'chemical/x-peptide-sequence-3-letter',
},
fasta: {
rna: 'chemical/x-rna-fasta',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export enum ChemicalMimeType {
SDF = 'chemical/x-sdf',
FASTA = 'chemical/x-fasta',
SEQUENCE = 'chemical/x-sequence',
PeptideSequenceThreeLetter = 'chemical/x-peptide-sequence-3-letter',
RNA = 'chemical/x-rna-sequence',
DNA = 'chemical/x-dna-sequence',
PEPTIDE = 'chemical/x-peptide-sequence',
Expand Down
78 changes: 65 additions & 13 deletions packages/ketcher-macromolecules/src/components/modal/Open/Open.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ import {
import { IndigoProvider } from 'ketcher-react';
import { RequiredModalProps } from '../modalContainer';
import { OpenFileWrapper } from './Open.styles';
import { Loader, StyledDropdown, stylesForExpanded } from '../save/Save.styles';
import {
Loader,
StyledDropdown as SaveDropdown,
stylesForExpanded,
} from '../save/Save.styles';
import { LoadingCircles } from './AnalyzingFile/LoadingCircles';
import { useAppDispatch } from 'hooks';
import { openErrorModal } from 'state/modal';
Expand All @@ -50,6 +54,7 @@ const OpenModal = styled(Modal)(
({ modalWidth }) => `
.MuiPaper-root {
width: ${modalWidth};
max-width: ${modalWidth};
}`,
);

Expand All @@ -67,15 +72,35 @@ const FooterSelectorContainer = styled.div({
fontSize: '12px',
});

const FooterFormatSelector = styled(StyledDropdown)((props) => ({
width:
props.currentSelection === 'seq' || props.currentSelection === 'fasta'
? `170px`
: '180px',
const StyledDropdown = styled(SaveDropdown)({
padding: 0,
fontSize: '12px',

'& .MuiSelect-select': {
display: 'flex',
alignItems: 'center',
padding: '0 20px 0 8px',
paddingRight: '20px !important', // override MUI styles
height: '100%',
},

'& span': {
fontSize: '12px',
},
});

const FooterFormatSelector = styled(StyledDropdown)(() => ({
width: '140px',
}));

const FooterSequenceSelector = styled(StyledDropdown)({
width: '110px',
width: '76px',
marginLeft: '8px',
});

const FooterPeptideLettersSelector = styled(StyledDropdown)({
width: '105px',
marginLeft: '8px',
});

const FooterButtonContainer = styled('div')({
Expand All @@ -90,7 +115,10 @@ const FooterButton = styled(ActionButton)({
const KET = 'ket';
const SEQ = 'seq';
const RNA = 'rna';
const PEPTIDE = 'peptide';
const FASTA = 'fasta';
const ONE_LETTER = 'one-letter';
const THREE_LETTER = 'three-letter';

const options: Array<Option> = [
{ id: 'ket', label: 'Ket' },
Expand All @@ -102,9 +130,14 @@ const options: Array<Option> = [
];

const additionalOptions: Array<Option> = [
{ id: 'rna', label: 'RNA' },
{ id: RNA, label: 'RNA' },
{ id: 'dna', label: 'DNA' },
{ id: 'peptide', label: 'Peptide' },
{ id: PEPTIDE, label: 'Peptide' },
];

const peptideLettersFormatOptions: Array<Option> = [
{ id: ONE_LETTER, label: '1-letter code' },
{ id: THREE_LETTER, label: '3-letter code' },
];

const inputFormats = macromoleculesFilesInputFormats;
Expand Down Expand Up @@ -172,13 +205,15 @@ const onOk = async ({
struct,
formatSelection,
additionalSelection,
peptideLettersFormatSelection,
onCloseCallback,
setIsLoading,
dispatch,
}: {
struct: string;
formatSelection: string;
additionalSelection: string;
peptideLettersFormatSelection: string;
onCloseCallback: () => void;
setIsLoading: (isLoading: boolean) => void;
dispatch: Dispatch<AnyAction>;
Expand Down Expand Up @@ -209,9 +244,14 @@ const onOk = async ({
showParsingError('Error during file parsing.');
}
return;
} else if (isSeq || isFasta) {
} else if (
isFasta ||
(isSeq && peptideLettersFormatSelection !== THREE_LETTER)
) {
inputFormat = inputFormats[formatSelection][additionalSelection];
fileData = fileData.toUpperCase();
} else if (isSeq && peptideLettersFormatSelection === THREE_LETTER) {
inputFormat = inputFormats.seq.peptide3Letter;
} else {
inputFormat = inputFormats[formatSelection];
}
Expand Down Expand Up @@ -252,6 +292,8 @@ const Open = ({ isModalOpen, onClose }: RequiredModalProps) => {
);
const [formatSelection, setFormatSelection] = useState(KET);
const [additionalSelection, setAdditionalSelection] = useState(RNA);
const [peptideLettersFormatSelection, setPeptideLettersFormatSelection] =
useState(ONE_LETTER);

useEffect(() => {
const splittedFilenameByDot = fileName?.split('.');
Expand Down Expand Up @@ -290,11 +332,12 @@ const Open = ({ isModalOpen, onClose }: RequiredModalProps) => {
opener?.chosenOpener(files[0]).then(onLoad, onError);
};

const copyHandler = () => {
const addToCanvasHandler = () => {
onOk({
struct: structStr,
formatSelection,
additionalSelection,
peptideLettersFormatSelection,
onCloseCallback,
setIsLoading,
dispatch,
Expand All @@ -314,6 +357,7 @@ const Open = ({ isModalOpen, onClose }: RequiredModalProps) => {
struct: structStr,
formatSelection,
additionalSelection,
peptideLettersFormatSelection,
onCloseCallback,
setIsLoading,
dispatch,
Expand All @@ -340,6 +384,14 @@ const Open = ({ isModalOpen, onClose }: RequiredModalProps) => {
testId="dropdown-select-type"
/>
) : null}
{formatSelection === SEQ && additionalSelection === PEPTIDE ? (
<FooterPeptideLettersSelector
options={peptideLettersFormatOptions}
currentSelection={peptideLettersFormatSelection}
selectionHandler={setPeptideLettersFormatSelection}
testId="dropdown-select-peptide-letters-format"
/>
) : null}
</FooterSelectorContainer>
<FooterButtonContainer>
<FooterButton
Expand All @@ -352,7 +404,7 @@ const Open = ({ isModalOpen, onClose }: RequiredModalProps) => {
<FooterButton
key="copyButton"
disabled={!structStr}
clickHandler={copyHandler}
clickHandler={addToCanvasHandler}
label="Add to Canvas"
title="Structure will be loaded as fragment and added to Clipboard"
data-testid="add-to-canvas-button"
Expand All @@ -366,7 +418,7 @@ const Open = ({ isModalOpen, onClose }: RequiredModalProps) => {
isOpen={isModalOpen}
title="Open Structure"
onClose={onCloseCallback}
modalWidth={currentState === MODAL_STATES.textEditor ? '600px' : ''}
modalWidth={currentState === MODAL_STATES.textEditor ? '620px' : ''}
>
<Modal.Content>
<OpenFileWrapper currentState={currentState}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Object {
aria-hidden="true"
/>
<div
class="MuiDialog-root MuiModal-root css-1rgipzt-MuiModal-root-MuiDialog-root"
class="MuiDialog-root MuiModal-root css-1ezeeef-MuiModal-root-MuiDialog-root"
role="presentation"
>
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ import { openErrorModal } from 'state/modal';
const options: Array<Option> = [
{ id: 'ket', label: 'Ket' },
{ id: 'mol', label: 'MDL Molfile V3000' },
{ id: 'sequence', label: 'Sequence' },
{ id: 'sequence', label: 'Sequence (1-letter code)' },
{ id: 'sequence-3-letter', label: 'Sequence (3-letter code)' },
{ id: 'fasta', label: 'FASTA' },
{ id: 'idt', label: 'IDT' },
{ id: 'svg', label: 'SVG Document' },
Expand All @@ -60,6 +61,7 @@ const formatDetector = {
mol: ChemicalMimeType.Mol,
fasta: ChemicalMimeType.FASTA,
sequence: ChemicalMimeType.SEQUENCE,
'sequence-3-letter': ChemicalMimeType.PeptideSequenceThreeLetter,
idt: ChemicalMimeType.IDT,
helm: ChemicalMimeType.HELM,
};
Expand Down

0 comments on commit d851892

Please sign in to comment.