transform.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import CIF from 'mol-io/reader/cif'
  7. import { FileEntity, DataEntity, UrlEntity, CifEntity, MmcifEntity, ModelEntity, StructureEntity, SpacefillEntity, AnyEntity, NullEntity, BallAndStickEntity, DistanceRestraintEntity, CartoonEntity, BackboneEntity, CarbohydrateEntity } from './entity';
  8. import { Model, Structure, Format } from 'mol-model/structure';
  9. import { StateContext } from './context';
  10. import StructureSymmetry from 'mol-model/structure/structure/symmetry';
  11. import { SpacefillProps, SpacefillRepresentation } from 'mol-geo/representation/structure/representation/spacefill';
  12. import { BallAndStickProps, BallAndStickRepresentation } from 'mol-geo/representation/structure/representation/ball-and-stick';
  13. import { DistanceRestraintRepresentation, DistanceRestraintProps } from 'mol-geo/representation/structure/representation/distance-restraint';
  14. import { CartoonRepresentation, CartoonProps } from 'mol-geo/representation/structure/representation/cartoon';
  15. import { BackboneProps, BackboneRepresentation } from 'mol-geo/representation/structure/representation/backbone';
  16. import { CarbohydrateProps, CarbohydrateRepresentation } from 'mol-geo/representation/structure/representation/carbohydrate';
  17. type transformer<I extends AnyEntity, O extends AnyEntity, P extends {}> = (ctx: StateContext, inputEntity: I, props?: P) => Promise<O>
  18. export interface StateTransform<I extends AnyEntity, O extends AnyEntity, P extends {}> {
  19. inputKind: I['kind']
  20. outputKind: O['kind']
  21. kind: string
  22. apply: transformer<I, O, P>
  23. }
  24. export namespace StateTransform {
  25. export function create<I extends AnyEntity, O extends AnyEntity, P extends {}>(inputKind: I['kind'], outputKind: O['kind'], kind: string, transformer: transformer<I, O, P>) {
  26. return { inputKind, outputKind, kind, apply: transformer }
  27. }
  28. }
  29. export type AnyTransform = StateTransform<AnyEntity, AnyEntity, {}>
  30. export type UrlToData = StateTransform<UrlEntity, DataEntity, {}>
  31. export const UrlToData: UrlToData = StateTransform.create('url', 'data', 'url-to-data',
  32. async function (ctx: StateContext, urlEntity: UrlEntity) {
  33. return DataEntity.ofData(ctx, await urlEntity.value.getData(), urlEntity.value.type)
  34. })
  35. export type FileToData = StateTransform<FileEntity, DataEntity, {}>
  36. export const FileToData: FileToData = StateTransform.create('file', 'data', 'file-to-data',
  37. async function (ctx: StateContext, fileEntity: FileEntity) {
  38. return DataEntity.ofData(ctx, await fileEntity.value.getData(), fileEntity.value.type)
  39. })
  40. export type DataToCif = StateTransform<DataEntity, CifEntity, {}>
  41. export const DataToCif: DataToCif = StateTransform.create('data', 'cif', 'data-to-cif',
  42. async function (ctx: StateContext, dataEntity: DataEntity) {
  43. const comp = CIF.parse(dataEntity.value.data)
  44. const parsed = await comp.run(ctx.log)
  45. if (parsed.isError) throw parsed
  46. return CifEntity.ofCifFile(ctx, parsed.result)
  47. })
  48. export type CifToMmcif = StateTransform<CifEntity, MmcifEntity, {}>
  49. export const CifToMmcif: CifToMmcif = StateTransform.create('cif', 'mmcif', 'cif-to-mmcif',
  50. async function (ctx: StateContext, cifEntity: CifEntity) {
  51. const frame = cifEntity.value.blocks[0];
  52. return MmcifEntity.ofMmcifDb(ctx, { frame, db: CIF.schema.mmCIF(frame) })
  53. })
  54. export type MmcifToModel = StateTransform<MmcifEntity, ModelEntity, {}>
  55. export const MmcifToModel: MmcifToModel = StateTransform.create('mmcif', 'model', 'mmcif-to-model',
  56. async function (ctx: StateContext, mmcifEntity: MmcifEntity) {
  57. const models = await Model.create(Format.mmCIF(mmcifEntity.value.frame, mmcifEntity.value.db)).run(ctx.log)
  58. return ModelEntity.ofModels(ctx, models)
  59. })
  60. export interface StructureProps {
  61. assembly?: string
  62. }
  63. export type ModelToStructure = StateTransform<ModelEntity, StructureEntity, StructureProps>
  64. export const ModelToStructure: ModelToStructure = StateTransform.create('model', 'structure', 'model-to-structure',
  65. async function (ctx: StateContext, modelEntity: ModelEntity, props: StructureProps = {}) {
  66. const model = modelEntity.value[0]
  67. const assembly = props.assembly
  68. let structure: Structure
  69. const assemblies = model.symmetry.assemblies
  70. if (assemblies.length) {
  71. structure = await StructureSymmetry.buildAssembly(Structure.ofModel(model), assembly || '1').run(ctx.log)
  72. } else {
  73. structure = Structure.ofModel(model)
  74. }
  75. return StructureEntity.ofStructure(ctx, structure)
  76. })
  77. export type StructureCenter = StateTransform<StructureEntity, NullEntity, {}>
  78. export const StructureCenter: StructureCenter = StateTransform.create('structure', 'null', 'structure-center',
  79. async function (ctx: StateContext, structureEntity: StructureEntity) {
  80. ctx.viewer.center(structureEntity.value.boundary.sphere.center)
  81. return NullEntity
  82. })
  83. export type StructureToSpacefill = StateTransform<StructureEntity, SpacefillEntity, Partial<SpacefillProps>>
  84. export const StructureToSpacefill: StructureToSpacefill = StateTransform.create('structure', 'spacefill', 'structure-to-spacefill',
  85. async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<SpacefillProps> = {}) {
  86. const spacefillRepr = SpacefillRepresentation()
  87. await spacefillRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
  88. ctx.viewer.add(spacefillRepr)
  89. ctx.viewer.requestDraw()
  90. console.log('stats', ctx.viewer.stats)
  91. return SpacefillEntity.ofRepr(ctx, spacefillRepr)
  92. })
  93. export type StructureToBallAndStick = StateTransform<StructureEntity, BallAndStickEntity, Partial<BallAndStickProps>>
  94. export const StructureToBallAndStick: StructureToBallAndStick = StateTransform.create('structure', 'ballandstick', 'structure-to-ballandstick',
  95. async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<BallAndStickProps> = {}) {
  96. const ballAndStickRepr = BallAndStickRepresentation()
  97. await ballAndStickRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
  98. ctx.viewer.add(ballAndStickRepr)
  99. ctx.viewer.requestDraw()
  100. console.log('stats', ctx.viewer.stats)
  101. return BallAndStickEntity.ofRepr(ctx, ballAndStickRepr)
  102. })
  103. export type StructureToDistanceRestraint = StateTransform<StructureEntity, DistanceRestraintEntity, Partial<DistanceRestraintProps>>
  104. export const StructureToDistanceRestraint: StructureToDistanceRestraint = StateTransform.create('structure', 'distancerestraint', 'structure-to-distancerestraint',
  105. async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<DistanceRestraintProps> = {}) {
  106. const distanceRestraintRepr = DistanceRestraintRepresentation()
  107. await distanceRestraintRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
  108. ctx.viewer.add(distanceRestraintRepr)
  109. ctx.viewer.requestDraw()
  110. console.log('stats', ctx.viewer.stats)
  111. return DistanceRestraintEntity.ofRepr(ctx, distanceRestraintRepr)
  112. })
  113. export type StructureToBackbone = StateTransform<StructureEntity, BackboneEntity, Partial<BackboneProps>>
  114. export const StructureToBackbone: StructureToBackbone = StateTransform.create('structure', 'backbone', 'structure-to-backbone',
  115. async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<BackboneProps> = {}) {
  116. const backboneRepr = BackboneRepresentation()
  117. await backboneRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
  118. ctx.viewer.add(backboneRepr)
  119. ctx.viewer.requestDraw()
  120. console.log('stats', ctx.viewer.stats)
  121. return BackboneEntity.ofRepr(ctx, backboneRepr)
  122. })
  123. export type StructureToCartoon = StateTransform<StructureEntity, CartoonEntity, Partial<CartoonProps>>
  124. export const StructureToCartoon: StructureToCartoon = StateTransform.create('structure', 'cartoon', 'structure-to-cartoon',
  125. async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<CartoonProps> = {}) {
  126. const cartoonRepr = CartoonRepresentation()
  127. await cartoonRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
  128. ctx.viewer.add(cartoonRepr)
  129. ctx.viewer.requestDraw()
  130. console.log('stats', ctx.viewer.stats)
  131. return CartoonEntity.ofRepr(ctx, cartoonRepr)
  132. })
  133. export type StructureToCarbohydrate = StateTransform<StructureEntity, CarbohydrateEntity, Partial<CarbohydrateProps>>
  134. export const StructureToCarbohydrate: StructureToCarbohydrate = StateTransform.create('structure', 'carbohydrate', 'structure-to-cartoon',
  135. async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<CarbohydrateProps> = {}) {
  136. const carbohydrateRepr = CarbohydrateRepresentation()
  137. await carbohydrateRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
  138. ctx.viewer.add(carbohydrateRepr)
  139. ctx.viewer.requestDraw()
  140. console.log('stats', ctx.viewer.stats)
  141. return CarbohydrateEntity.ofRepr(ctx, carbohydrateRepr)
  142. })
  143. export type SpacefillUpdate = StateTransform<SpacefillEntity, NullEntity, Partial<SpacefillProps>>
  144. export const SpacefillUpdate: SpacefillUpdate = StateTransform.create('spacefill', 'null', 'spacefill-update',
  145. async function (ctx: StateContext, spacefillEntity: SpacefillEntity, props: Partial<SpacefillProps> = {}) {
  146. const spacefillRepr = spacefillEntity.value
  147. await spacefillRepr.createOrUpdate(props).run(ctx.log)
  148. ctx.viewer.add(spacefillRepr)
  149. ctx.viewer.requestDraw()
  150. console.log('stats', ctx.viewer.stats)
  151. return NullEntity
  152. })
  153. export type BallAndStickUpdate = StateTransform<BallAndStickEntity, NullEntity, Partial<BallAndStickProps>>
  154. export const BallAndStickUpdate: BallAndStickUpdate = StateTransform.create('ballandstick', 'null', 'ballandstick-update',
  155. async function (ctx: StateContext, ballAndStickEntity: BallAndStickEntity, props: Partial<BallAndStickProps> = {}) {
  156. const ballAndStickRepr = ballAndStickEntity.value
  157. await ballAndStickRepr.createOrUpdate(props).run(ctx.log)
  158. ctx.viewer.add(ballAndStickRepr)
  159. ctx.viewer.requestDraw()
  160. console.log('stats', ctx.viewer.stats)
  161. return NullEntity
  162. })
  163. export type DistanceRestraintUpdate = StateTransform<DistanceRestraintEntity, NullEntity, Partial<DistanceRestraintProps>>
  164. export const DistanceRestraintUpdate: DistanceRestraintUpdate = StateTransform.create('distancerestraint', 'null', 'distancerestraint-update',
  165. async function (ctx: StateContext, distanceRestraintEntity: DistanceRestraintEntity, props: Partial<DistanceRestraintProps> = {}) {
  166. const distanceRestraintRepr = distanceRestraintEntity.value
  167. await distanceRestraintRepr.createOrUpdate(props).run(ctx.log)
  168. ctx.viewer.add(distanceRestraintRepr)
  169. ctx.viewer.requestDraw()
  170. console.log('stats', ctx.viewer.stats)
  171. return NullEntity
  172. })
  173. export type BackboneUpdate = StateTransform<BackboneEntity, NullEntity, Partial<BackboneProps>>
  174. export const BackboneUpdate: BackboneUpdate = StateTransform.create('backbone', 'null', 'backbone-update',
  175. async function (ctx: StateContext, backboneEntity: BackboneEntity, props: Partial<BackboneProps> = {}) {
  176. const backboneRepr = backboneEntity.value
  177. await backboneRepr.createOrUpdate(props).run(ctx.log)
  178. ctx.viewer.add(backboneRepr)
  179. ctx.viewer.requestDraw()
  180. console.log('stats', ctx.viewer.stats)
  181. return NullEntity
  182. })
  183. export type CartoonUpdate = StateTransform<CartoonEntity, NullEntity, Partial<CartoonProps>>
  184. export const CartoonUpdate: CartoonUpdate = StateTransform.create('cartoon', 'null', 'cartoon-update',
  185. async function (ctx: StateContext, cartoonEntity: CartoonEntity, props: Partial<CartoonProps> = {}) {
  186. const cartoonRepr = cartoonEntity.value
  187. await cartoonRepr.createOrUpdate(props).run(ctx.log)
  188. ctx.viewer.add(cartoonRepr)
  189. ctx.viewer.requestDraw()
  190. console.log('stats', ctx.viewer.stats)
  191. return NullEntity
  192. })
  193. export type CarbohydrateUpdate = StateTransform<CarbohydrateEntity, NullEntity, Partial<CarbohydrateProps>>
  194. export const CarbohydrateUpdate: CarbohydrateUpdate = StateTransform.create('carbohydrate', 'null', 'carbohydrate-update',
  195. async function (ctx: StateContext, carbohydrateEntity: CarbohydrateEntity, props: Partial<CarbohydrateProps> = {}) {
  196. const carbohydrateRepr = carbohydrateEntity.value
  197. await carbohydrateRepr.createOrUpdate(props).run(ctx.log)
  198. ctx.viewer.add(carbohydrateRepr)
  199. ctx.viewer.requestDraw()
  200. console.log('stats', ctx.viewer.stats)
  201. return NullEntity
  202. })
  203. // composed
  204. export type MmcifUrlToModel = StateTransform<UrlEntity, ModelEntity, {}>
  205. export const MmcifUrlToModel: MmcifUrlToModel = StateTransform.create('url', 'model', 'url-to-model',
  206. async function (ctx: StateContext, urlEntity: UrlEntity) {
  207. const dataEntity = await UrlToData.apply(ctx, urlEntity)
  208. return DataToModel.apply(ctx, dataEntity)
  209. })
  210. export type MmcifFileToModel = StateTransform<FileEntity, ModelEntity, {}>
  211. export const MmcifFileToModel: MmcifFileToModel = StateTransform.create('file', 'model', 'file-to-model',
  212. async function (ctx: StateContext, fileEntity: FileEntity) {
  213. const dataEntity = await FileToData.apply(ctx, fileEntity)
  214. return DataToModel.apply(ctx, dataEntity)
  215. })
  216. export type DataToModel = StateTransform<DataEntity, ModelEntity, {}>
  217. export const DataToModel: DataToModel = StateTransform.create('data', 'model', 'data-to-model',
  218. async function getModelFromData(ctx: StateContext, dataEntity: DataEntity) {
  219. const cifEntity = await DataToCif.apply(ctx, dataEntity)
  220. const mmcifEntity = await CifToMmcif.apply(ctx, cifEntity)
  221. return MmcifToModel.apply(ctx, mmcifEntity)
  222. })
  223. export type ModelToSpacefill = StateTransform<ModelEntity, SpacefillEntity, Partial<SpacefillProps>>
  224. export const ModelToSpacefill: ModelToSpacefill = StateTransform.create('model', 'spacefill', 'model-to-spacefill',
  225. async function (ctx: StateContext, modelEntity: ModelEntity, props: Partial<SpacefillProps> = {}) {
  226. const structureEntity = await ModelToStructure.apply(ctx, modelEntity)
  227. // StructureToBond.apply(ctx, structureEntity, props)
  228. return StructureToSpacefill.apply(ctx, structureEntity, props)
  229. })
  230. export type MmcifUrlToSpacefill = StateTransform<UrlEntity, SpacefillEntity, Partial<SpacefillProps>>
  231. export const MmcifUrlToSpacefill: MmcifUrlToSpacefill = StateTransform.create('url', 'spacefill', 'url-to-spacefill',
  232. async function (ctx: StateContext, urlEntity: UrlEntity, props: Partial<SpacefillProps> = {}) {
  233. const modelEntity = await MmcifUrlToModel.apply(ctx, urlEntity)
  234. return ModelToSpacefill.apply(ctx, modelEntity, props)
  235. })
  236. export type MmcifFileToSpacefill = StateTransform<FileEntity, SpacefillEntity, Partial<SpacefillProps>>
  237. export const MmcifFileToSpacefill: MmcifFileToSpacefill = StateTransform.create('file', 'spacefill', 'file-to-spacefill',
  238. async function (ctx: StateContext, fileEntity: FileEntity, props: Partial<SpacefillProps> = {}) {
  239. const modelEntity = await MmcifFileToModel.apply(ctx, fileEntity)
  240. return ModelToSpacefill.apply(ctx, modelEntity, props)
  241. })