AssemblyPfvManagerFactory.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import {
  2. RcsbFvModulePublicInterface
  3. } from "@rcsb/rcsb-saguaro-app/build/dist/RcsbFvWeb/RcsbFvModule/RcsbFvModuleInterface";
  4. import {
  5. ChainInfo, OperatorInfo,
  6. } from "../../../../RcsbFvStructure/StructureViewerInterface";
  7. import {
  8. InstanceSequenceConfig
  9. } from "@rcsb/rcsb-saguaro-app/build/dist/RcsbFvWeb/RcsbFvBuilder/RcsbFvInstanceBuilder";
  10. import {asyncScheduler} from "rxjs";
  11. import {buildInstanceSequenceFv, FeatureType, RcsbFvUI, RcsbRequestContextManager} from "@rcsb/rcsb-saguaro-app";
  12. import {RcsbFvDOMConstants} from "../../../../RcsbFvConstants/RcsbFvConstants";
  13. import {SelectOptionProps} from "@rcsb/rcsb-saguaro-app/build/dist/RcsbFvWeb/RcsbFvComponents/SelectButton";
  14. import {ChainDisplayComponent} from "./AssemblyPfvComponents/ChainDisplayComponent";
  15. import * as React from "react";
  16. import {AnnotationFeatures, Source, Type} from "@rcsb/rcsb-api-tools/build/RcsbGraphQL/Types/Borrego/GqlTypes";
  17. import {
  18. PolymerEntityInstanceInterface
  19. } from "@rcsb/rcsb-saguaro-app/build/dist/RcsbCollectTools/DataCollectors/PolymerEntityInstancesCollector";
  20. import {
  21. InterfaceInstanceTranslate
  22. } from "@rcsb/rcsb-saguaro-app/build/dist/RcsbUtils/Translators/InterfaceInstanceTranslate";
  23. import {DataContainer} from "../../../../Utils/DataContainer";
  24. import {
  25. BuildPfvInterface,
  26. AbstractPfvManager,
  27. PfvManagerFactoryConfigInterface,
  28. PfvManagerInterface,
  29. PfvManagerFactoryInterface
  30. } from "../PfvManagerFactoryInterface";
  31. interface AssemblyPfvManagerInterface extends PfvManagerFactoryConfigInterface<undefined>{
  32. useOperatorsFlag?: boolean;
  33. instanceSequenceConfig?: InstanceSequenceConfig;
  34. }
  35. export class AssemblyPfvManagerFactory implements PfvManagerFactoryInterface<{instanceSequenceConfig: InstanceSequenceConfig|undefined;useOperatorsFlag: boolean | undefined;},undefined> {
  36. public getPfvManager(config: AssemblyPfvManagerInterface): PfvManagerInterface {
  37. return new AssemblyPfvManager(config);
  38. }
  39. }
  40. class AssemblyPfvManager extends AbstractPfvManager<{instanceSequenceConfig?: InstanceSequenceConfig;useOperatorsFlag?: boolean;},undefined> {
  41. private readonly instanceSequenceConfig: InstanceSequenceConfig|undefined;
  42. private readonly useOperatorsFlag:boolean | undefined;
  43. private readonly OPERATOR_DROPDOWN_TITLE: string = "Symmetry Partner";
  44. private module: RcsbFvModulePublicInterface | undefined = undefined;
  45. constructor(config: AssemblyPfvManagerInterface) {
  46. super(config);
  47. this.instanceSequenceConfig = config.instanceSequenceConfig;
  48. this.useOperatorsFlag = config.useOperatorsFlag;
  49. }
  50. public async create(config: BuildPfvInterface): Promise<RcsbFvModulePublicInterface | undefined> {
  51. const onChangeCallback: Map<string, (x: PolymerEntityInstanceInterface)=>void> = new Map<string, (x: PolymerEntityInstanceInterface) => {}>();
  52. const assemblyInstances: Map<string, Set<string>> = new Map<string, Set<string>>();
  53. this.stateManager.assemblyModelSate.forEach((v,k)=>{
  54. assemblyInstances.set(v.entryId,new Set<string>(v.chains.map(d=>d.label)));
  55. onChangeCallback.set(v.entryId,(x)=>{
  56. this.stateManager.assemblyModelSate.set({entryId: v.entryId, labelAsymId: x.asymId, modelId: k});
  57. asyncScheduler.schedule(()=>{
  58. this.pfvChangeCallback(undefined);
  59. },100);
  60. });
  61. });
  62. const operatorNameContainer: DataContainer<string> = new DataContainer<string>(config.defaultOperatorName);
  63. if(this.stateManager.assemblyModelSate.get("entryId") != null) {
  64. this.module = await buildInstanceSequenceFv(
  65. this.rcsbFvDivId,
  66. RcsbFvDOMConstants.SELECT_BUTTON_PFV_ID,
  67. this.stateManager.assemblyModelSate.getString("entryId"),
  68. {
  69. ...this.instanceSequenceConfig,
  70. defaultValue: config.defaultAuthId ?? this.instanceSequenceConfig?.defaultValue,
  71. onChangeCallback: onChangeCallback.get(this.stateManager.assemblyModelSate.getString("entryId")),
  72. beforeChangeCallback: (x: PolymerEntityInstanceInterface)=>{
  73. this.stateManager.assemblyModelSate.set({entryId:x.entryId, labelAsymId: x.asymId});
  74. const entryMap:[string, {entryId: string, assemblyId: string, chains: ChainInfo[]}] | undefined = Array.from(this.stateManager.assemblyModelSate.entries()).find((e)=>(e[1].entryId === x.entryId));
  75. if(!entryMap){
  76. throw `Error: no modelId was found for ${x.entryId}`;
  77. }
  78. const operator: OperatorInfo|undefined = getOperator(this.stateManager.assemblyModelSate.getMap().get(entryMap[0])!, config.defaultAuthId, operatorNameContainer.get());
  79. this.addOperatorButton(operator?.name);
  80. this.stateManager.assemblyModelSate.setOperator(x.asymId,operator?.name);
  81. operatorNameContainer.set(undefined);
  82. if(typeof this.additionalConfig?.operatorChangeCallback === "function" && this.stateManager.assemblyModelSate.getOperator()){
  83. this.additionalConfig.operatorChangeCallback(this.stateManager.assemblyModelSate.getOperator()!);
  84. }
  85. if((this.stateManager.assemblyModelSate.getChainInfo()?.operators?.length ?? 0) > 1)
  86. return {
  87. operatorIds: operator?.ids
  88. }
  89. },
  90. filterInstances: assemblyInstances.get(this.stateManager.assemblyModelSate.getString("entryId")),
  91. selectButtonOptionProps: (props: SelectOptionProps) => (
  92. <div style={{display: 'flex'}}>
  93. <ChainDisplayComponent stateManager={this.stateManager} label={props.data.label}/>
  94. {props.children}
  95. </div>
  96. )
  97. },
  98. {
  99. ...this.additionalConfig,
  100. boardConfig: this.boardConfigContainer.get(),
  101. externalTrackBuilder:{
  102. filterFeatures: this.filterFeatures.bind(this)
  103. }
  104. }
  105. );
  106. }
  107. return this.module;
  108. }
  109. private addOperatorButton(operatorName?: string): void{
  110. const currentChainInfo: ChainInfo|undefined = this.stateManager.assemblyModelSate.getChainInfo();
  111. if(this.useOperatorsFlag && currentChainInfo && currentChainInfo.operators.length >1 ){
  112. this.stateManager.assemblyModelSate.setOperator(undefined,operatorName);
  113. RcsbFvUI.addSelectButton(
  114. this.rcsbFvDivId,
  115. RcsbFvDOMConstants.SELECT_BUTTON_PFV_ID,
  116. currentChainInfo.operators.map(op=>({
  117. label:`${op.ids.join("-")} (${op.name})`,
  118. optId:op.name,
  119. onChange: async ()=>{
  120. this.module?.getFv()?.reset();
  121. this.stateManager.assemblyModelSate.set({operator:op});
  122. await this.create({
  123. defaultAuthId: this.stateManager.assemblyModelSate.getChainInfo()?.auth,
  124. defaultOperatorName: op.name
  125. })
  126. }
  127. })),
  128. {
  129. defaultValue: this.stateManager.assemblyModelSate.getOperator()?.name,
  130. dropdownTitle:this.OPERATOR_DROPDOWN_TITLE
  131. }
  132. );
  133. }else{
  134. RcsbFvUI.clearSelectButton(this.rcsbFvDivId,RcsbFvDOMConstants.SELECT_BUTTON_PFV_ID);
  135. }
  136. }
  137. private filterFeatures(data: {annotations: Array<AnnotationFeatures>; rcsbContext:Partial<PolymerEntityInstanceInterface>}): Promise<Array<AnnotationFeatures>> {
  138. return new Promise<Array<AnnotationFeatures>>(async resolve => {
  139. let annotations: Array<AnnotationFeatures> = [];
  140. (await Promise.all(data.annotations.map(async ann=>{
  141. if(ann.source == Source.PdbInterface && ann.target_id && data.rcsbContext?.asymId) {
  142. const interfaceToInstance: InterfaceInstanceTranslate = await RcsbRequestContextManager.getInterfaceToInstance(ann.target_id);
  143. if(typeof ann.target_identifiers?.interface_partner_index === "number" && ann.target_identifiers.assembly_id === this.stateManager.assemblyModelSate.getString("assemblyId") && Array.isArray(interfaceToInstance.getOperatorIds(ann.target_id))) {
  144. const operatorIds:string[][]|undefined = interfaceToInstance.getOperatorIds(ann.target_id)?.[ann.target_identifiers.interface_partner_index];
  145. if(ann.features && this.stateManager.assemblyModelSate.getOperator() && operatorIds?.map(o=>o.join("|")).includes( this.stateManager.assemblyModelSate.getOperator()!.ids.join("|") )){
  146. ann.features = ann.features.filter(f=>(f && f.type == FeatureType.BurialFraction));
  147. if(ann.features.length > 0)
  148. return ann;
  149. }
  150. }
  151. }else if(ann.source == Source.PdbInstance && ann.features){
  152. ann.features = ann.features?.filter(f=>(f?.type!==Type.Asa));
  153. return ann;
  154. }else if(ann.source != Source.PdbInterface){
  155. return ann;
  156. }
  157. }))).forEach((value,index,array)=>{
  158. if(value)
  159. annotations = annotations.concat(value);
  160. });
  161. resolve(annotations);
  162. });
  163. }
  164. }
  165. function getOperator(entryInfo: {entryId: string; assemblyId: string, chains:Array<ChainInfo>;}, defaultAuthId?: string, defaultOperatorName?:string): OperatorInfo | undefined{
  166. const chainInfo: ChainInfo | undefined = defaultAuthId ? entryInfo.chains.find(ch=>ch.auth === defaultAuthId) : entryInfo.chains[0];
  167. if(chainInfo){
  168. const operatorInfo: OperatorInfo | undefined = defaultOperatorName ? chainInfo.operators.find(op=>op.name === defaultOperatorName) : chainInfo.operators[0];
  169. if(operatorInfo)
  170. return operatorInfo;
  171. }
  172. return undefined;
  173. }