diff --git a/src/mol-plugin/state/actions/structure.ts b/src/mol-plugin/state/actions/structure.ts index d6ba75abdf75e930a23e905b800cfb4ca63126c5..a3481bb0727e518dd3cc3c2d1604bdb58cbd518d 100644 --- a/src/mol-plugin/state/actions/structure.ts +++ b/src/mol-plugin/state/actions/structure.ts @@ -69,6 +69,8 @@ export const GroProvider: DataFormatProvider<any> = { } } +type StructureFormat = 'pdb' | 'cif' | 'gro' + // const DownloadStructurePdbIdSourceOptions = PD.Group({ @@ -99,6 +101,10 @@ const DownloadStructure = StateAction.build({ id: PD.Text('1tqn', { label: 'Id' }), options: DownloadStructurePdbIdSourceOptions }, { isFlat: true }), + 'swissmodel': PD.Group({ + id: PD.Text('Q9Y2I8', { label: 'UniProtKB AC' }), + options: DownloadStructurePdbIdSourceOptions + }, { isFlat: true, description: 'Loads the best homology model or experimental structure' }), 'url': PD.Group({ url: PD.Text(''), format: PD.Select('cif', [['cif', 'CIF'], ['pdb', 'PDB']]), @@ -113,6 +119,7 @@ const DownloadStructure = StateAction.build({ ['rcsb', 'RCSB'], ['pdb-dev', 'PDBDEV'], ['bcif-static', 'BinaryCIF (static PDBe Updated)'], + ['swissmodel', 'SWISS-MODEL'], ['url', 'URL'] ] }) @@ -121,12 +128,13 @@ const DownloadStructure = StateAction.build({ const b = state.build(); const src = params.source; let downloadParams: StateTransformer.Params<Download>[]; - let supportProps = false, asTrajectory = false; + let supportProps = false, asTrajectory = false, format: StructureFormat = 'cif'; switch (src.name) { case 'url': downloadParams = [{ url: src.params.url, isBinary: src.params.isBinary }]; supportProps = !!src.params.options.supportProps; + format = src.params.format break; case 'pdbe-updated': downloadParams = getDownloadParams(src.params.id, id => `https://www.ebi.ac.uk/pdbe/static/entry/${id.toLowerCase()}_updated.cif`, id => `PDBe: ${id}`, false); @@ -155,6 +163,12 @@ const DownloadStructure = StateAction.build({ supportProps = !!src.params.options.supportProps; asTrajectory = !!src.params.options.asTrajectory; break; + case 'swissmodel': + downloadParams = getDownloadParams(src.params.id, id => `https://swissmodel.expasy.org/repository/uniprot/${id.toUpperCase()}.pdb`, id => `SWISS-MODEL: ${id}`, false); + supportProps = !!src.params.options.supportProps; + asTrajectory = !!src.params.options.asTrajectory; + format = 'pdb' + break; default: throw new Error(`${(src as any).name} not supported.`); } @@ -164,7 +178,7 @@ const DownloadStructure = StateAction.build({ } else { for (const download of downloadParams) { const data = b.toRoot().apply(StateTransforms.Data.Download, download, { state: { isGhost: true } }); - const traj = createModelTree(data, src.name === 'url' ? src.params.format : 'cif'); + const traj = createModelTree(data, format); createStructureTree(ctx, traj, supportProps) } } @@ -192,7 +206,7 @@ function createSingleTrajectoryModel(sources: StateTransformer.Params<Download>[ .apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: 0 }); } -export function createModelTree(b: StateBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, format: 'pdb' | 'cif' | 'gro' = 'cif') { +export function createModelTree(b: StateBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, format: StructureFormat = 'cif') { let parsed: StateBuilder.To<PluginStateObject.Molecule.Trajectory> switch (format) { case 'cif': diff --git a/src/mol-plugin/state/transforms/model.ts b/src/mol-plugin/state/transforms/model.ts index a5edcfbfc80ed6a4ba604f956bf741b92e3f0246..0bc62ac0f247f8450e1feeb4e771f31295b0932e 100644 --- a/src/mol-plugin/state/transforms/model.ts +++ b/src/mol-plugin/state/transforms/model.ts @@ -108,7 +108,7 @@ const TrajectoryFromPDB = PluginStateTransform.BuiltIn({ })({ apply({ a }) { return Task.create('Parse PDB', async ctx => { - const parsed = await parsePDB(a.data).runInContext(ctx); + const parsed = await parsePDB(a.data, a.label).runInContext(ctx); if (parsed.isError) throw new Error(parsed.message); const models = await trajectoryFromPDB(parsed.result).runInContext(ctx); const props = { label: models[0].label, description: `${models.length} model${models.length === 1 ? '' : 's'}` }; @@ -222,7 +222,7 @@ const StructureAssemblyFromModel = PluginStateTransform.BuiltIn({ const base = Structure.ofModel(model); if (!asm) { await ensureSecondaryStructure(base) - const label = { label: a.data.label, description: structureDesc(base) }; + const label = { label: 'Deposited', description: structureDesc(base) }; return new SO.Molecule.Structure(base, label); }