Skip to content

Commit

Permalink
MobiDB lite standardization
Browse files Browse the repository at this point in the history
  • Loading branch information
apolignano committed Feb 12, 2025
1 parent a288127 commit ea1da61
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 148 deletions.
28 changes: 0 additions & 28 deletions src/components/Protein/Isoforms/Viewer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,38 +142,10 @@ const Viewer = ({ isoform, data }: LoadedProps) => {
const { accession, length, sequence, features } = data.payload;
const dataProtvista = features2protvista(features);

const mainTracks = [
'alphafold confidence',
'family',
'domain',
'pathogenic and likely pathogenic variants',
'intrinsically disordered regions',
'spurious proteins',
'residues',
];

const hideCategories = {
'secondary structure': false,
family: false,
domain: false,
repeat: false,
'conserved site': false,
'active site': false,
'binding site': false,
ptm: false,
'match conservation': false,
'coiled-coils, signal peptides, transmembrane regions': false,
'short linear motifs': false,
'pfam-n': false,
funfam: false,
};

return (
<div className={css('isoform-panel')}>
<IsoformHeader accession={accession} length={length} />
<ProteinViewer
mainTracks={mainTracks}
hideCategories={hideCategories}
protein={{ sequence, length: sequence.length }}
data={dataProtvista}
title="Entry matches to this isoform"
Expand Down
30 changes: 17 additions & 13 deletions src/components/ProteinViewer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import {
FeatureLocation,
} from '@nightingale-elements/nightingale-track';

import { typeNameToSectionName, standardizePTMData } from './utils';
import {
typeNameToSectionName,
standardizePTMData,
firstHideCategories,
} from './utils';

import {
useFloating,
Expand Down Expand Up @@ -111,16 +115,9 @@ type Props = PropsWithChildren<{
conservationError?: string;
/** TO include loading animation in the header */
loading: boolean;

viewerType: string;

changeSettingsRaw: typeof changeSettingsRaw;

showMoreSettings: boolean;

mainTracks: string[];

hideCategories: Record<string, boolean>;
}>;

interface LoadedProps extends Props, LoadDataProps<RootAPIPayload, 'Base'> {}
Expand Down Expand Up @@ -153,9 +150,7 @@ const switchCategoryVisibilityShowMore = (
};

export const ProteinViewer = ({
mainTracks,
viewerType,
hideCategories,
protein,
title,
data,
Expand All @@ -170,10 +165,19 @@ export const ProteinViewer = ({
}: LoadedProps) => {
const [isPrinting, setPrinting] = useState(false);

const mainTracks = [
'alphafold confidence',
'domain',
'family',
'active site',
'conserved site',
'intrinsically disordered regions',
];

/// STATE
const [showMore, setShowMore] = useState(showMoreSettings);
const [hideCategory, setHideCategory] =
useState<CategoryVisibility>(hideCategories);
useState<CategoryVisibility>(firstHideCategories);
const categoryRefs = useRef<ExpandedHandle[]>([]);
const [_, setOverTooltip, overTooltipRef] = useStateRef(false);
const arrowRef = useRef(null);
Expand Down Expand Up @@ -245,7 +249,7 @@ export const ProteinViewer = ({
If the representative track is not available, nothing would be shown. This prevents it, showing all the matches anyway.
*/
const changeVisibilityFor: string[] = [];
['familiy', 'domain'].forEach((type) => {
['family', 'domain'].forEach((type) => {
const entries = data.find(([entryType]) => entryType === type)?.[1] || [];
const hasRep = (entries as ExtendedFeature[]).some(
(entry) => entry.representative === true,
Expand Down Expand Up @@ -357,7 +361,7 @@ export const ProteinViewer = ({
}

// Transform PTM data to track-like data
else if (type == 'ptm') {
if (type == 'ptm') {
entries = standardizePTMData(entries, protein);
}

Expand Down
25 changes: 24 additions & 1 deletion src/components/ProteinViewer/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,23 @@ export const typeNameToSectionName: Record<string, string> = {
'external sources': 'External Sources',
};

export const firstHideCategories = {
'secondary structure': false,
family: false,
domain: false,
repeat: false,
'conserved site': false,
residues: false,
'active site': false,
'binding site': false,
ptm: false,
'match conservation': false,
'coiled-coils, signal peptides, transmembrane regions': false,
'short linear motifs': false,
'pfam-n': false,
funfam: false,
};

export type PTM = {
position: number;
name: string;
Expand Down Expand Up @@ -176,7 +193,7 @@ const processData = <M = Metadata>(
};
};

const ptmFeaturesFragments = (features: PTMFeature[]): PTMFragment[] => {
export const ptmFeaturesFragments = (features: PTMFeature[]): PTMFragment[] => {
const ptmFragments: PTMFragment[] = [];

features.map((feature) => {
Expand Down Expand Up @@ -236,13 +253,19 @@ export const standardizePTMData = (
locations: [{ fragments: fragments }],
};

console.log('f', newFeature);

ptmsEntriesGroupedByModification.push(newFeature);
});

console.log('here', ptmsEntriesGroupedByModification);

// PTMs coming from InterPro and external API should be in the same section but require different processing due to different structure (see above)
entries = ptmsEntriesGroupedByModification.concat(
entries.filter((entry) => entry.source_database === 'interpro'),
);

console.log('final', entries);

return [...entries];
};
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,11 @@ const ProteinViewerLoaded = ({
};
});

// List of "main" tracks to be displayed, the rest are hidden by default
const mainTracks = [
'secondary structure',
'family',
'domain',
'conserved site',
'active site',
];

const hideCategories = {
'secondary structure': false,
family: false,
domain: false,
'conserved site': false,
'active site': false,
};

const enrichedTracks = [...tracks];

return (
<div ref={protvistaEl}>
<ProteinViewer
mainTracks={mainTracks}
hideCategories={hideCategories}
protein={protein}
data={enrichedTracks}
id={id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ const standardizeMobiDBFeatureStructure = (
tempFeature.locations = slicedTempFeatureLocations;
newFeatures.push(tempFeature);
});

return newFeatures;
};

Expand Down Expand Up @@ -307,8 +308,6 @@ const DomainsOnProteinLoaded = ({
(mainData as ProteinEntryPayload).metadata ||
(mainData as { payload: ProteinEntryPayload }).payload.metadata;

let mainTracks: string[] = [];
let hideCategories: Record<string, boolean> = {};
let flattenedData = undefined;

if (dataConfidence)
Expand Down Expand Up @@ -375,22 +374,22 @@ const DomainsOnProteinLoaded = ({
dataMerged['unintegrated'] = [...filteredUnintegrated];
}

console.log(accessionsToRemoveFromUnintegrated);

// Create PTM section
if (dataMerged['intrinsically_disordered_regions']) {
dataMerged['intrinsically_disordered_regions'] =
standardizeMobiDBFeatureStructure(
dataMerged['intrinsically_disordered_regions'] as ExtendedFeature[],
);
}

let proteinViewerData = proteinViewerReorganization(
dataFeatures,
dataMerged as ProteinViewerDataObject<MinimalFeature>,
);
proteinViewerData = sectionsReorganization(proteinViewerData);

// Create PTM section
if (proteinViewerData['intrinsically_disordered_regions']) {
proteinViewerData['intrinsically_disordered_regions'] =
standardizeMobiDBFeatureStructure(
proteinViewerData[
'intrinsically_disordered_regions'
] as ExtendedFeature[],
);
}

// Sort data by match position, but exclude PIRSR, which is sorted in proteinViewerReorganization
Object.entries(
proteinViewerData as ProteinViewerDataObject<ExtendedFeature>,
Expand Down Expand Up @@ -420,65 +419,12 @@ const DomainsOnProteinLoaded = ({
dataMerged[representativeToSection[track]] = dataMerged[
representativeToSection[track]
].concat(dataMerged[track]);

// Remove representative_x track
dataMerged[track] = [];
}
});

mainTracks = [
'alphafold confidence',
'family',
'domain',
'pathogenic and likely pathogenic variants',
'intrinsically disordered regions',
'spurious proteins',
'residues',
'unintegrated',
'other features',
'other residues',
];

hideCategories = {
'secondary structure': false,
family: false,
domain: false,
repeat: false,
'conserved site': false,
'active site': false,
'binding site': false,
ptm: false,
'match conservation': false,
'coiled-coils, signal peptides, transmembrane regions': false,
'short linear motifs': false,
'pfam-n': false,
funfam: false,
};
} else {
mainTracks = [
'alphafold confidence',
'family',
'domain',
'pathogenic and likely pathogenic variants',
'intrinsically disordered regions',
'spurious proteins',
'residues',
];

hideCategories = {
'secondary structure': false,
family: false,
domain: false,
repeat: false,
'conserved site': false,
residues: false,
'active site': false,
'binding site': false,
ptm: false,
'match conservation': false,
'coiled-coils, signal peptides, transmembrane regions': false,
'short linear motifs': false,
'pfam-n': false,
funfam: false,
};

flattenedData = flattenTracksObject(dataMerged);
}

Expand All @@ -493,8 +439,6 @@ const DomainsOnProteinLoaded = ({
handleConservationLoad={handleConservationLoad}
conservationError={conservationError}
loading={loading}
mainTracks={mainTracks}
hideCategories={hideCategories}
>
{children}
</ProteinViewer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,31 +151,14 @@ const ProteinViewerForAlphafold = ({
if (dataConfidence) addConfidenceTrack(dataConfidence, protein, groups);
const tracks = flattenTracksObject(groups);

const mainTracks = [
'alphafold confidence',
'domain',
'family',
'active site',
'conserved site',
];

if (!dataProtein.payload?.metadata) return null;

const hideCategories = {
domain: false,
family: false,
'active site': false,
'conserved site': false,
};

return (
<div ref={trackRef}>
<ProteinViewer
viewerType={'structures'}
protein={dataProtein.payload.metadata}
data={tracks}
mainTracks={mainTracks}
hideCategories={hideCategories}
title="Protein domains"
showOptions={!isSplitScreen}
/>
Expand Down

0 comments on commit ea1da61

Please sign in to comment.