RcsbFvSelectorManager.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import {SaguaroChain, SaguaroRange, SaguaroRegionList, SaguaroSet} from "../RcsbFvStructure/StructureViewerInterface";
  2. export interface RegionSelectionInterface{
  3. begin:number;
  4. end:number;
  5. isEmpty?: boolean;
  6. source:'structure'|'sequence';
  7. }
  8. //TODO this class should be interfaced
  9. //TODO Check how lastSelection is used. It is not linked to selection. Only label asymId is used when the value is got
  10. export class RcsbFvSelectorManager {
  11. private lastSelection: SaguaroRegionList | null = null;
  12. private selection: Array<SaguaroRegionList> = new Array<SaguaroRegionList>();
  13. private hover: Array<SaguaroRegionList> = new Array<SaguaroRegionList>();
  14. public setSelectionFromRegion(modelId: string, labelAsymId: string, region: RegionSelectionInterface, mode:'select'|'hover', operatorName?: string): void {
  15. this.clearSelection(mode);
  16. this.addSelectionFromRegion(modelId, labelAsymId, region, mode, operatorName);
  17. }
  18. public addSelectionFromRegion(modelId: string, labelAsymId: string, region: RegionSelectionInterface, mode:'select'|'hover', operatorName?: string): void {
  19. if(mode === 'select'){
  20. this.selection.push({modelId:modelId, labelAsymId:labelAsymId, regions:[region], operatorName: operatorName});
  21. }else{
  22. this.hover.push({modelId:modelId, labelAsymId:labelAsymId, regions:[region], operatorName: operatorName});
  23. }
  24. }
  25. public setSelectionFromMultipleRegions(regions: {modelId: string, labelAsymId: string, region: RegionSelectionInterface, operatorName?: string}[], mode:'select'|'hover'): void {
  26. this.clearSelection(mode);
  27. this.addSelectionFromMultipleRegions(regions, mode);
  28. }
  29. public addSelectionFromMultipleRegions(regions: (SaguaroChain & {region: RegionSelectionInterface})[], mode:'select'|'hover'): void {
  30. regions.forEach(r=>{
  31. this.addSelectionFromRegion(r.modelId, r.labelAsymId, r.region, mode, r.operatorName);
  32. });
  33. }
  34. public setSelectionFromResidueSelection(res: Array<SaguaroSet>, mode:'select'|'hover', source: 'structure'|'sequence'): void {
  35. if(mode==='select'){
  36. this.selection = selectionFromResidueSelection(res, mode, source);
  37. }else{
  38. this.hover = selectionFromResidueSelection(res, mode, source);
  39. }
  40. }
  41. public getSelection(mode:'select'|'hover'): Array<SaguaroRegionList> {
  42. if(mode === 'select')
  43. return this.selection;
  44. else
  45. return this.hover;
  46. }
  47. public getLastSelection(mode:'select'|'hover'): SaguaroRegionList | null{
  48. return this.lastSelection;
  49. }
  50. public setLastSelection(mode:'select'|'hover', selection: SaguaroRegionList | null): void {
  51. this.lastSelection = selection;
  52. }
  53. public getSelectionWithCondition(modelId: string, labelAsymId: string, mode:'select'|'hover', operatorName?: string): SaguaroRegionList | undefined {
  54. const sel: Array<SaguaroRegionList> = mode === 'select' ?
  55. this.selection.filter(d=>(d.modelId===modelId && d.labelAsymId === labelAsymId && (d.operatorName === operatorName || !operatorName))) :
  56. this.hover.filter(d=>(d.modelId===modelId && d.labelAsymId === labelAsymId && (d.operatorName === operatorName || !operatorName)));
  57. if(sel.length > 0)
  58. return {modelId: sel[0].modelId, labelAsymId: sel[0].labelAsymId, operatorName: operatorName, regions:[].concat.apply([],sel.map(s=>s.regions))};
  59. }
  60. public clearSelection(mode:'select'|'hover', selection?:Partial<SaguaroChain>): void {
  61. if(!selection)
  62. if(mode === 'select')
  63. this.selection = new Array<SaguaroRegionList>();
  64. else
  65. this.hover = new Array<SaguaroRegionList>();
  66. else
  67. if(selection.labelAsymId || selection.modelId)
  68. if(mode === 'select')
  69. this.selection = this.selection.filter(r=>selectionFilter(r, selection));
  70. else
  71. this.hover = this.hover.filter(r=>selectionFilter(r, selection));
  72. }
  73. //TODO missing operatorName case
  74. public selectionSource(mode:'select'|'hover', region:SaguaroChain & SaguaroRange): 'structure'|'sequence'|undefined{
  75. if(mode === 'select')
  76. return this.selection
  77. .filter(r=>(r.modelId === region.modelId && r.labelAsymId === region.labelAsymId))[0]?.regions
  78. .filter(r=>(r.begin === region. begin && r.end === region.end))[0]?.source;
  79. else
  80. return this.hover
  81. .filter(r=>(r.modelId === region.modelId && r.labelAsymId === region.labelAsymId))[0]?.regions
  82. .filter(r=>(r.begin === region. begin && r.end === region.end))[0]?.source;
  83. }
  84. }
  85. function selectionFromResidueSelection(res: Array<SaguaroSet>, mode:'select'|'hover', source: 'structure'|'sequence'): Array<SaguaroRegionList> {
  86. const none:"none" = "none";
  87. const selMap: Map<string,Map<string,Map<string,Set<number>>>> = new Map<string, Map<string,Map<string,Set<number>>>>();
  88. res.forEach(r=>{
  89. if(!selMap.has(r.modelId))
  90. selMap.set(r.modelId,new Map<string, Map<string,Set<number>>>());
  91. if(!selMap.get(r.modelId)!.has(r.labelAsymId))
  92. selMap.get(r.modelId)!.set(r.labelAsymId, new Map<string,Set<number>>());
  93. if(r.operatorName && !selMap.get(r.modelId)!.get(r.labelAsymId)!.has(r.operatorName))
  94. selMap.get(r.modelId)!.get(r.labelAsymId)!.set(r.operatorName, new Set<number>());
  95. else
  96. selMap.get(r.modelId)!.get(r.labelAsymId)!.set(none, new Set<number>());
  97. r.seqIds.forEach(s=>{
  98. selMap.get(r.modelId)!.get(r.labelAsymId)!.get(r.operatorName ?? none)!.add(s);
  99. });
  100. });
  101. const selection = new Array<SaguaroRegionList>();
  102. selMap.forEach((labelMap, modelId)=>{
  103. labelMap.forEach((operatorMap,labelId)=>{
  104. operatorMap.forEach((seqSet, operatorId)=>{
  105. selection.push({
  106. modelId: modelId,
  107. labelAsymId: labelId,
  108. operatorName: operatorId!=none ? operatorId : undefined,
  109. regions: buildIntervals(seqSet, source)
  110. });
  111. });
  112. });
  113. });
  114. return selection;
  115. }
  116. function buildIntervals(ids: Set<number>, source: 'structure'|'sequence'): Array<RegionSelectionInterface>{
  117. const out: Array<RegionSelectionInterface> = new Array<RegionSelectionInterface>();
  118. const sorted: Array<number> = Array.from(ids).sort((a,b)=>(a-b));
  119. let begin: number = sorted.shift()!;
  120. let end: number = begin;
  121. for(const n of sorted){
  122. if(n==(end+1)){
  123. end = n;
  124. }else{
  125. out.push({begin:begin,end:end,source:source});
  126. begin = n;
  127. end = n;
  128. }
  129. }
  130. out.push({begin:begin,end:end,source:source});
  131. return out;
  132. }
  133. function selectionFilter(r:SaguaroRegionList, selection:Partial<SaguaroChain>): boolean{
  134. return (typeof selection.modelId === "string" && r.modelId != selection.modelId) ||
  135. (typeof selection.labelAsymId === "string" && r.labelAsymId != selection.labelAsymId) ||
  136. (typeof selection.operatorName === "string" && r.operatorName != selection.operatorName);
  137. }