Browse Source

Merge pull request #657 from molstar/fix-qa-assignment

Fix QualityAssessment assignment
David Sehnal 2 năm trước cách đây
mục cha
commit
02654ea57b

+ 1 - 0
CHANGELOG.md

@@ -14,6 +14,7 @@ Note that since we don't clearly distinguish between a public and private interf
     - Fix cylinder near-clipping
     - Add interior cylinder caps
     - Add per-pixel object clipping
+- Fix `QualityAssessment` assignment bug for structures with different auth vs label sequence numbering
 
 ## [v3.26.0] - 2022-12-04
 

+ 19 - 3
src/extensions/model-archive/quality-assessment/prop.ts

@@ -2,6 +2,7 @@
  * Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author David Sehnal <david.sehnal@gmail.com>
  */
 
 import { ParamDefinition as PD } from '../../../mol-util/param-definition';
@@ -14,6 +15,7 @@ import { CustomPropSymbol } from '../../../mol-script/language/symbol';
 import { Type } from '../../../mol-script/language/type';
 import { CustomPropertyDescriptor } from '../../../mol-model/custom-property';
 import { MmcifFormat } from '../../../mol-model-formats/structure/mmcif';
+import { AtomicIndex } from '../../../mol-model/structure/model/properties/atomic';
 
 export { QualityAssessment };
 
@@ -71,14 +73,28 @@ namespace QualityAssessment {
             localNames.set(ma_qa_metric.id.value(i), name);
         }
 
+        const residueKey: AtomicIndex.ResidueLabelKey = {
+            label_entity_id: '',
+            label_asym_id: '',
+            label_seq_id: 0,
+            pdbx_PDB_ins_code: undefined,
+        };
+
         for (let i = 0, il = ma_qa_metric_local._rowCount; i < il; i++) {
             if (model_id.value(i) !== model.modelNum) continue;
 
             const labelAsymId = label_asym_id.value(i);
             const entityIndex = index.findEntity(labelAsymId);
-            const rI = index.findResidue(model.entities.data.id.value(entityIndex), labelAsymId, label_seq_id.value(i));
-            const name = localNames.get(metric_id.value(i))!;
-            localMetrics.get(name)!.set(rI, metric_value.value(i));
+
+            residueKey.label_entity_id = model.entities.data.id.value(entityIndex);
+            residueKey.label_asym_id = labelAsymId;
+            residueKey.label_seq_id = label_seq_id.value(i);
+
+            const rI = index.findResidueLabel(residueKey);
+            if (rI >= 0) {
+                const name = localNames.get(metric_id.value(i))!;
+                localMetrics.get(name)!.set(rI, metric_value.value(i));
+            }
         }
 
         return {

+ 8 - 0
src/mol-model/structure/model/properties/atomic/hierarchy.ts

@@ -166,6 +166,14 @@ export interface AtomicIndex {
     findResidue(key: AtomicIndex.ResidueKey): ResidueIndex,
     findResidue(label_entity_id: string, label_asym_id: string, auth_seq_id: number, pdbx_PDB_ins_code?: string): ResidueIndex,
 
+
+    /**
+     * Index of the 1st occurence of this residue using "all-label" address.
+     * Doesn't work for "ligands" as they don't have a label seq id assigned.
+     * @returns index or -1 if not present.
+     */
+    findResidueLabel(key: AtomicIndex.ResidueLabelKey): ResidueIndex,
+
     /**
      * Index of the 1st occurence of this residue.
      * @param key.pdbx_PDB_ins_code Empty string for undefined

+ 8 - 0
src/mol-model/structure/model/properties/utils/atomic-index.ts

@@ -124,6 +124,14 @@ class Index implements AtomicIndex {
         return rm.has(id) ? rm.get(id)! : -1 as ResidueIndex;
     }
 
+    findResidueLabel(key: AtomicIndex.ResidueLabelKey): ResidueIndex {
+        const cI = this.findChainLabel(key);
+        if (cI < 0) return -1 as ResidueIndex;
+        const rm = this.map.chain_index_label_seq_id.get(cI)!;
+        const id = getResidueId(key.label_seq_id, key.pdbx_PDB_ins_code || '');
+        return rm.has(id) ? rm.get(id)! : -1 as ResidueIndex;
+    }
+
     findResidueAuth(key: AtomicIndex.ResidueAuthKey): ResidueIndex {
         const cI = this.findChainAuth(key);
         if (cI < 0) return -1 as ResidueIndex;