pdbe.ts 4.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import * as fs from 'fs'
  7. import * as path from 'path'
  8. import { Model } from '../../../../mol-model/structure';
  9. import { StructureQualityReport } from '../../../../mol-model-props/pdbe/structure-quality-report';
  10. import { fetchRetry } from '../../utils/fetch-retry';
  11. import { UUID } from '../../../../mol-util';
  12. import { PDBePreferredAssembly } from '../../../../mol-model-props/pdbe/preferred-assembly';
  13. import { PDBeStructRefDomain } from '../../../../mol-model-props/pdbe/struct-ref-domain';
  14. import { AttachModelProperty } from '../../property-provider';
  15. import { ConsoleLogger } from '../../../../mol-util/console-logger';
  16. import { getParam } from '../../../common/util';
  17. export const PDBe_structureQualityReport: AttachModelProperty = ({ model, params, cache }) => {
  18. const PDBe_apiSourceJson = useFileSource(params)
  19. ? residuewise_outlier_summary.getDataFromAggregateFile(getFilePrefix(params, 'residuewise_outlier_summary'))
  20. : apiQueryProvider(getApiUrl(params, 'residuewise_outlier_summary', 'https://www.ebi.ac.uk/pdbe/api/validation/residuewise_outlier_summary/entry'), cache);
  21. return StructureQualityReport.attachFromCifOrApi(model, { PDBe_apiSourceJson });
  22. }
  23. export const PDBe_preferredAssembly: AttachModelProperty = ({ model, params, cache }) => {
  24. const PDBe_apiSourceJson = apiQueryProvider(getApiUrl(params, 'preferred_assembly', 'https://www.ebi.ac.uk/pdbe/api/pdb/entry/summary'), cache);
  25. return PDBePreferredAssembly.attachFromCifOrApi(model, { PDBe_apiSourceJson });
  26. }
  27. export const PDBe_structRefDomain: AttachModelProperty = ({ model, params, cache }) => {
  28. const PDBe_apiSourceJson = apiQueryProvider(getApiUrl(params, 'struct_ref_domain', 'https://www.ebi.ac.uk/pdbe/api/mappings/sequence_domains'), cache);
  29. return PDBeStructRefDomain.attachFromCifOrApi(model, { PDBe_apiSourceJson });
  30. }
  31. namespace residuewise_outlier_summary {
  32. const json = new Map<string, any>();
  33. export function getDataFromAggregateFile(pathPrefix: string) {
  34. // This is for "testing" purposes and should probably only read
  35. // a single file with the appropriate prop in the "production" version.
  36. return async (model: Model) => {
  37. const key = `${model.label[1]}${model.label[2]}`;
  38. if (!json.has(key)) {
  39. const fn = path.join(pathPrefix, `${key}.json`);
  40. if (!fs.existsSync(fn)) json.set(key, { });
  41. // TODO: use async readFile?
  42. else json.set(key, JSON.parse(fs.readFileSync(fn, 'utf8')));
  43. }
  44. return json.get(key)![model.label.toLowerCase()] || { };
  45. }
  46. }
  47. }
  48. function getApiUrl(params: any, name: string, fallback: string) {
  49. const url = getParam<string>(params, 'PDBe', 'API', name);
  50. if (!url) return fallback;
  51. if (url[url.length - 1] === '/') return url.substring(0, url.length - 1);
  52. return url;
  53. }
  54. function getFilePrefix(params: any, name: string) {
  55. const ret = getParam<string>(params, 'PDBe', 'File', name);
  56. if (!ret) throw new Error(`PDBe file prefix '${name}' not set!`);
  57. return ret;
  58. }
  59. function useFileSource(params: any) {
  60. return !!getParam<boolean>(params, 'PDBe', 'UseFileSource')
  61. }
  62. function apiQueryProvider(urlPrefix: string, cache: any) {
  63. const cacheKey = UUID.create22();
  64. return async (model: Model) => {
  65. try {
  66. if (cache[cacheKey]) return cache[cacheKey];
  67. const rawData = await fetchRetry(`${urlPrefix}/${model.label.toLowerCase()}`, 1500, 5);
  68. // TODO: is this ok?
  69. if (rawData.status !== 200) return { };
  70. const json = (await rawData.json())[model.label.toLowerCase()] || { };
  71. cache[cacheKey] = json;
  72. return json;
  73. } catch (e) {
  74. // TODO: handle better
  75. ConsoleLogger.warn('Props', `Count not retrieve prop @${`${urlPrefix}/${model.label.toLowerCase()}`}`);
  76. return { };
  77. }
  78. }
  79. }