@datagrok/bio 2.26.0 → 2.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Bio changelog
2
2
 
3
+ ## 2.26.0 (2026-03-04)
4
+
5
+ * Antibodies support: Numbering schemes, highlighting, allignment, liabilities detection, extracting regions, and more.
6
+
3
7
  ## 2.25.15 (2026-02-26)
4
8
 
5
9
  * Monomer collections
package/dist/282.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";(self.webpackChunkbio=self.webpackChunkbio||[]).push([[282],{1282(e,t,a){a.d(t,{showNumberingSchemeDialog:()=>p});var n,i,o=a(4328),s=a(7389),l=a(6082),r=a(2003),g=a(4517);!function(e){e.IMGT="IMGT",e.Kabat="Kabat",e.Chothia="Chothia",e.AHo="AHo"}(n||(n={})),function(e){e.Heavy="Heavy",e.Light_Kappa="Light_Kappa",e.Light_Lambda="Light_Lambda"}(i||(i={}));i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda;n.IMGT,n.Kabat,n.Chothia,n.AHo;var h=a(3736);function p(){const e=o.shell.tv?.dataFrame;if(!e)return void o.shell.warning("No table open");const t=e.columns.bySemTypeAll(l.SEMTYPE.MACROMOLECULE);if(0===t.length)return void o.shell.warning("No macromolecule columns found");const i=function(){const e=[],t=l.Func.find({meta:{role:"antibodyNumbering"}});if(0===t.length)throw new Error("No external antibody numbering engines found. Make sure that Proteomics plugin is installed and up to date.");for(const a of t){const t=a.package?.name??"",n=a.friendlyName||a.name;e.push({label:n,key:t?`${t}:${a.name}`:a.name,func:a})}return e.push({label:"Built-in (TypeScript)",key:"__builtin__",func:null}),e}(),p=i.map(e=>e.label),m=Object.values(n),L=s.input.table("Table",{value:e}),d=s.input.column("Sequence",{table:e,value:t[0],filter:e=>e.semType===l.SEMTYPE.MACROMOLECULE}),f=s.input.choice("Scheme",{value:n.IMGT,items:m}),_=s.input.choice("Engine",{value:p[0],items:p}),b=s.dialog({title:"Apply Antibody Numbering"}).add(s.inputs([L,d,f,_])).onOK(async()=>{const t=d.value,n=f.value,s=_.value,p=i.find(e=>e.label===s)??i[i.length-1],m=l.TaskBarProgressIndicator.create(`Applying ${n} numbering...`);try{let i;i=p.func?await p.func.apply({df:e,seqCol:t,scheme:n.toLowerCase()}):await async function(e,t){const{numberSequences:n,extractSequence:i}=await a.e(767).then(a.bind(a,6767)),o=t.toLowerCase(),s=[];for(let t=0;t<e.length;t++){const a=e.get(t);s.push(i(a??""))}return function(e){const t=e.length,a=l.Column.fromType(l.COLUMN_TYPE.STRING,"position_names",t),n=l.Column.fromType(l.COLUMN_TYPE.STRING,"chain_type",t),i=l.Column.fromType(l.COLUMN_TYPE.STRING,"annotations_json",t),o=l.Column.fromType(l.COLUMN_TYPE.STRING,"numbering_detail",t),s=l.Column.fromType(l.COLUMN_TYPE.STRING,"numbering_map",t);for(let l=0;l<t;l++){const t=e[l];t.error&&t.percentIdentity<.3?(a.set(l,""),n.set(l,""),i.set(l,"[]"),o.set(l,""),s.set(l,"")):(a.set(l,t.positionNames),n.set(l,t.chainType),i.set(l,JSON.stringify(t.annotations)),o.set(l,JSON.stringify(t.numberingDetail)),s.set(l,JSON.stringify(t.numberingMap)))}return l.DataFrame.fromColumns([a,n,i,o,s])}(n(s,o))}(t,n),function(e,t,a,n,i,s){if(!a||0===a.rowCount)return void o.shell.warning("No numbering results returned");const p=a.getCol("position_names"),m=a.getCol("chain_type"),L=a.getCol("annotations_json"),d=a.col("numbering_map");if(d)for(let e=0;e<a.rowCount;e++){const a=d.get(e);if(a)try{const n=JSON.parse(a),i=c(t.get(e)??""),o={};for(const[e,t]of Object.entries(n))t<i.length&&(o[e]=i[t]);d.set(e,JSON.stringify(o))}catch{}}let f=-1,_=-1;for(let e=0;e<a.rowCount;e++){const t=p.get(e);if(!t||0===t.length)continue;const a=L.get(e);let n=0;if(a)try{n=JSON.parse(a).length}catch{}n>_&&(_=n,f=e)}const b=f>=0?m.get(f)??"":"",y=f>=0?L.get(f)??"[]":"[]";if(f<0)return void o.shell.warning(`${s} could not number the sequences. Check that they are valid antibody variable region sequences.`);t.setTag(r.gp.numberingScheme,n);try{const e=JSON.parse(y),a=(0,h.Ln)(t).filter(e=>e.category!==g.eI.Structure);(0,h.fh)(t,[...a,...e])}catch(e){console.warn("Failed to set annotation definitions on original column:",e)}if(d)try{const n=(0,h.Lz)(e,t);for(let e=0;e<a.rowCount;e++){const t=d.get(e),a=L.get(e);if(!t||!a)continue;const i=JSON.parse(t),o=JSON.parse(a),s=[];for(const e of o){if(null==e.start||null==e.end)continue;const t=i[e.start],a=i[e.end];null!=t&&null!=a&&s.push({annotationId:e.id,positionIndex:t,endPositionIndex:a,positionName:e.start,matchedMonomers:""})}const l=(0,h.JG)(n,e)??[];(0,h.z5)(n,e,(0,h.bq)(l,s,!0,!1))}}catch(e){console.warn("Failed to store per-row region data on original column:",e)}const v=function(e,t,a){const n=a.col("numbering_map");if(!n)return null;const i=new Set,o=[],s=[],g=[];for(let e=0;e<a.rowCount;e++){const a=n.get(e),l=t.get(e)??"";if(a)try{const e=JSON.parse(a);o.push(e);for(const t of Object.keys(e))i.add(t);const t=Object.values(e),n=Math.min(...t),r=Math.max(...t);s.push(n),g.push(Math.max(0,l.length-r-1))}catch{o.push(null),s.push(0),g.push(0)}else o.push(null),s.push(0),g.push(0)}if(0===i.size)return null;const h=Math.max(0,...s),p=Math.max(0,...g),c=Array.from(i).slice().sort((e,t)=>{const[a,n]=u(e),[i,o]=u(t);return a!==i?a-i:n.localeCompare(o)}),m=[];for(let e=h;e>0;e--)m.push(`N-${e}`);const L=[];for(let e=1;e<=p;e++)L.push(`C+${e}`);const d=[...m,...c,...L],f=d.length,_=h,b=new Map;for(let e=0;e<c.length;e++)b.set(c[e],_+e);const y=e.columns.getUnusedName(`${t.name} (aligned)`),v=l.Column.fromType(l.COLUMN_TYPE.STRING,y,e.rowCount);for(let a=0;a<e.rowCount;a++){const e=a<o.length?o[a]:null,n=t.get(a)??"";if(!e){v.set(a,"-".repeat(f));continue}const i=new Array(f).fill("-");for(const[t,a]of Object.entries(e)){const e=b.get(t);null!=e&&a<n.length&&(i[e]=n[a])}const l=s[a],r=Object.values(e),h=Math.min(...r);for(let e=0;e<l;e++)i[_-l+e]=n[h-l+e];const p=g[a],u=Math.max(...r),m=_+c.length;for(let e=0;e<p;e++)i[m+e]=n[u+1+e];v.set(a,i.join(""))}return v.semType=l.SEMTYPE.MACROMOLECULE,v.setTag(r.gp.aligned,"SEQ.MSA"),v.setTag(r.gp.alphabet,r.YI.PT),v.meta.units=r.Hi.FASTA,v.setTag(l.Tags.CellRenderer,"sequence"),v.setTag(r.gp.positionNames,d.join(", ")),{alignedCol:v,unifiedPositions:d,preOffset:_}}(e,t,a);if(v&&(e.columns.insert(v.alignedCol,e.columns.toList().indexOf(t)+1),o.shell.tv?.dataFrame===e&&o.shell.tv.grid.scrollToCell(t,0),v.alignedCol.setTag(r.gp.numberingScheme,n),i))try{const e=JSON.parse(y),t=(0,h.Ln)(v.alignedCol).filter(e=>e.category!==g.eI.Structure);(0,h.fh)(v.alignedCol,[...t,...e])}catch(e){console.warn("Failed to set column-level annotations on aligned column:",e)}e.fireValuesChanged(),o.shell.info(`Numbering applied: ${n}, chain type: ${b}`)}(e,t,i,n,!0,p.label)}catch(e){o.shell.error(`Numbering failed: ${e.message??e}`),console.error(e)}finally{m.close()}});b.show()}function c(e){const t=[];for(let a=0;a<e.length;a++)"-"!==e[a]&&"."!==e[a]&&t.push(a);return t}function u(e){const t=e.match(/^(\d+)([A-Z]?)$/);return t?[parseInt(t[1],10),t[2]]:[1/0,e]}}}]);
1
+ "use strict";(self.webpackChunkbio=self.webpackChunkbio||[]).push([[282],{1282(e,t,a){a.d(t,{showNumberingSchemeDialog:()=>p});var n,i,o=a(4328),s=a(7389),l=a(6082),r=a(2003),g=a(4517);!function(e){e.IMGT="IMGT",e.Kabat="Kabat",e.Chothia="Chothia",e.AHo="AHo"}(n||(n={})),function(e){e.Heavy="Heavy",e.Light_Kappa="Light_Kappa",e.Light_Lambda="Light_Lambda"}(i||(i={}));i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Heavy,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Kappa,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda,i.Light_Lambda;n.IMGT,n.Kabat,n.Chothia,n.AHo;var h=a(3736);function p(){const e=o.shell.tv?.dataFrame;if(!e)return void o.shell.warning("No table open");const t=e.columns.bySemTypeAll(l.SEMTYPE.MACROMOLECULE);if(0===t.length)return void o.shell.warning("No macromolecule columns found");const i=function(){const e=[],t=l.Func.find({meta:{role:"antibodyNumbering"}});if(0===t.length)throw o.shell.error("No antibody numbering engines found. Make sure that Proteomics plugin is installed and up to date."),new Error("No external antibody numbering engines found. Make sure that Proteomics plugin is installed and up to date.");for(const a of t){const t=a.package?.name??"",n=a.friendlyName||a.name;e.push({label:n,key:t?`${t}:${a.name}`:a.name,func:a})}return e.push({label:"Built-in (TypeScript)",key:"__builtin__",func:null}),e}(),p=i.map(e=>e.label),m=Object.values(n),L=s.input.table("Table",{value:e}),d=s.input.column("Sequence",{table:e,value:t[0],filter:e=>e.semType===l.SEMTYPE.MACROMOLECULE}),f=s.input.choice("Scheme",{value:n.IMGT,items:m}),_=s.input.choice("Engine",{value:p[0],items:p}),b=s.dialog({title:"Apply Antibody Numbering"}).add(s.inputs([L,d,f,_])).onOK(async()=>{const t=d.value,n=f.value,s=_.value,p=i.find(e=>e.label===s)??i[i.length-1],m=l.TaskBarProgressIndicator.create(`Applying ${n} numbering...`);try{let i;i=p.func?await p.func.apply({df:e,seqCol:t,scheme:n.toLowerCase()}):await async function(e,t){const{numberSequences:n,extractSequence:i}=await a.e(767).then(a.bind(a,6767)),o=t.toLowerCase(),s=[];for(let t=0;t<e.length;t++){const a=e.get(t);s.push(i(a??""))}return function(e){const t=e.length,a=l.Column.fromType(l.COLUMN_TYPE.STRING,"position_names",t),n=l.Column.fromType(l.COLUMN_TYPE.STRING,"chain_type",t),i=l.Column.fromType(l.COLUMN_TYPE.STRING,"annotations_json",t),o=l.Column.fromType(l.COLUMN_TYPE.STRING,"numbering_detail",t),s=l.Column.fromType(l.COLUMN_TYPE.STRING,"numbering_map",t);for(let l=0;l<t;l++){const t=e[l];t.error&&t.percentIdentity<.3?(a.set(l,""),n.set(l,""),i.set(l,"[]"),o.set(l,""),s.set(l,"")):(a.set(l,t.positionNames),n.set(l,t.chainType),i.set(l,JSON.stringify(t.annotations)),o.set(l,JSON.stringify(t.numberingDetail)),s.set(l,JSON.stringify(t.numberingMap)))}return l.DataFrame.fromColumns([a,n,i,o,s])}(n(s,o))}(t,n),function(e,t,a,n,i,s){if(!a||0===a.rowCount)return void o.shell.warning("No numbering results returned");const p=a.getCol("position_names"),m=a.getCol("chain_type"),L=a.getCol("annotations_json"),d=a.col("numbering_map");if(d)for(let e=0;e<a.rowCount;e++){const a=d.get(e);if(a)try{const n=JSON.parse(a),i=u(t.get(e)??""),o={};for(const[e,t]of Object.entries(n))t<i.length&&(o[e]=i[t]);d.set(e,JSON.stringify(o))}catch{}}let f=-1,_=-1;for(let e=0;e<a.rowCount;e++){const t=p.get(e);if(!t||0===t.length)continue;const a=L.get(e);let n=0;if(a)try{n=JSON.parse(a).length}catch{}n>_&&(_=n,f=e)}const b=f>=0?m.get(f)??"":"",y=f>=0?L.get(f)??"[]":"[]";if(f<0)return void o.shell.warning(`${s} could not number the sequences. Check that they are valid antibody variable region sequences.`);t.setTag(r.gp.numberingScheme,n);try{const e=JSON.parse(y),a=(0,h.Ln)(t).filter(e=>e.category!==g.eI.Structure);(0,h.fh)(t,[...a,...e])}catch(e){console.warn("Failed to set annotation definitions on original column:",e)}if(d)try{const n=(0,h.Lz)(e,t);for(let e=0;e<a.rowCount;e++){const t=d.get(e),a=L.get(e);if(!t||!a)continue;const i=JSON.parse(t),o=JSON.parse(a),s=[];for(const e of o){if(null==e.start||null==e.end)continue;const t=i[e.start],a=i[e.end];null!=t&&null!=a&&s.push({annotationId:e.id,positionIndex:t,endPositionIndex:a,positionName:e.start,matchedMonomers:""})}const l=(0,h.JG)(n,e)??[];(0,h.z5)(n,e,(0,h.bq)(l,s,!0,!1))}}catch(e){console.warn("Failed to store per-row region data on original column:",e)}const v=function(e,t,a){const n=a.col("numbering_map");if(!n)return null;const i=new Set,o=[],s=[],g=[];for(let e=0;e<a.rowCount;e++){const a=n.get(e),l=t.get(e)??"";if(a)try{const e=JSON.parse(a);o.push(e);for(const t of Object.keys(e))i.add(t);const t=Object.values(e),n=Math.min(...t),r=Math.max(...t);s.push(n),g.push(Math.max(0,l.length-r-1))}catch{o.push(null),s.push(0),g.push(0)}else o.push(null),s.push(0),g.push(0)}if(0===i.size)return null;const h=Math.max(0,...s),p=Math.max(0,...g),u=Array.from(i).slice().sort((e,t)=>{const[a,n]=c(e),[i,o]=c(t);return a!==i?a-i:n.localeCompare(o)}),m=[];for(let e=h;e>0;e--)m.push(`N-${e}`);const L=[];for(let e=1;e<=p;e++)L.push(`C+${e}`);const d=[...m,...u,...L],f=d.length,_=h,b=new Map;for(let e=0;e<u.length;e++)b.set(u[e],_+e);const y=e.columns.getUnusedName(`${t.name} (aligned)`),v=l.Column.fromType(l.COLUMN_TYPE.STRING,y,e.rowCount);for(let a=0;a<e.rowCount;a++){const e=a<o.length?o[a]:null,n=t.get(a)??"";if(!e){v.set(a,"-".repeat(f));continue}const i=new Array(f).fill("-");for(const[t,a]of Object.entries(e)){const e=b.get(t);null!=e&&a<n.length&&(i[e]=n[a])}const l=s[a],r=Object.values(e),h=Math.min(...r);for(let e=0;e<l;e++)i[_-l+e]=n[h-l+e];const p=g[a],c=Math.max(...r),m=_+u.length;for(let e=0;e<p;e++)i[m+e]=n[c+1+e];v.set(a,i.join(""))}return v.semType=l.SEMTYPE.MACROMOLECULE,v.setTag(r.gp.aligned,"SEQ.MSA"),v.setTag(r.gp.alphabet,r.YI.PT),v.meta.units=r.Hi.FASTA,v.setTag(l.Tags.CellRenderer,"sequence"),v.setTag(r.gp.positionNames,d.join(", ")),{alignedCol:v,unifiedPositions:d,preOffset:_}}(e,t,a);if(v&&(e.columns.insert(v.alignedCol,e.columns.toList().indexOf(t)+1),o.shell.tv?.dataFrame===e&&o.shell.tv.grid.scrollToCell(t,0),v.alignedCol.setTag(r.gp.numberingScheme,n),i))try{const e=JSON.parse(y),t=(0,h.Ln)(v.alignedCol).filter(e=>e.category!==g.eI.Structure);(0,h.fh)(v.alignedCol,[...t,...e])}catch(e){console.warn("Failed to set column-level annotations on aligned column:",e)}e.fireValuesChanged(),o.shell.info(`Numbering applied: ${n}, chain type: ${b}`)}(e,t,i,n,!0,p.label)}catch(e){o.shell.error(`Numbering failed: ${e.message??e}`),console.error(e)}finally{m.close()}});b.show()}function u(e){const t=[];for(let a=0;a<e.length;a++)"-"!==e[a]&&"."!==e[a]&&t.push(a);return t}function c(e){const t=e.match(/^(\d+)([A-Z]?)$/);return t?[parseInt(t[1],10),t[2]]:[1/0,e]}}}]);
2
2
  //# sourceMappingURL=282.js.map
package/dist/282.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"282.js","mappings":"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","sources":["webpack://bio/./node_modules/@datagrok-libraries/bio/src/utils/macromolecule/numbering-schemes.js","webpack://bio/./src/utils/annotations/numbering-ui.ts"],"sourcesContent":["/** Static antibody numbering scheme region definitions.\n *\n * Contains FR/CDR boundaries for IMGT, Kabat, Chothia, and AHo schemes.\n * These are the canonical position ranges used after a numbering tool\n * (e.g. ANARCI) has assigned scheme-specific position names.\n */\nexport var NumberingScheme;\n(function (NumberingScheme) {\n NumberingScheme[\"IMGT\"] = \"IMGT\";\n NumberingScheme[\"Kabat\"] = \"Kabat\";\n NumberingScheme[\"Chothia\"] = \"Chothia\";\n NumberingScheme[\"AHo\"] = \"AHo\";\n})(NumberingScheme || (NumberingScheme = {}));\nexport var ChainType;\n(function (ChainType) {\n ChainType[\"Heavy\"] = \"Heavy\";\n ChainType[\"Light_Kappa\"] = \"Light_Kappa\";\n ChainType[\"Light_Lambda\"] = \"Light_Lambda\";\n})(ChainType || (ChainType = {}));\n/** IMGT region boundaries — the reference numbering scheme.\n * @see https://www.imgt.org/IMGTScientificChart/Numbering/IMGTIGVLsuperfamily.html\n */\nexport const IMGT_REGIONS = {\n [ChainType.Heavy]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '26', chainType: ChainType.Heavy },\n { name: 'CDR1', type: 'CDR', startPosition: '27', endPosition: '38', chainType: ChainType.Heavy },\n { name: 'FR2', type: 'FR', startPosition: '39', endPosition: '55', chainType: ChainType.Heavy },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '65', chainType: ChainType.Heavy },\n { name: 'FR3', type: 'FR', startPosition: '66', endPosition: '104', chainType: ChainType.Heavy },\n { name: 'CDR3', type: 'CDR', startPosition: '105', endPosition: '117', chainType: ChainType.Heavy },\n { name: 'FR4', type: 'FR', startPosition: '118', endPosition: '128', chainType: ChainType.Heavy },\n ],\n [ChainType.Light_Kappa]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '26', chainType: ChainType.Light_Kappa },\n { name: 'CDR1', type: 'CDR', startPosition: '27', endPosition: '38', chainType: ChainType.Light_Kappa },\n { name: 'FR2', type: 'FR', startPosition: '39', endPosition: '55', chainType: ChainType.Light_Kappa },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '65', chainType: ChainType.Light_Kappa },\n { name: 'FR3', type: 'FR', startPosition: '66', endPosition: '104', chainType: ChainType.Light_Kappa },\n { name: 'CDR3', type: 'CDR', startPosition: '105', endPosition: '117', chainType: ChainType.Light_Kappa },\n { name: 'FR4', type: 'FR', startPosition: '118', endPosition: '127', chainType: ChainType.Light_Kappa },\n ],\n [ChainType.Light_Lambda]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '26', chainType: ChainType.Light_Lambda },\n { name: 'CDR1', type: 'CDR', startPosition: '27', endPosition: '38', chainType: ChainType.Light_Lambda },\n { name: 'FR2', type: 'FR', startPosition: '39', endPosition: '55', chainType: ChainType.Light_Lambda },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '65', chainType: ChainType.Light_Lambda },\n { name: 'FR3', type: 'FR', startPosition: '66', endPosition: '104', chainType: ChainType.Light_Lambda },\n { name: 'CDR3', type: 'CDR', startPosition: '105', endPosition: '117', chainType: ChainType.Light_Lambda },\n { name: 'FR4', type: 'FR', startPosition: '118', endPosition: '127', chainType: ChainType.Light_Lambda },\n ],\n};\n/** Kabat region boundaries (differ mainly in CDR definitions). */\nexport const KABAT_REGIONS = {\n [ChainType.Heavy]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '30', chainType: ChainType.Heavy },\n { name: 'CDR1', type: 'CDR', startPosition: '31', endPosition: '35', chainType: ChainType.Heavy },\n { name: 'FR2', type: 'FR', startPosition: '36', endPosition: '49', chainType: ChainType.Heavy },\n { name: 'CDR2', type: 'CDR', startPosition: '50', endPosition: '65', chainType: ChainType.Heavy },\n { name: 'FR3', type: 'FR', startPosition: '66', endPosition: '94', chainType: ChainType.Heavy },\n { name: 'CDR3', type: 'CDR', startPosition: '95', endPosition: '102', chainType: ChainType.Heavy },\n { name: 'FR4', type: 'FR', startPosition: '103', endPosition: '113', chainType: ChainType.Heavy },\n ],\n [ChainType.Light_Kappa]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '23', chainType: ChainType.Light_Kappa },\n { name: 'CDR1', type: 'CDR', startPosition: '24', endPosition: '34', chainType: ChainType.Light_Kappa },\n { name: 'FR2', type: 'FR', startPosition: '35', endPosition: '49', chainType: ChainType.Light_Kappa },\n { name: 'CDR2', type: 'CDR', startPosition: '50', endPosition: '56', chainType: ChainType.Light_Kappa },\n { name: 'FR3', type: 'FR', startPosition: '57', endPosition: '88', chainType: ChainType.Light_Kappa },\n { name: 'CDR3', type: 'CDR', startPosition: '89', endPosition: '97', chainType: ChainType.Light_Kappa },\n { name: 'FR4', type: 'FR', startPosition: '98', endPosition: '107', chainType: ChainType.Light_Kappa },\n ],\n [ChainType.Light_Lambda]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '23', chainType: ChainType.Light_Lambda },\n { name: 'CDR1', type: 'CDR', startPosition: '24', endPosition: '34', chainType: ChainType.Light_Lambda },\n { name: 'FR2', type: 'FR', startPosition: '35', endPosition: '49', chainType: ChainType.Light_Lambda },\n { name: 'CDR2', type: 'CDR', startPosition: '50', endPosition: '56', chainType: ChainType.Light_Lambda },\n { name: 'FR3', type: 'FR', startPosition: '57', endPosition: '88', chainType: ChainType.Light_Lambda },\n { name: 'CDR3', type: 'CDR', startPosition: '89', endPosition: '97', chainType: ChainType.Light_Lambda },\n { name: 'FR4', type: 'FR', startPosition: '98', endPosition: '107', chainType: ChainType.Light_Lambda },\n ],\n};\n/** Chothia region boundaries. */\nexport const CHOTHIA_REGIONS = {\n [ChainType.Heavy]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '25', chainType: ChainType.Heavy },\n { name: 'CDR1', type: 'CDR', startPosition: '26', endPosition: '32', chainType: ChainType.Heavy },\n { name: 'FR2', type: 'FR', startPosition: '33', endPosition: '51', chainType: ChainType.Heavy },\n { name: 'CDR2', type: 'CDR', startPosition: '52', endPosition: '56', chainType: ChainType.Heavy },\n { name: 'FR3', type: 'FR', startPosition: '57', endPosition: '94', chainType: ChainType.Heavy },\n { name: 'CDR3', type: 'CDR', startPosition: '95', endPosition: '102', chainType: ChainType.Heavy },\n { name: 'FR4', type: 'FR', startPosition: '103', endPosition: '113', chainType: ChainType.Heavy },\n ],\n [ChainType.Light_Kappa]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '25', chainType: ChainType.Light_Kappa },\n { name: 'CDR1', type: 'CDR', startPosition: '26', endPosition: '32', chainType: ChainType.Light_Kappa },\n { name: 'FR2', type: 'FR', startPosition: '33', endPosition: '49', chainType: ChainType.Light_Kappa },\n { name: 'CDR2', type: 'CDR', startPosition: '50', endPosition: '52', chainType: ChainType.Light_Kappa },\n { name: 'FR3', type: 'FR', startPosition: '53', endPosition: '90', chainType: ChainType.Light_Kappa },\n { name: 'CDR3', type: 'CDR', startPosition: '91', endPosition: '96', chainType: ChainType.Light_Kappa },\n { name: 'FR4', type: 'FR', startPosition: '97', endPosition: '107', chainType: ChainType.Light_Kappa },\n ],\n [ChainType.Light_Lambda]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '25', chainType: ChainType.Light_Lambda },\n { name: 'CDR1', type: 'CDR', startPosition: '26', endPosition: '32', chainType: ChainType.Light_Lambda },\n { name: 'FR2', type: 'FR', startPosition: '33', endPosition: '49', chainType: ChainType.Light_Lambda },\n { name: 'CDR2', type: 'CDR', startPosition: '50', endPosition: '52', chainType: ChainType.Light_Lambda },\n { name: 'FR3', type: 'FR', startPosition: '53', endPosition: '90', chainType: ChainType.Light_Lambda },\n { name: 'CDR3', type: 'CDR', startPosition: '91', endPosition: '96', chainType: ChainType.Light_Lambda },\n { name: 'FR4', type: 'FR', startPosition: '97', endPosition: '107', chainType: ChainType.Light_Lambda },\n ],\n};\n/** AHo region boundaries. */\nexport const AHO_REGIONS = {\n [ChainType.Heavy]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '24', chainType: ChainType.Heavy },\n { name: 'CDR1', type: 'CDR', startPosition: '25', endPosition: '40', chainType: ChainType.Heavy },\n { name: 'FR2', type: 'FR', startPosition: '41', endPosition: '55', chainType: ChainType.Heavy },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '78', chainType: ChainType.Heavy },\n { name: 'FR3', type: 'FR', startPosition: '79', endPosition: '108', chainType: ChainType.Heavy },\n { name: 'CDR3', type: 'CDR', startPosition: '109', endPosition: '138', chainType: ChainType.Heavy },\n { name: 'FR4', type: 'FR', startPosition: '139', endPosition: '149', chainType: ChainType.Heavy },\n ],\n [ChainType.Light_Kappa]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '24', chainType: ChainType.Light_Kappa },\n { name: 'CDR1', type: 'CDR', startPosition: '25', endPosition: '40', chainType: ChainType.Light_Kappa },\n { name: 'FR2', type: 'FR', startPosition: '41', endPosition: '55', chainType: ChainType.Light_Kappa },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '78', chainType: ChainType.Light_Kappa },\n { name: 'FR3', type: 'FR', startPosition: '79', endPosition: '108', chainType: ChainType.Light_Kappa },\n { name: 'CDR3', type: 'CDR', startPosition: '109', endPosition: '138', chainType: ChainType.Light_Kappa },\n { name: 'FR4', type: 'FR', startPosition: '139', endPosition: '149', chainType: ChainType.Light_Kappa },\n ],\n [ChainType.Light_Lambda]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '24', chainType: ChainType.Light_Lambda },\n { name: 'CDR1', type: 'CDR', startPosition: '25', endPosition: '40', chainType: ChainType.Light_Lambda },\n { name: 'FR2', type: 'FR', startPosition: '41', endPosition: '55', chainType: ChainType.Light_Lambda },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '78', chainType: ChainType.Light_Lambda },\n { name: 'FR3', type: 'FR', startPosition: '79', endPosition: '108', chainType: ChainType.Light_Lambda },\n { name: 'CDR3', type: 'CDR', startPosition: '109', endPosition: '138', chainType: ChainType.Light_Lambda },\n { name: 'FR4', type: 'FR', startPosition: '139', endPosition: '149', chainType: ChainType.Light_Lambda },\n ],\n};\n/** Lookup table: scheme → chain type → region defs */\nexport const SCHEME_REGIONS = {\n [NumberingScheme.IMGT]: IMGT_REGIONS,\n [NumberingScheme.Kabat]: KABAT_REGIONS,\n [NumberingScheme.Chothia]: CHOTHIA_REGIONS,\n [NumberingScheme.AHo]: AHO_REGIONS,\n};\n//# sourceMappingURL=numbering-schemes.js.map","/* eslint-disable max-len */\nimport * as grok from 'datagrok-api/grok';\nimport * as ui from 'datagrok-api/ui';\nimport * as DG from 'datagrok-api/dg';\n\nimport {TAGS as bioTAGS, ALIGNMENT, ALPHABET, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';\nimport {\n SeqAnnotation, SeqAnnotationHit, AnnotationCategory,\n} from '@datagrok-libraries/bio/src/utils/macromolecule/annotations';\nimport {NumberingScheme} from '@datagrok-libraries/bio/src/utils/macromolecule/numbering-schemes';\nimport {\n setColumnAnnotations, getColumnAnnotations,\n getOrCreateAnnotationColumn, getRowAnnotations, setRowAnnotations, mergeRowHits,\n} from './annotation-manager';\nimport {_package} from '../../package';\nimport type {NumberingResult, Scheme} from '../antibody-numbering (WIP)';\n\nconst BUILTIN_ENGINE_KEY = '__builtin__';\nconst BUILTIN_ENGINE_LABEL = 'Built-in (TypeScript)';\n\n/** An engine entry: either a dynamically discovered DG.Func or the built-in TS engine. */\ninterface NumberingEngine {\n /** Display label for the dropdown */\n label: string;\n /** Unique key — nqName for DG.Func engines, BUILTIN_ENGINE_KEY for built-in */\n key: string;\n /** The DG.Func to call, or null for the built-in engine */\n func: DG.Func | null;\n}\n\n/** Discovers all registered antibody numbering engines + the built-in TS engine.\n * Dynamic engines (meta.role = 'antibodyNumbering') come first; built-in is last. */\nfunction discoverEngines(): NumberingEngine[] {\n const engines: NumberingEngine[] = [];\n\n const funcs = DG.Func.find({meta: {role: 'antibodyNumbering'}});\n if (funcs.length === 0)\n throw new Error('No external antibody numbering engines found. Make sure that Proteomics plugin is installed and up to date.');\n for (const f of funcs) {\n const pkgName = f.package?.name ?? '';\n const label = f.friendlyName || f.name;\n engines.push({\n label: label,\n key: pkgName ? `${pkgName}:${f.name}` : f.name,\n func: f,\n });\n }\n\n // Built-in TS engine is always last\n engines.push({label: BUILTIN_ENGINE_LABEL, key: BUILTIN_ENGINE_KEY, func: null});\n return engines;\n}\n\n/** Converts TS NumberingResult[] to a DG.DataFrame matching the expected output shape.\n * Columns: position_names, chain_type, annotations_json, numbering_detail, numbering_map. */\nexport function numberingResultsToDataFrame(results: NumberingResult[]): DG.DataFrame {\n const n = results.length;\n const posNames = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'position_names', n);\n const chainTypes = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'chain_type', n);\n const annotJson = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'annotations_json', n);\n const numDetail = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'numbering_detail', n);\n const numMap = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'numbering_map', n);\n\n for (let i = 0; i < n; i++) {\n const r = results[i];\n if (r.error && r.percentIdentity < 0.3) {\n posNames.set(i, '');\n chainTypes.set(i, '');\n annotJson.set(i, '[]');\n numDetail.set(i, '');\n numMap.set(i, '');\n } else {\n posNames.set(i, r.positionNames);\n chainTypes.set(i, r.chainType);\n annotJson.set(i, JSON.stringify(r.annotations));\n numDetail.set(i, JSON.stringify(r.numberingDetail));\n numMap.set(i, JSON.stringify(r.numberingMap));\n }\n }\n\n return DG.DataFrame.fromColumns([posNames, chainTypes, annotJson, numDetail, numMap]);\n}\n\n/** Runs the built-in TS numbering engine on all rows of a sequence column. */\nasync function runBuiltinNumbering(\n seqCol: DG.Column<string>, schemeName: string,\n): Promise<DG.DataFrame> {\n const {numberSequences, extractSequence} = await import('../antibody-numbering (WIP)');\n const scheme = schemeName.toLowerCase() as Scheme;\n\n const sequences: string[] = [];\n for (let i = 0; i < seqCol.length; i++) {\n const raw = seqCol.get(i);\n sequences.push(extractSequence(raw ?? ''));\n }\n\n const results = numberSequences(sequences, scheme);\n return numberingResultsToDataFrame(results);\n}\n\nexport function showNumberingSchemeDialog(): void {\n const df = grok.shell.tv?.dataFrame;\n if (!df) {\n grok.shell.warning('No table open');\n return;\n }\n\n const seqCols = df.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);\n if (seqCols.length === 0) {\n grok.shell.warning('No macromolecule columns found');\n return;\n }\n\n const engines = discoverEngines();\n const engineLabels = engines.map((e) => e.label);\n const schemeChoices = Object.values(NumberingScheme);\n\n const tableInput = ui.input.table('Table', {value: df});\n const seqInput = ui.input.column('Sequence', {\n table: df, value: seqCols[0],\n filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE,\n });\n const schemeInput = ui.input.choice('Scheme', {value: NumberingScheme.IMGT, items: schemeChoices});\n const engineInput = ui.input.choice('Engine', {\n value: engineLabels[0], items: engineLabels,\n });\n // const populateRegions = ui.input.bool('Populate FR/CDR regions', {value: true});\n // const openVdRegions = ui.input.bool('Open VD Regions viewer', {value: true});\n\n const dialog = ui.dialog({title: 'Apply Antibody Numbering'})\n .add(ui.inputs([tableInput, seqInput, schemeInput, engineInput]))\n .onOK(async () => {\n const seqCol = seqInput.value!;\n const schemeName = schemeInput.value!;\n const selectedLabel = engineInput.value!;\n const engine = engines.find((e) => e.label === selectedLabel) ?? engines[engines.length - 1];\n const pi = DG.TaskBarProgressIndicator.create(`Applying ${schemeName} numbering...`);\n try {\n let result: DG.DataFrame;\n if (engine.func)\n result = await engine.func.apply({df: df, seqCol: seqCol, scheme: schemeName.toLowerCase()});\n else\n result = await runBuiltinNumbering(seqCol, schemeName);\n\n applyNumberingResults(df, seqCol, result, schemeName, true, engine.label);\n\n // // Open VD Regions viewer\n // if (openVdRegions.value && grok.shell.tv) {\n // try {\n // await grok.shell.tv.dataFrame.plot.fromType('VdRegions', {});\n // } catch (err) {\n // console.warn('Could not open VD Regions viewer:', err);\n // }\n // }\n } catch (err: any) {\n grok.shell.error(`Numbering failed: ${err.message ?? err}`);\n console.error(err);\n } finally {\n pi.close();\n }\n });\n\n dialog.show();\n}\n\n/** Builds a map from ungapped character index to gapped character index.\n * Used when the source column is already aligned (MSA) — numbering engines strip gaps,\n * so their output indices refer to the ungapped sequence, not the gapped original. */\nfunction buildUngappedToGappedMap(gappedSeq: string): number[] {\n const map: number[] = [];\n for (let g = 0; g < gappedSeq.length; g++) {\n if (gappedSeq[g] !== '-' && gappedSeq[g] !== '.')\n map.push(g);\n }\n return map;\n}\n\n/** Parses a position code into [numericPart, insertionLetter] for sorting.\n * E.g. \"27\" → [27, \"\"], \"111A\" → [111, \"A\"], \"27B\" → [27, \"B\"]. */\nfunction parsePositionCode(code: string): [number, string] {\n const match = code.match(/^(\\d+)([A-Z]?)$/);\n if (!match) return [Infinity, code];\n return [parseInt(match[1], 10), match[2]];\n}\n\n/** Sorts position codes in scheme order: numeric ascending, then insertion letter. */\nfunction sortPositionCodes(codes: string[]): string[] {\n return codes.slice().sort((a, b) => {\n const [numA, insA] = parsePositionCode(a);\n const [numB, insB] = parsePositionCode(b);\n if (numA !== numB) return numA - numB;\n return insA.localeCompare(insB);\n });\n}\n\n/** Builds unified position list from all rows and creates an aligned sequence column.\n * Includes flanking residues (before/after the numbered region) padded with gaps.\n * Layout: [pre-region gaps+residues] [scheme-aligned region] [post-region residues+gaps]\n * @returns aligned column, full position list (including flanking), and the pre-region offset. */\nfunction createAlignedColumn(\n df: DG.DataFrame, seqCol: DG.Column<string>, result: DG.DataFrame,\n): {alignedCol: DG.Column<string>; unifiedPositions: string[]; preOffset: number} | null {\n const numberingMapCol = result.col('numbering_map');\n if (!numberingMapCol) return null;\n\n // Pass 1: collect all scheme position codes and per-row flanking lengths\n const allCodes = new Set<string>();\n const rowMaps: (Record<string, number> | null)[] = [];\n const rowPreLens: number[] = []; // chars before first numbered position\n const rowPostLens: number[] = []; // chars after last numbered position\n\n for (let i = 0; i < result.rowCount; i++) {\n const mapStr = numberingMapCol.get(i);\n const rawSeq = seqCol.get(i) ?? '';\n if (!mapStr) {\n rowMaps.push(null);\n rowPreLens.push(0);\n rowPostLens.push(0);\n continue;\n }\n try {\n const posToCharIdx: Record<string, number> = JSON.parse(mapStr);\n rowMaps.push(posToCharIdx);\n for (const code of Object.keys(posToCharIdx))\n allCodes.add(code);\n\n // Find min/max char indices that were numbered\n const charIndices = Object.values(posToCharIdx);\n const minChar = Math.min(...charIndices);\n const maxChar = Math.max(...charIndices);\n rowPreLens.push(minChar); // chars before first numbered\n rowPostLens.push(Math.max(0, rawSeq.length - maxChar - 1)); // chars after last numbered\n } catch {\n rowMaps.push(null);\n rowPreLens.push(0);\n rowPostLens.push(0);\n }\n }\n\n if (allCodes.size === 0) return null;\n\n const maxPreLen = Math.max(0, ...rowPreLens);\n const maxPostLen = Math.max(0, ...rowPostLens);\n\n // Build position names: [pre-flanking] + [scheme positions] + [post-flanking]\n const schemePositions = sortPositionCodes(Array.from(allCodes));\n const preNames: string[] = [];\n for (let p = maxPreLen; p > 0; p--)\n preNames.push(`N-${p}`);\n const postNames: string[] = [];\n for (let p = 1; p <= maxPostLen; p++)\n postNames.push(`C+${p}`);\n\n const unifiedPositions = [...preNames, ...schemePositions, ...postNames];\n const totalLen = unifiedPositions.length;\n const preOffset = maxPreLen; // scheme region starts at this index in the aligned string\n\n // Map scheme position codes → index in the full unified list\n const posToUnifiedIdx = new Map<string, number>();\n for (let s = 0; s < schemePositions.length; s++)\n posToUnifiedIdx.set(schemePositions[s], preOffset + s);\n\n // Pass 2: build aligned sequences\n const colName = df.columns.getUnusedName(`${seqCol.name} (aligned)`);\n const alignedCol = DG.Column.fromType(DG.COLUMN_TYPE.STRING, colName, df.rowCount);\n\n for (let i = 0; i < df.rowCount; i++) {\n const map = i < rowMaps.length ? rowMaps[i] : null;\n const rawSeq = seqCol.get(i) ?? '';\n\n if (!map) {\n alignedCol.set(i, '-'.repeat(totalLen));\n continue;\n }\n\n const aligned = new Array<string>(totalLen).fill('-');\n\n // Place scheme-numbered residues\n for (const [posCode, charIdx] of Object.entries(map)) {\n const uIdx = posToUnifiedIdx.get(posCode);\n if (uIdx != null && charIdx < rawSeq.length)\n aligned[uIdx] = rawSeq[charIdx];\n }\n\n // Place pre-region flanking residues (right-aligned within the pre-region block)\n const preLen = rowPreLens[i];\n const charIndices = Object.values(map);\n const minChar = Math.min(...charIndices);\n for (let p = 0; p < preLen; p++)\n aligned[preOffset - preLen + p] = rawSeq[minChar - preLen + p];\n\n // Place post-region flanking residues (left-aligned within the post-region block)\n const postLen = rowPostLens[i];\n const maxChar = Math.max(...charIndices);\n const postStart = preOffset + schemePositions.length;\n for (let p = 0; p < postLen; p++)\n aligned[postStart + p] = rawSeq[maxChar + 1 + p];\n\n alignedCol.set(i, aligned.join(''));\n }\n\n // Set macromolecule tags on the aligned column\n alignedCol.semType = DG.SEMTYPE.MACROMOLECULE;\n alignedCol.setTag(bioTAGS.aligned, ALIGNMENT.SEQ_MSA);\n alignedCol.setTag(bioTAGS.alphabet, ALPHABET.PT);\n alignedCol.meta.units = NOTATION.FASTA;\n alignedCol.setTag(DG.Tags.CellRenderer, 'sequence');\n alignedCol.setTag(bioTAGS.positionNames, unifiedPositions.join(', '));\n\n return {alignedCol, unifiedPositions, preOffset};\n}\n\n/** Applies numbering results (from either engine) to the sequence column and dataframe.\n *\n * Annotation strategy:\n * - Original column: row-level region spans only (char indices from numbering_map).\n * No column-level position names (they differ per row).\n * - Aligned column: column-level annotations only (all rows share unified positions).\n * Position names tag set to the unified list. */\nfunction applyNumberingResults(\n df: DG.DataFrame, seqCol: DG.Column<string>, result: DG.DataFrame,\n schemeName: string, populateRegions: boolean, engineLabel: string,\n): void {\n if (!result || result.rowCount === 0) {\n grok.shell.warning('No numbering results returned');\n return;\n }\n\n const posNamesCol = result.getCol('position_names');\n const chainTypeCol = result.getCol('chain_type');\n const annotJsonCol = result.getCol('annotations_json');\n const numberingMapCol = result.col('numbering_map');\n\n // If the source column is already aligned (MSA), remap numbering_map indices\n // from ungapped to gapped, since numbering engines strip gaps before processing.\n const isAligned = true; // always treat as aligned to handle remapping\n if (isAligned && numberingMapCol) {\n for (let i = 0; i < result.rowCount; i++) {\n const mapStr = numberingMapCol.get(i);\n if (!mapStr) continue;\n try {\n const posToCharIdx: Record<string, number> = JSON.parse(mapStr);\n const rawSeq = seqCol.get(i) ?? '';\n const ungapToGap = buildUngappedToGappedMap(rawSeq);\n const remapped: Record<string, number> = {};\n for (const [posCode, ungappedIdx] of Object.entries(posToCharIdx)) {\n if (ungappedIdx < ungapToGap.length)\n remapped[posCode] = ungapToGap[ungappedIdx];\n }\n numberingMapCol.set(i, JSON.stringify(remapped));\n } catch { /* skip */ }\n }\n }\n\n // Pick the row with the most annotations for column-level representative data\n let bestRowIdx = -1;\n let bestAnnotCount = -1;\n\n for (let i = 0; i < result.rowCount; i++) {\n const pn = posNamesCol.get(i);\n if (!pn || pn.length === 0) continue;\n const aj = annotJsonCol.get(i);\n let count = 0;\n if (aj)\n try { count = JSON.parse(aj).length; } catch { /* skip */ }\n if (count > bestAnnotCount) {\n bestAnnotCount = count;\n bestRowIdx = i;\n }\n }\n\n const chainType = bestRowIdx >= 0 ? (chainTypeCol.get(bestRowIdx) ?? '') : '';\n const annotationsJson = bestRowIdx >= 0 ? (annotJsonCol.get(bestRowIdx) ?? '[]') : '[]';\n\n if (bestRowIdx < 0) {\n grok.shell.warning(`${engineLabel} could not number the sequences. Check that they are valid antibody variable region sequences.`);\n return;\n }\n\n // Mark scheme on original column (no position names — they differ per row)\n seqCol.setTag(bioTAGS.numberingScheme, schemeName);\n\n // --- Original column: column-level annotation definitions (needed for renderer\n // to resolve annotation IDs → colors/names) + row-level region spans ---\n if (populateRegions) {\n try {\n const regionAnnotations: SeqAnnotation[] = JSON.parse(annotationsJson);\n const existing = getColumnAnnotations(seqCol).filter((a) => a.category !== AnnotationCategory.Structure);\n setColumnAnnotations(seqCol, [...existing, ...regionAnnotations]);\n } catch (err) {\n console.warn('Failed to set annotation definitions on original column:', err);\n }\n }\n\n if (populateRegions && numberingMapCol) {\n try {\n const annotCol = getOrCreateAnnotationColumn(df, seqCol);\n for (let i = 0; i < result.rowCount; i++) {\n const mapStr = numberingMapCol.get(i);\n const rowAnnotJson = annotJsonCol.get(i);\n if (!mapStr || !rowAnnotJson) continue;\n const posToCharIdx: Record<string, number> = JSON.parse(mapStr);\n const rowRegions: SeqAnnotation[] = JSON.parse(rowAnnotJson);\n\n const regionHits: SeqAnnotationHit[] = [];\n for (const region of rowRegions) {\n if (region.start == null || region.end == null) continue;\n const startCharIdx = posToCharIdx[region.start];\n const endCharIdx = posToCharIdx[region.end];\n if (startCharIdx == null || endCharIdx == null) continue;\n regionHits.push({\n annotationId: region.id,\n positionIndex: startCharIdx,\n endPositionIndex: endCharIdx,\n positionName: region.start,\n matchedMonomers: '',\n });\n }\n\n const existingHits = getRowAnnotations(annotCol, i) ?? [];\n setRowAnnotations(annotCol, i, mergeRowHits(existingHits, regionHits, true, false));\n }\n } catch (err) {\n console.warn('Failed to store per-row region data on original column:', err);\n }\n }\n\n // --- Aligned column: column-level annotations only ---\n const alignment = createAlignedColumn(df, seqCol, result);\n if (alignment) {\n df.columns.insert(alignment.alignedCol, df.columns.toList().indexOf(seqCol) + 1);\n if (grok.shell.tv?.dataFrame === df)\n grok.shell.tv.grid.scrollToCell(seqCol, 0);\n\n alignment.alignedCol.setTag(bioTAGS.numberingScheme, schemeName);\n\n if (populateRegions) {\n try {\n const regionAnnotations: SeqAnnotation[] = JSON.parse(annotationsJson);\n const existing = getColumnAnnotations(alignment.alignedCol).filter((a) => a.category !== AnnotationCategory.Structure);\n setColumnAnnotations(alignment.alignedCol, [...existing, ...regionAnnotations]);\n } catch (err) {\n console.warn('Failed to set column-level annotations on aligned column:', err);\n }\n }\n }\n\n df.fireValuesChanged();\n grok.shell.info(`Numbering applied: ${schemeName}, chain type: ${chainType}`);\n}\n"],"names":["NumberingScheme","ChainType","Heavy","Light_Kappa","Light_Lambda","IMGT","Kabat","Chothia","AHo","showNumberingSchemeDialog","df","tv","dataFrame","warning","seqCols","columns","bySemTypeAll","MACROMOLECULE","length","engines","funcs","find","meta","role","Error","f","pkgName","package","name","label","friendlyName","push","key","func","discoverEngines","engineLabels","map","e","schemeChoices","Object","values","tableInput","table","value","seqInput","column","filter","col","semType","schemeInput","choice","items","engineInput","dialog","title","add","onOK","async","seqCol","schemeName","selectedLabel","engine","pi","create","result","apply","scheme","toLowerCase","numberSequences","extractSequence","sequences","i","raw","get","results","n","posNames","fromType","STRING","chainTypes","annotJson","numDetail","numMap","r","error","percentIdentity","set","positionNames","chainType","JSON","stringify","annotations","numberingDetail","numberingMap","fromColumns","numberingResultsToDataFrame","runBuiltinNumbering","populateRegions","engineLabel","rowCount","posNamesCol","getCol","chainTypeCol","annotJsonCol","numberingMapCol","mapStr","posToCharIdx","parse","ungapToGap","buildUngappedToGappedMap","remapped","posCode","ungappedIdx","entries","bestRowIdx","bestAnnotCount","pn","aj","count","annotationsJson","setTag","numberingScheme","regionAnnotations","existing","a","category","Structure","err","console","warn","annotCol","rowAnnotJson","rowRegions","regionHits","region","start","end","startCharIdx","endCharIdx","annotationId","id","positionIndex","endPositionIndex","positionName","matchedMonomers","existingHits","alignment","allCodes","Set","rowMaps","rowPreLens","rowPostLens","rawSeq","code","keys","charIndices","minChar","Math","min","maxChar","max","size","maxPreLen","maxPostLen","schemePositions","Array","from","slice","sort","b","numA","insA","parsePositionCode","numB","insB","localeCompare","preNames","p","postNames","unifiedPositions","totalLen","preOffset","posToUnifiedIdx","Map","s","colName","getUnusedName","alignedCol","repeat","aligned","fill","charIdx","uIdx","preLen","postLen","postStart","join","alphabet","PT","units","FASTA","CellRenderer","createAlignedColumn","insert","toList","indexOf","grid","scrollToCell","fireValuesChanged","info","applyNumberingResults","message","close","show","gappedSeq","g","match","parseInt","Infinity"],"sourceRoot":""}
1
+ {"version":3,"file":"282.js","mappings":"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","sources":["webpack://bio/./node_modules/@datagrok-libraries/bio/src/utils/macromolecule/numbering-schemes.js","webpack://bio/./src/utils/annotations/numbering-ui.ts"],"sourcesContent":["/** Static antibody numbering scheme region definitions.\n *\n * Contains FR/CDR boundaries for IMGT, Kabat, Chothia, and AHo schemes.\n * These are the canonical position ranges used after a numbering tool\n * (e.g. ANARCI) has assigned scheme-specific position names.\n */\nexport var NumberingScheme;\n(function (NumberingScheme) {\n NumberingScheme[\"IMGT\"] = \"IMGT\";\n NumberingScheme[\"Kabat\"] = \"Kabat\";\n NumberingScheme[\"Chothia\"] = \"Chothia\";\n NumberingScheme[\"AHo\"] = \"AHo\";\n})(NumberingScheme || (NumberingScheme = {}));\nexport var ChainType;\n(function (ChainType) {\n ChainType[\"Heavy\"] = \"Heavy\";\n ChainType[\"Light_Kappa\"] = \"Light_Kappa\";\n ChainType[\"Light_Lambda\"] = \"Light_Lambda\";\n})(ChainType || (ChainType = {}));\n/** IMGT region boundaries — the reference numbering scheme.\n * @see https://www.imgt.org/IMGTScientificChart/Numbering/IMGTIGVLsuperfamily.html\n */\nexport const IMGT_REGIONS = {\n [ChainType.Heavy]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '26', chainType: ChainType.Heavy },\n { name: 'CDR1', type: 'CDR', startPosition: '27', endPosition: '38', chainType: ChainType.Heavy },\n { name: 'FR2', type: 'FR', startPosition: '39', endPosition: '55', chainType: ChainType.Heavy },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '65', chainType: ChainType.Heavy },\n { name: 'FR3', type: 'FR', startPosition: '66', endPosition: '104', chainType: ChainType.Heavy },\n { name: 'CDR3', type: 'CDR', startPosition: '105', endPosition: '117', chainType: ChainType.Heavy },\n { name: 'FR4', type: 'FR', startPosition: '118', endPosition: '128', chainType: ChainType.Heavy },\n ],\n [ChainType.Light_Kappa]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '26', chainType: ChainType.Light_Kappa },\n { name: 'CDR1', type: 'CDR', startPosition: '27', endPosition: '38', chainType: ChainType.Light_Kappa },\n { name: 'FR2', type: 'FR', startPosition: '39', endPosition: '55', chainType: ChainType.Light_Kappa },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '65', chainType: ChainType.Light_Kappa },\n { name: 'FR3', type: 'FR', startPosition: '66', endPosition: '104', chainType: ChainType.Light_Kappa },\n { name: 'CDR3', type: 'CDR', startPosition: '105', endPosition: '117', chainType: ChainType.Light_Kappa },\n { name: 'FR4', type: 'FR', startPosition: '118', endPosition: '127', chainType: ChainType.Light_Kappa },\n ],\n [ChainType.Light_Lambda]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '26', chainType: ChainType.Light_Lambda },\n { name: 'CDR1', type: 'CDR', startPosition: '27', endPosition: '38', chainType: ChainType.Light_Lambda },\n { name: 'FR2', type: 'FR', startPosition: '39', endPosition: '55', chainType: ChainType.Light_Lambda },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '65', chainType: ChainType.Light_Lambda },\n { name: 'FR3', type: 'FR', startPosition: '66', endPosition: '104', chainType: ChainType.Light_Lambda },\n { name: 'CDR3', type: 'CDR', startPosition: '105', endPosition: '117', chainType: ChainType.Light_Lambda },\n { name: 'FR4', type: 'FR', startPosition: '118', endPosition: '127', chainType: ChainType.Light_Lambda },\n ],\n};\n/** Kabat region boundaries (differ mainly in CDR definitions). */\nexport const KABAT_REGIONS = {\n [ChainType.Heavy]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '30', chainType: ChainType.Heavy },\n { name: 'CDR1', type: 'CDR', startPosition: '31', endPosition: '35', chainType: ChainType.Heavy },\n { name: 'FR2', type: 'FR', startPosition: '36', endPosition: '49', chainType: ChainType.Heavy },\n { name: 'CDR2', type: 'CDR', startPosition: '50', endPosition: '65', chainType: ChainType.Heavy },\n { name: 'FR3', type: 'FR', startPosition: '66', endPosition: '94', chainType: ChainType.Heavy },\n { name: 'CDR3', type: 'CDR', startPosition: '95', endPosition: '102', chainType: ChainType.Heavy },\n { name: 'FR4', type: 'FR', startPosition: '103', endPosition: '113', chainType: ChainType.Heavy },\n ],\n [ChainType.Light_Kappa]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '23', chainType: ChainType.Light_Kappa },\n { name: 'CDR1', type: 'CDR', startPosition: '24', endPosition: '34', chainType: ChainType.Light_Kappa },\n { name: 'FR2', type: 'FR', startPosition: '35', endPosition: '49', chainType: ChainType.Light_Kappa },\n { name: 'CDR2', type: 'CDR', startPosition: '50', endPosition: '56', chainType: ChainType.Light_Kappa },\n { name: 'FR3', type: 'FR', startPosition: '57', endPosition: '88', chainType: ChainType.Light_Kappa },\n { name: 'CDR3', type: 'CDR', startPosition: '89', endPosition: '97', chainType: ChainType.Light_Kappa },\n { name: 'FR4', type: 'FR', startPosition: '98', endPosition: '107', chainType: ChainType.Light_Kappa },\n ],\n [ChainType.Light_Lambda]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '23', chainType: ChainType.Light_Lambda },\n { name: 'CDR1', type: 'CDR', startPosition: '24', endPosition: '34', chainType: ChainType.Light_Lambda },\n { name: 'FR2', type: 'FR', startPosition: '35', endPosition: '49', chainType: ChainType.Light_Lambda },\n { name: 'CDR2', type: 'CDR', startPosition: '50', endPosition: '56', chainType: ChainType.Light_Lambda },\n { name: 'FR3', type: 'FR', startPosition: '57', endPosition: '88', chainType: ChainType.Light_Lambda },\n { name: 'CDR3', type: 'CDR', startPosition: '89', endPosition: '97', chainType: ChainType.Light_Lambda },\n { name: 'FR4', type: 'FR', startPosition: '98', endPosition: '107', chainType: ChainType.Light_Lambda },\n ],\n};\n/** Chothia region boundaries. */\nexport const CHOTHIA_REGIONS = {\n [ChainType.Heavy]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '25', chainType: ChainType.Heavy },\n { name: 'CDR1', type: 'CDR', startPosition: '26', endPosition: '32', chainType: ChainType.Heavy },\n { name: 'FR2', type: 'FR', startPosition: '33', endPosition: '51', chainType: ChainType.Heavy },\n { name: 'CDR2', type: 'CDR', startPosition: '52', endPosition: '56', chainType: ChainType.Heavy },\n { name: 'FR3', type: 'FR', startPosition: '57', endPosition: '94', chainType: ChainType.Heavy },\n { name: 'CDR3', type: 'CDR', startPosition: '95', endPosition: '102', chainType: ChainType.Heavy },\n { name: 'FR4', type: 'FR', startPosition: '103', endPosition: '113', chainType: ChainType.Heavy },\n ],\n [ChainType.Light_Kappa]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '25', chainType: ChainType.Light_Kappa },\n { name: 'CDR1', type: 'CDR', startPosition: '26', endPosition: '32', chainType: ChainType.Light_Kappa },\n { name: 'FR2', type: 'FR', startPosition: '33', endPosition: '49', chainType: ChainType.Light_Kappa },\n { name: 'CDR2', type: 'CDR', startPosition: '50', endPosition: '52', chainType: ChainType.Light_Kappa },\n { name: 'FR3', type: 'FR', startPosition: '53', endPosition: '90', chainType: ChainType.Light_Kappa },\n { name: 'CDR3', type: 'CDR', startPosition: '91', endPosition: '96', chainType: ChainType.Light_Kappa },\n { name: 'FR4', type: 'FR', startPosition: '97', endPosition: '107', chainType: ChainType.Light_Kappa },\n ],\n [ChainType.Light_Lambda]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '25', chainType: ChainType.Light_Lambda },\n { name: 'CDR1', type: 'CDR', startPosition: '26', endPosition: '32', chainType: ChainType.Light_Lambda },\n { name: 'FR2', type: 'FR', startPosition: '33', endPosition: '49', chainType: ChainType.Light_Lambda },\n { name: 'CDR2', type: 'CDR', startPosition: '50', endPosition: '52', chainType: ChainType.Light_Lambda },\n { name: 'FR3', type: 'FR', startPosition: '53', endPosition: '90', chainType: ChainType.Light_Lambda },\n { name: 'CDR3', type: 'CDR', startPosition: '91', endPosition: '96', chainType: ChainType.Light_Lambda },\n { name: 'FR4', type: 'FR', startPosition: '97', endPosition: '107', chainType: ChainType.Light_Lambda },\n ],\n};\n/** AHo region boundaries. */\nexport const AHO_REGIONS = {\n [ChainType.Heavy]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '24', chainType: ChainType.Heavy },\n { name: 'CDR1', type: 'CDR', startPosition: '25', endPosition: '40', chainType: ChainType.Heavy },\n { name: 'FR2', type: 'FR', startPosition: '41', endPosition: '55', chainType: ChainType.Heavy },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '78', chainType: ChainType.Heavy },\n { name: 'FR3', type: 'FR', startPosition: '79', endPosition: '108', chainType: ChainType.Heavy },\n { name: 'CDR3', type: 'CDR', startPosition: '109', endPosition: '138', chainType: ChainType.Heavy },\n { name: 'FR4', type: 'FR', startPosition: '139', endPosition: '149', chainType: ChainType.Heavy },\n ],\n [ChainType.Light_Kappa]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '24', chainType: ChainType.Light_Kappa },\n { name: 'CDR1', type: 'CDR', startPosition: '25', endPosition: '40', chainType: ChainType.Light_Kappa },\n { name: 'FR2', type: 'FR', startPosition: '41', endPosition: '55', chainType: ChainType.Light_Kappa },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '78', chainType: ChainType.Light_Kappa },\n { name: 'FR3', type: 'FR', startPosition: '79', endPosition: '108', chainType: ChainType.Light_Kappa },\n { name: 'CDR3', type: 'CDR', startPosition: '109', endPosition: '138', chainType: ChainType.Light_Kappa },\n { name: 'FR4', type: 'FR', startPosition: '139', endPosition: '149', chainType: ChainType.Light_Kappa },\n ],\n [ChainType.Light_Lambda]: [\n { name: 'FR1', type: 'FR', startPosition: '1', endPosition: '24', chainType: ChainType.Light_Lambda },\n { name: 'CDR1', type: 'CDR', startPosition: '25', endPosition: '40', chainType: ChainType.Light_Lambda },\n { name: 'FR2', type: 'FR', startPosition: '41', endPosition: '55', chainType: ChainType.Light_Lambda },\n { name: 'CDR2', type: 'CDR', startPosition: '56', endPosition: '78', chainType: ChainType.Light_Lambda },\n { name: 'FR3', type: 'FR', startPosition: '79', endPosition: '108', chainType: ChainType.Light_Lambda },\n { name: 'CDR3', type: 'CDR', startPosition: '109', endPosition: '138', chainType: ChainType.Light_Lambda },\n { name: 'FR4', type: 'FR', startPosition: '139', endPosition: '149', chainType: ChainType.Light_Lambda },\n ],\n};\n/** Lookup table: scheme → chain type → region defs */\nexport const SCHEME_REGIONS = {\n [NumberingScheme.IMGT]: IMGT_REGIONS,\n [NumberingScheme.Kabat]: KABAT_REGIONS,\n [NumberingScheme.Chothia]: CHOTHIA_REGIONS,\n [NumberingScheme.AHo]: AHO_REGIONS,\n};\n//# sourceMappingURL=numbering-schemes.js.map","/* eslint-disable max-len */\nimport * as grok from 'datagrok-api/grok';\nimport * as ui from 'datagrok-api/ui';\nimport * as DG from 'datagrok-api/dg';\n\nimport {TAGS as bioTAGS, ALIGNMENT, ALPHABET, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';\nimport {\n SeqAnnotation, SeqAnnotationHit, AnnotationCategory,\n} from '@datagrok-libraries/bio/src/utils/macromolecule/annotations';\nimport {NumberingScheme} from '@datagrok-libraries/bio/src/utils/macromolecule/numbering-schemes';\nimport {\n setColumnAnnotations, getColumnAnnotations,\n getOrCreateAnnotationColumn, getRowAnnotations, setRowAnnotations, mergeRowHits,\n} from './annotation-manager';\nimport {_package} from '../../package';\nimport type {NumberingResult, Scheme} from '../antibody-numbering (WIP)';\nimport {VdRegionsViewer} from '../../viewers/vd-regions-viewer';\nimport { VdRegion, VdRegionType } from '@datagrok-libraries/bio/src/viewers/vd-regions';\n\nconst BUILTIN_ENGINE_KEY = '__builtin__';\nconst BUILTIN_ENGINE_LABEL = 'Built-in (TypeScript)';\n\n/** An engine entry: either a dynamically discovered DG.Func or the built-in TS engine. */\ninterface NumberingEngine {\n /** Display label for the dropdown */\n label: string;\n /** Unique key — nqName for DG.Func engines, BUILTIN_ENGINE_KEY for built-in */\n key: string;\n /** The DG.Func to call, or null for the built-in engine */\n func: DG.Func | null;\n}\n\n/** Discovers all registered antibody numbering engines + the built-in TS engine.\n * Dynamic engines (meta.role = 'antibodyNumbering') come first; built-in is last. */\nfunction discoverEngines(): NumberingEngine[] {\n const engines: NumberingEngine[] = [];\n\n const funcs = DG.Func.find({meta: {role: 'antibodyNumbering'}});\n if (funcs.length === 0) {\n grok.shell.error('No antibody numbering engines found. Make sure that Proteomics plugin is installed and up to date.');\n throw new Error('No external antibody numbering engines found. Make sure that Proteomics plugin is installed and up to date.');\n }\n for (const f of funcs) {\n const pkgName = f.package?.name ?? '';\n const label = f.friendlyName || f.name;\n engines.push({\n label: label,\n key: pkgName ? `${pkgName}:${f.name}` : f.name,\n func: f,\n });\n }\n\n // Built-in TS engine is always last\n engines.push({label: BUILTIN_ENGINE_LABEL, key: BUILTIN_ENGINE_KEY, func: null});\n return engines;\n}\n\n/** Converts TS NumberingResult[] to a DG.DataFrame matching the expected output shape.\n * Columns: position_names, chain_type, annotations_json, numbering_detail, numbering_map. */\nexport function numberingResultsToDataFrame(results: NumberingResult[]): DG.DataFrame {\n const n = results.length;\n const posNames = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'position_names', n);\n const chainTypes = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'chain_type', n);\n const annotJson = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'annotations_json', n);\n const numDetail = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'numbering_detail', n);\n const numMap = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'numbering_map', n);\n\n for (let i = 0; i < n; i++) {\n const r = results[i];\n if (r.error && r.percentIdentity < 0.3) {\n posNames.set(i, '');\n chainTypes.set(i, '');\n annotJson.set(i, '[]');\n numDetail.set(i, '');\n numMap.set(i, '');\n } else {\n posNames.set(i, r.positionNames);\n chainTypes.set(i, r.chainType);\n annotJson.set(i, JSON.stringify(r.annotations));\n numDetail.set(i, JSON.stringify(r.numberingDetail));\n numMap.set(i, JSON.stringify(r.numberingMap));\n }\n }\n\n return DG.DataFrame.fromColumns([posNames, chainTypes, annotJson, numDetail, numMap]);\n}\n\n/** Runs the built-in TS numbering engine on all rows of a sequence column. */\nasync function runBuiltinNumbering(\n seqCol: DG.Column<string>, schemeName: string,\n): Promise<DG.DataFrame> {\n const {numberSequences, extractSequence} = await import('../antibody-numbering (WIP)');\n const scheme = schemeName.toLowerCase() as Scheme;\n\n const sequences: string[] = [];\n for (let i = 0; i < seqCol.length; i++) {\n const raw = seqCol.get(i);\n sequences.push(extractSequence(raw ?? ''));\n }\n\n const results = numberSequences(sequences, scheme);\n return numberingResultsToDataFrame(results);\n}\n\nexport function showNumberingSchemeDialog(): void {\n const df = grok.shell.tv?.dataFrame;\n if (!df) {\n grok.shell.warning('No table open');\n return;\n }\n\n const seqCols = df.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);\n if (seqCols.length === 0) {\n grok.shell.warning('No macromolecule columns found');\n return;\n }\n\n const engines = discoverEngines();\n const engineLabels = engines.map((e) => e.label);\n const schemeChoices = Object.values(NumberingScheme);\n\n const tableInput = ui.input.table('Table', {value: df});\n const seqInput = ui.input.column('Sequence', {\n table: df, value: seqCols[0],\n filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE,\n });\n const schemeInput = ui.input.choice('Scheme', {value: NumberingScheme.IMGT, items: schemeChoices});\n const engineInput = ui.input.choice('Engine', {\n value: engineLabels[0], items: engineLabels,\n });\n // const populateRegions = ui.input.bool('Populate FR/CDR regions', {value: true});\n // const openVdRegions = ui.input.bool('Open VD Regions viewer', {value: true});\n\n const dialog = ui.dialog({title: 'Apply Antibody Numbering'})\n .add(ui.inputs([tableInput, seqInput, schemeInput, engineInput]))\n .onOK(async () => {\n const seqCol = seqInput.value!;\n const schemeName = schemeInput.value!;\n const selectedLabel = engineInput.value!;\n const engine = engines.find((e) => e.label === selectedLabel) ?? engines[engines.length - 1];\n const pi = DG.TaskBarProgressIndicator.create(`Applying ${schemeName} numbering...`);\n try {\n let result: DG.DataFrame;\n if (engine.func)\n result = await engine.func.apply({df: df, seqCol: seqCol, scheme: schemeName.toLowerCase()});\n else\n result = await runBuiltinNumbering(seqCol, schemeName);\n\n applyNumberingResults(df, seqCol, result, schemeName, true, engine.label);\n\n // // Open VD Regions viewer\n // if (openVdRegions.value && grok.shell.tv) {\n // try {\n // await grok.shell.tv.dataFrame.plot.fromType('VdRegions', {});\n // } catch (err) {\n // console.warn('Could not open VD Regions viewer:', err);\n // }\n // }\n } catch (err: any) {\n grok.shell.error(`Numbering failed: ${err.message ?? err}`);\n console.error(err);\n } finally {\n pi.close();\n }\n });\n\n dialog.show();\n}\n\n/** Builds a map from ungapped character index to gapped character index.\n * Used when the source column is already aligned (MSA) — numbering engines strip gaps,\n * so their output indices refer to the ungapped sequence, not the gapped original. */\nfunction buildUngappedToGappedMap(gappedSeq: string): number[] {\n const map: number[] = [];\n for (let g = 0; g < gappedSeq.length; g++) {\n if (gappedSeq[g] !== '-' && gappedSeq[g] !== '.')\n map.push(g);\n }\n return map;\n}\n\n/** Parses a position code into [numericPart, insertionLetter] for sorting.\n * E.g. \"27\" → [27, \"\"], \"111A\" → [111, \"A\"], \"27B\" → [27, \"B\"]. */\nfunction parsePositionCode(code: string): [number, string] {\n const match = code.match(/^(\\d+)([A-Z]?)$/);\n if (!match) return [Infinity, code];\n return [parseInt(match[1], 10), match[2]];\n}\n\n/** Sorts position codes in scheme order: numeric ascending, then insertion letter. */\nfunction sortPositionCodes(codes: string[]): string[] {\n return codes.slice().sort((a, b) => {\n const [numA, insA] = parsePositionCode(a);\n const [numB, insB] = parsePositionCode(b);\n if (numA !== numB) return numA - numB;\n return insA.localeCompare(insB);\n });\n}\n\n/** Builds unified position list from all rows and creates an aligned sequence column.\n * Includes flanking residues (before/after the numbered region) padded with gaps.\n * Layout: [pre-region gaps+residues] [scheme-aligned region] [post-region residues+gaps]\n * @returns aligned column, full position list (including flanking), and the pre-region offset. */\nfunction createAlignedColumn(\n df: DG.DataFrame, seqCol: DG.Column<string>, result: DG.DataFrame,\n): {alignedCol: DG.Column<string>; unifiedPositions: string[]; preOffset: number} | null {\n const numberingMapCol = result.col('numbering_map');\n if (!numberingMapCol) return null;\n\n // Pass 1: collect all scheme position codes and per-row flanking lengths\n const allCodes = new Set<string>();\n const rowMaps: (Record<string, number> | null)[] = [];\n const rowPreLens: number[] = []; // chars before first numbered position\n const rowPostLens: number[] = []; // chars after last numbered position\n\n for (let i = 0; i < result.rowCount; i++) {\n const mapStr = numberingMapCol.get(i);\n const rawSeq = seqCol.get(i) ?? '';\n if (!mapStr) {\n rowMaps.push(null);\n rowPreLens.push(0);\n rowPostLens.push(0);\n continue;\n }\n try {\n const posToCharIdx: Record<string, number> = JSON.parse(mapStr);\n rowMaps.push(posToCharIdx);\n for (const code of Object.keys(posToCharIdx))\n allCodes.add(code);\n\n // Find min/max char indices that were numbered\n const charIndices = Object.values(posToCharIdx);\n const minChar = Math.min(...charIndices);\n const maxChar = Math.max(...charIndices);\n rowPreLens.push(minChar); // chars before first numbered\n rowPostLens.push(Math.max(0, rawSeq.length - maxChar - 1)); // chars after last numbered\n } catch {\n rowMaps.push(null);\n rowPreLens.push(0);\n rowPostLens.push(0);\n }\n }\n\n if (allCodes.size === 0) return null;\n\n const maxPreLen = Math.max(0, ...rowPreLens);\n const maxPostLen = Math.max(0, ...rowPostLens);\n\n // Build position names: [pre-flanking] + [scheme positions] + [post-flanking]\n const schemePositions = sortPositionCodes(Array.from(allCodes));\n const preNames: string[] = [];\n for (let p = maxPreLen; p > 0; p--)\n preNames.push(`N-${p}`);\n const postNames: string[] = [];\n for (let p = 1; p <= maxPostLen; p++)\n postNames.push(`C+${p}`);\n\n const unifiedPositions = [...preNames, ...schemePositions, ...postNames];\n const totalLen = unifiedPositions.length;\n const preOffset = maxPreLen; // scheme region starts at this index in the aligned string\n\n // Map scheme position codes → index in the full unified list\n const posToUnifiedIdx = new Map<string, number>();\n for (let s = 0; s < schemePositions.length; s++)\n posToUnifiedIdx.set(schemePositions[s], preOffset + s);\n\n // Pass 2: build aligned sequences\n const colName = df.columns.getUnusedName(`${seqCol.name} (aligned)`);\n const alignedCol = DG.Column.fromType(DG.COLUMN_TYPE.STRING, colName, df.rowCount);\n\n for (let i = 0; i < df.rowCount; i++) {\n const map = i < rowMaps.length ? rowMaps[i] : null;\n const rawSeq = seqCol.get(i) ?? '';\n\n if (!map) {\n alignedCol.set(i, '-'.repeat(totalLen));\n continue;\n }\n\n const aligned = new Array<string>(totalLen).fill('-');\n\n // Place scheme-numbered residues\n for (const [posCode, charIdx] of Object.entries(map)) {\n const uIdx = posToUnifiedIdx.get(posCode);\n if (uIdx != null && charIdx < rawSeq.length)\n aligned[uIdx] = rawSeq[charIdx];\n }\n\n // Place pre-region flanking residues (right-aligned within the pre-region block)\n const preLen = rowPreLens[i];\n const charIndices = Object.values(map);\n const minChar = Math.min(...charIndices);\n for (let p = 0; p < preLen; p++)\n aligned[preOffset - preLen + p] = rawSeq[minChar - preLen + p];\n\n // Place post-region flanking residues (left-aligned within the post-region block)\n const postLen = rowPostLens[i];\n const maxChar = Math.max(...charIndices);\n const postStart = preOffset + schemePositions.length;\n for (let p = 0; p < postLen; p++)\n aligned[postStart + p] = rawSeq[maxChar + 1 + p];\n\n alignedCol.set(i, aligned.join(''));\n }\n\n // Set macromolecule tags on the aligned column\n alignedCol.semType = DG.SEMTYPE.MACROMOLECULE;\n alignedCol.setTag(bioTAGS.aligned, ALIGNMENT.SEQ_MSA);\n alignedCol.setTag(bioTAGS.alphabet, ALPHABET.PT);\n alignedCol.meta.units = NOTATION.FASTA;\n alignedCol.setTag(DG.Tags.CellRenderer, 'sequence');\n alignedCol.setTag(bioTAGS.positionNames, unifiedPositions.join(', '));\n\n return {alignedCol, unifiedPositions, preOffset};\n}\n\n/** Applies numbering results (from either engine) to the sequence column and dataframe.\n *\n * Annotation strategy:\n * - Original column: row-level region spans only (char indices from numbering_map).\n * No column-level position names (they differ per row).\n * - Aligned column: column-level annotations only (all rows share unified positions).\n * Position names tag set to the unified list. */\nfunction applyNumberingResults(\n df: DG.DataFrame, seqCol: DG.Column<string>, result: DG.DataFrame,\n schemeName: string, populateRegions: boolean, engineLabel: string,\n): void {\n if (!result || result.rowCount === 0) {\n grok.shell.warning('No numbering results returned');\n return;\n }\n\n const posNamesCol = result.getCol('position_names');\n const chainTypeCol = result.getCol('chain_type');\n const annotJsonCol = result.getCol('annotations_json');\n const numberingMapCol = result.col('numbering_map');\n\n // If the source column is already aligned (MSA), remap numbering_map indices\n // from ungapped to gapped, since numbering engines strip gaps before processing.\n const isAligned = true; // always treat as aligned to handle remapping\n if (isAligned && numberingMapCol) {\n for (let i = 0; i < result.rowCount; i++) {\n const mapStr = numberingMapCol.get(i);\n if (!mapStr) continue;\n try {\n const posToCharIdx: Record<string, number> = JSON.parse(mapStr);\n const rawSeq = seqCol.get(i) ?? '';\n const ungapToGap = buildUngappedToGappedMap(rawSeq);\n const remapped: Record<string, number> = {};\n for (const [posCode, ungappedIdx] of Object.entries(posToCharIdx)) {\n if (ungappedIdx < ungapToGap.length)\n remapped[posCode] = ungapToGap[ungappedIdx];\n }\n numberingMapCol.set(i, JSON.stringify(remapped));\n } catch { /* skip */ }\n }\n }\n\n // Pick the row with the most annotations for column-level representative data\n let bestRowIdx = -1;\n let bestAnnotCount = -1;\n\n for (let i = 0; i < result.rowCount; i++) {\n const pn = posNamesCol.get(i);\n if (!pn || pn.length === 0) continue;\n const aj = annotJsonCol.get(i);\n let count = 0;\n if (aj)\n try { count = JSON.parse(aj).length; } catch { /* skip */ }\n if (count > bestAnnotCount) {\n bestAnnotCount = count;\n bestRowIdx = i;\n }\n }\n\n const chainType = bestRowIdx >= 0 ? (chainTypeCol.get(bestRowIdx) ?? '') : '';\n const annotationsJson = bestRowIdx >= 0 ? (annotJsonCol.get(bestRowIdx) ?? '[]') : '[]';\n\n if (bestRowIdx < 0) {\n grok.shell.warning(`${engineLabel} could not number the sequences. Check that they are valid antibody variable region sequences.`);\n return;\n }\n\n // Mark scheme on original column (no position names — they differ per row)\n seqCol.setTag(bioTAGS.numberingScheme, schemeName);\n\n // --- Original column: column-level annotation definitions (needed for renderer\n // to resolve annotation IDs → colors/names) + row-level region spans ---\n if (populateRegions) {\n try {\n const regionAnnotations: SeqAnnotation[] = JSON.parse(annotationsJson);\n const existing = getColumnAnnotations(seqCol).filter((a) => a.category !== AnnotationCategory.Structure);\n setColumnAnnotations(seqCol, [...existing, ...regionAnnotations]);\n } catch (err) {\n console.warn('Failed to set annotation definitions on original column:', err);\n }\n }\n\n if (populateRegions && numberingMapCol) {\n try {\n const annotCol = getOrCreateAnnotationColumn(df, seqCol);\n for (let i = 0; i < result.rowCount; i++) {\n const mapStr = numberingMapCol.get(i);\n const rowAnnotJson = annotJsonCol.get(i);\n if (!mapStr || !rowAnnotJson) continue;\n const posToCharIdx: Record<string, number> = JSON.parse(mapStr);\n const rowRegions: SeqAnnotation[] = JSON.parse(rowAnnotJson);\n\n const regionHits: SeqAnnotationHit[] = [];\n for (const region of rowRegions) {\n if (region.start == null || region.end == null) continue;\n const startCharIdx = posToCharIdx[region.start];\n const endCharIdx = posToCharIdx[region.end];\n if (startCharIdx == null || endCharIdx == null) continue;\n regionHits.push({\n annotationId: region.id,\n positionIndex: startCharIdx,\n endPositionIndex: endCharIdx,\n positionName: region.start,\n matchedMonomers: '',\n });\n }\n\n const existingHits = getRowAnnotations(annotCol, i) ?? [];\n setRowAnnotations(annotCol, i, mergeRowHits(existingHits, regionHits, true, false));\n }\n } catch (err) {\n console.warn('Failed to store per-row region data on original column:', err);\n }\n }\n\n // --- Aligned column: column-level annotations only ---\n const alignment = createAlignedColumn(df, seqCol, result);\n if (alignment) {\n df.columns.insert(alignment.alignedCol, df.columns.toList().indexOf(seqCol) + 1);\n if (grok.shell.tv?.dataFrame === df)\n grok.shell.tv.grid.scrollToCell(seqCol, 0);\n\n alignment.alignedCol.setTag(bioTAGS.numberingScheme, schemeName);\n\n if (populateRegions) {\n try {\n const regionAnnotations: SeqAnnotation[] = JSON.parse(annotationsJson);\n const existing = getColumnAnnotations(alignment.alignedCol).filter((a) => a.category !== AnnotationCategory.Structure);\n setColumnAnnotations(alignment.alignedCol, [...existing, ...regionAnnotations]);\n // chunk for vd regions viewer if that becomes a desired feature in the future\n // if (grok.shell.tv?.dataFrame === df) {\n // (async () => {\n // const vdRegionsViewer: VdRegionsViewer = await grok.shell.tv.dataFrame.plot.fromType('VdRegions',) as VdRegionsViewer;\n // vdRegionsViewer.chains = [chainType];\n // vdRegionsViewer.setData(regionAnnotations.map((a, i) => ({\n // type: a.name?.toLowerCase().startsWith('cdr') ? VdRegionType.CDR : VdRegionType.FR,\n // name: a.name,\n // chain: chainType,\n // order: i,\n // sequenceColumnName: alignment.alignedCol.name,\n // positionStartName: a.start ?? '',\n // positionEndName: a.end ?? '',\n // } satisfies VdRegion)));\n // grok.shell.tv.addViewer(vdRegionsViewer);\n // })();\n // }\n } catch (err) {\n console.warn('Failed to set column-level annotations on aligned column:', err);\n }\n }\n }\n\n df.fireValuesChanged();\n\n grok.shell.info(`Numbering applied: ${schemeName}, chain type: ${chainType}`);\n}\n"],"names":["NumberingScheme","ChainType","Heavy","Light_Kappa","Light_Lambda","IMGT","Kabat","Chothia","AHo","showNumberingSchemeDialog","df","tv","dataFrame","warning","seqCols","columns","bySemTypeAll","MACROMOLECULE","length","engines","funcs","find","meta","role","error","Error","f","pkgName","package","name","label","friendlyName","push","key","func","discoverEngines","engineLabels","map","e","schemeChoices","Object","values","tableInput","table","value","seqInput","column","filter","col","semType","schemeInput","choice","items","engineInput","dialog","title","add","onOK","async","seqCol","schemeName","selectedLabel","engine","pi","create","result","apply","scheme","toLowerCase","numberSequences","extractSequence","sequences","i","raw","get","results","n","posNames","fromType","STRING","chainTypes","annotJson","numDetail","numMap","r","percentIdentity","set","positionNames","chainType","JSON","stringify","annotations","numberingDetail","numberingMap","fromColumns","numberingResultsToDataFrame","runBuiltinNumbering","populateRegions","engineLabel","rowCount","posNamesCol","getCol","chainTypeCol","annotJsonCol","numberingMapCol","mapStr","posToCharIdx","parse","ungapToGap","buildUngappedToGappedMap","remapped","posCode","ungappedIdx","entries","bestRowIdx","bestAnnotCount","pn","aj","count","annotationsJson","setTag","numberingScheme","regionAnnotations","existing","a","category","Structure","err","console","warn","annotCol","rowAnnotJson","rowRegions","regionHits","region","start","end","startCharIdx","endCharIdx","annotationId","id","positionIndex","endPositionIndex","positionName","matchedMonomers","existingHits","alignment","allCodes","Set","rowMaps","rowPreLens","rowPostLens","rawSeq","code","keys","charIndices","minChar","Math","min","maxChar","max","size","maxPreLen","maxPostLen","schemePositions","Array","from","slice","sort","b","numA","insA","parsePositionCode","numB","insB","localeCompare","preNames","p","postNames","unifiedPositions","totalLen","preOffset","posToUnifiedIdx","Map","s","colName","getUnusedName","alignedCol","repeat","aligned","fill","charIdx","uIdx","preLen","postLen","postStart","join","alphabet","PT","units","FASTA","CellRenderer","createAlignedColumn","insert","toList","indexOf","grid","scrollToCell","fireValuesChanged","info","applyNumberingResults","message","close","show","gappedSeq","g","match","parseInt","Infinity"],"sourceRoot":""}
package/dist/422.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";(self.webpackChunkbio=self.webpackChunkbio||[]).push([[422],{9422(e,t,i){i.d(t,{showLiabilityScannerDialog:()=>g});var n=i(4328),a=i(7389),o=i(6082),l=i(4958),r=i(4517),d=i(3736);const s=[{id:"deamid-ng",name:"Deamidation (NG)",pattern:/NG/g,length:2,severity:r.Hq.High,ruleCategory:"deamidation",color:r.D5.liability.deamidation,enabled:!0},{id:"deamid-ns",name:"Deamidation (NS)",pattern:/NS/g,length:2,severity:r.Hq.Medium,ruleCategory:"deamidation",color:r.D5.liability.deamidation,enabled:!0},{id:"deamid-na",name:"Deamidation (NA)",pattern:/NA/g,length:2,severity:r.Hq.Low,ruleCategory:"deamidation",color:r.D5.liability.deamidation,enabled:!0},{id:"deamid-nd",name:"Deamidation (ND)",pattern:/ND/g,length:2,severity:r.Hq.Low,ruleCategory:"deamidation",color:r.D5.liability.deamidation,enabled:!0},{id:"deamid-nt",name:"Deamidation (NT)",pattern:/NT/g,length:2,severity:r.Hq.Low,ruleCategory:"deamidation",color:r.D5.liability.deamidation,enabled:!0},{id:"isom-dg",name:"Isomerization (DG)",pattern:/DG/g,length:2,severity:r.Hq.High,ruleCategory:"isomerization",color:r.D5.liability.isomerization,enabled:!0},{id:"isom-ds",name:"Isomerization (DS)",pattern:/DS/g,length:2,severity:r.Hq.Medium,ruleCategory:"isomerization",color:r.D5.liability.isomerization,enabled:!0},{id:"oxid-m",name:"Oxidation (Met)",pattern:/M/g,length:1,severity:r.Hq.Medium,ruleCategory:"oxidation",color:r.D5.liability.oxidation,enabled:!0},{id:"oxid-w",name:"Oxidation (Trp)",pattern:/W/g,length:1,severity:r.Hq.Low,ruleCategory:"oxidation",color:r.D5.liability.oxidation,enabled:!0},{id:"glyco-nxst",name:"N-glycosylation",pattern:/N[^P][ST]/g,length:3,severity:r.Hq.High,ruleCategory:"glycosylation",color:r.D5.liability.glycosylation,enabled:!0},{id:"free-cys",name:"Free Cysteine",pattern:/C/g,length:1,severity:r.Hq.Info,ruleCategory:"freeCysteine",color:r.D5.liability.freeCysteine,enabled:!1}];function u(e,t){const i=e.getSplitted(t),n=new Array(i.length);for(let e=0;e<i.length;e++)n[e]=i.getCanonical(e);return n.join("")}const c={[r.Hq.High]:"High",[r.Hq.Medium]:"Medium",[r.Hq.Low]:"Low",[r.Hq.Info]:"Info"};function g(){const e=n.shell.tv?.dataFrame;if(!e)return void n.shell.warning("No table open");const t=e.columns.bySemTypeAll(o.SEMTYPE.MACROMOLECULE);if(0===t.length)return void n.shell.warning("No macromolecule columns found");const i=s.map(e=>({...e,pattern:new RegExp(e.pattern.source,"g")})),g=a.input.table("Table",{value:e}),m=a.input.column("Sequence",{table:e,value:t[0],filter:e=>e.semType===o.SEMTYPE.MACROMOLECULE}),y=[],p=a.divV([]);for(const e of i){const t=a.input.bool(e.name,{value:e.enabled,tooltipText:`Severity: ${c[e.severity]??e.severity}`});y.push({rule:e,input:t}),p.append(t.root)}const h=a.input.bool("Highlight in cell renderer",{value:!0}),b=a.input.bool("Create annotation column",{value:!0}),f=a.input.bool("Create summary count column",{value:!1}),v=a.dialog({title:"Scan Sequence Liabilities"}).add(a.inputs([g,m])).add(a.h3("Rules")).add(p).add(a.h3("Output")).add(a.inputs([h,b,f])).onOK(()=>{try{const t=m.value,a=l._package.seqHelper.getSeqHandler(t);for(const{rule:e,input:t}of y)e.enabled=t.value;const o=function(e,t,i){const n=i.filter(e=>e.enabled),a=t.posList,o=new Map,l=new Array(e.length);let d=0;for(let i=0;i<e.length;i++){const e=u(t,i),r=[];for(const t of n){let i;for(t.pattern.lastIndex=0;null!==(i=t.pattern.exec(e));)r.push({annotationId:t.id,positionIndex:i.index,positionName:i.index<a.length?a[i.index]:void 0,matchedMonomers:i[0]}),o.set(t.id,(o.get(t.id)??0)+1),d++}l[i]=r}return{annotations:n.filter(e=>o.has(e.id)).map(e=>({id:e.id,name:e.name,description:`${e.ruleCategory} liability pattern (${o.get(e.id)} hits)`,start:null,end:null,visualType:1===e.length?r.ao.Point:r.ao.Motif,category:r.eI.Liability,color:e.color,severity:e.severity,motifPattern:e.pattern.source,autoGenerated:!0})),rowData:l,totalHits:d}}(t,a,i);(b.value||h.value)&&function(e,t,i){const n=(0,d.Ln)(t).filter(e=>e.category!==r.eI.Liability);(0,d.fh)(t,[...n,...i.annotations]);const a=(0,d.Lz)(e,t);for(let e=0;e<i.rowData.length;e++){const t=(0,d.JG)(a,e)??[];(0,d.z5)(a,e,(0,d.bq)(t,i.rowData[e],!1,!0))}}(e,t,o),f.value&&function(e,t,i){const n=`${t.name}_liability_count`,a=i.rowData.map(e=>e.length),o=e.columns.addNewInt(n);for(let e=0;e<a.length;e++)o.set(e,a[e])}(e,t,o),n.shell.info(`Liability scan: ${o.totalHits} hits found across ${o.annotations.length} rules`),e.fireValuesChanged()}catch(e){n.shell.error(`Liability scan failed: ${e.message??e}`),console.error(e)}});v.show()}}}]);
1
+ "use strict";(self.webpackChunkbio=self.webpackChunkbio||[]).push([[422],{9422(e,t,i){i.d(t,{showLiabilityScannerDialog:()=>c});var n=i(4328),a=i(7389),o=i(6082),l=i(3785),r=i(4517),d=i(3736);const s=[{id:"deamid-ng",name:"Deamidation (NG)",pattern:/NG/g,length:2,severity:r.Hq.High,ruleCategory:"deamidation",color:r.D5.liability.deamidation,enabled:!0},{id:"deamid-ns",name:"Deamidation (NS)",pattern:/NS/g,length:2,severity:r.Hq.Medium,ruleCategory:"deamidation",color:r.D5.liability.deamidation,enabled:!0},{id:"deamid-na",name:"Deamidation (NA)",pattern:/NA/g,length:2,severity:r.Hq.Low,ruleCategory:"deamidation",color:r.D5.liability.deamidation,enabled:!0},{id:"deamid-nd",name:"Deamidation (ND)",pattern:/ND/g,length:2,severity:r.Hq.Low,ruleCategory:"deamidation",color:r.D5.liability.deamidation,enabled:!0},{id:"deamid-nt",name:"Deamidation (NT)",pattern:/NT/g,length:2,severity:r.Hq.Low,ruleCategory:"deamidation",color:r.D5.liability.deamidation,enabled:!0},{id:"isom-dg",name:"Isomerization (DG)",pattern:/DG/g,length:2,severity:r.Hq.High,ruleCategory:"isomerization",color:r.D5.liability.isomerization,enabled:!0},{id:"isom-ds",name:"Isomerization (DS)",pattern:/DS/g,length:2,severity:r.Hq.Medium,ruleCategory:"isomerization",color:r.D5.liability.isomerization,enabled:!0},{id:"oxid-m",name:"Oxidation (Met)",pattern:/M/g,length:1,severity:r.Hq.Medium,ruleCategory:"oxidation",color:r.D5.liability.oxidation,enabled:!0},{id:"oxid-w",name:"Oxidation (Trp)",pattern:/W/g,length:1,severity:r.Hq.Low,ruleCategory:"oxidation",color:r.D5.liability.oxidation,enabled:!0},{id:"glyco-nxst",name:"N-glycosylation",pattern:/N[^P][ST]/g,length:3,severity:r.Hq.High,ruleCategory:"glycosylation",color:r.D5.liability.glycosylation,enabled:!0},{id:"free-cys",name:"Free Cysteine",pattern:/C/g,length:1,severity:r.Hq.Info,ruleCategory:"freeCysteine",color:r.D5.liability.freeCysteine,enabled:!1}];function u(e,t){const i=e.getSplitted(t),n=new Array(i.length);for(let e=0;e<i.length;e++)n[e]=i.getOriginal(e);return n.join("")}const g={[r.Hq.High]:"High",[r.Hq.Medium]:"Medium",[r.Hq.Low]:"Low",[r.Hq.Info]:"Info"};function c(){const e=n.shell.tv?.dataFrame;if(!e)return void n.shell.warning("No table open");const t=e.columns.bySemTypeAll(o.SEMTYPE.MACROMOLECULE);if(0===t.length)return void n.shell.warning("No macromolecule columns found");const i=s.map(e=>({...e,pattern:new RegExp(e.pattern.source,"g")})),c=a.input.table("Table",{value:e}),m=a.input.column("Sequence",{table:e,value:t[0],filter:e=>e.semType===o.SEMTYPE.MACROMOLECULE}),y=[],p=a.divV([]);for(const e of i){const t=a.input.bool(e.name,{value:e.enabled,tooltipText:`Severity: ${g[e.severity]??e.severity}`});y.push({rule:e,input:t}),p.append(t.root)}const h=a.input.bool("Highlight in cell renderer",{value:!0}),b=a.input.bool("Create annotation column",{value:!0}),f=a.input.bool("Create summary count column",{value:!1}),v=a.dialog({title:"Scan Sequence Liabilities"}).add(a.inputs([c,m])).add(a.h3("Rules")).add(p).add(a.h3("Output")).add(a.inputs([h,b,f])).onOK(()=>{try{const t=m.value,a=l._package.seqHelper.getSeqHandler(t);for(const{rule:e,input:t}of y)e.enabled=t.value;const o=function(e,t,i){const n=i.filter(e=>e.enabled),a=t.posList,o=new Map,l=new Array(e.length);let d=0;for(let i=0;i<e.length;i++){const e=u(t,i),r=[];for(const t of n){let i;for(t.pattern.lastIndex=0;null!==(i=t.pattern.exec(e));)r.push({annotationId:t.id,positionIndex:i.index,positionName:i.index<a.length?a[i.index]:void 0,matchedMonomers:i[0]}),o.set(t.id,(o.get(t.id)??0)+1),d++}l[i]=r}return{annotations:n.filter(e=>o.has(e.id)).map(e=>({id:e.id,name:e.name,description:`${e.ruleCategory} liability pattern (${o.get(e.id)} hits)`,start:null,end:null,visualType:1===e.length?r.ao.Point:r.ao.Motif,category:r.eI.Liability,color:e.color,severity:e.severity,motifPattern:e.pattern.source,autoGenerated:!0})),rowData:l,totalHits:d}}(t,a,i);(b.value||h.value)&&function(e,t,i){const n=(0,d.Ln)(t).filter(e=>e.category!==r.eI.Liability);(0,d.fh)(t,[...n,...i.annotations]);const a=(0,d.Lz)(e,t);for(let e=0;e<i.rowData.length;e++){const t=(0,d.JG)(a,e)??[];(0,d.z5)(a,e,(0,d.bq)(t,i.rowData[e],!1,!0))}}(e,t,o),f.value&&function(e,t,i){const n=`${t.name}_liability_count`,a=i.rowData.map(e=>e.length),o=e.columns.addNewInt(n);for(let e=0;e<a.length;e++)o.set(e,a[e])}(e,t,o),n.shell.info(`Liability scan: ${o.totalHits} hits found across ${o.annotations.length} rules`),e.fireValuesChanged()}catch(e){n.shell.error(`Liability scan failed: ${e.message??e}`),console.error(e)}});v.show()}}}]);
2
2
  //# sourceMappingURL=422.js.map
package/dist/422.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"422.js","mappings":"gMA4BO,MAAMA,EAA2C,CACtD,CAACC,GAAI,YAAaC,KAAM,mBAAoBC,QAAS,MAAOC,OAAQ,EAAGC,SAAU,KAAkBC,KAAMC,aAAc,cAAeC,MAAO,KAAkBC,UAAUC,YAAaC,SAAS,GAC/L,CAACV,GAAI,YAAaC,KAAM,mBAAoBC,QAAS,MAAOC,OAAQ,EAAGC,SAAU,KAAkBO,OAAQL,aAAc,cAAeC,MAAO,KAAkBC,UAAUC,YAAaC,SAAS,GACjM,CAACV,GAAI,YAAaC,KAAM,mBAAoBC,QAAS,MAAOC,OAAQ,EAAGC,SAAU,KAAkBQ,IAAKN,aAAc,cAAeC,MAAO,KAAkBC,UAAUC,YAAaC,SAAS,GAC9L,CAACV,GAAI,YAAaC,KAAM,mBAAoBC,QAAS,MAAOC,OAAQ,EAAGC,SAAU,KAAkBQ,IAAKN,aAAc,cAAeC,MAAO,KAAkBC,UAAUC,YAAaC,SAAS,GAC9L,CAACV,GAAI,YAAaC,KAAM,mBAAoBC,QAAS,MAAOC,OAAQ,EAAGC,SAAU,KAAkBQ,IAAKN,aAAc,cAAeC,MAAO,KAAkBC,UAAUC,YAAaC,SAAS,GAC9L,CAACV,GAAI,UAAWC,KAAM,qBAAsBC,QAAS,MAAOC,OAAQ,EAAGC,SAAU,KAAkBC,KAAMC,aAAc,gBAAiBC,MAAO,KAAkBC,UAAUK,cAAeH,SAAS,GACnM,CAACV,GAAI,UAAWC,KAAM,qBAAsBC,QAAS,MAAOC,OAAQ,EAAGC,SAAU,KAAkBO,OAAQL,aAAc,gBAAiBC,MAAO,KAAkBC,UAAUK,cAAeH,SAAS,GACrM,CAACV,GAAI,SAAUC,KAAM,kBAAmBC,QAAS,KAAMC,OAAQ,EAAGC,SAAU,KAAkBO,OAAQL,aAAc,YAAaC,MAAO,KAAkBC,UAAUM,UAAWJ,SAAS,GACxL,CAACV,GAAI,SAAUC,KAAM,kBAAmBC,QAAS,KAAMC,OAAQ,EAAGC,SAAU,KAAkBQ,IAAKN,aAAc,YAAaC,MAAO,KAAkBC,UAAUM,UAAWJ,SAAS,GACrL,CAACV,GAAI,aAAcC,KAAM,kBAAmBC,QAAS,aAAcC,OAAQ,EAAGC,SAAU,KAAkBC,KAAMC,aAAc,gBAAiBC,MAAO,KAAkBC,UAAUO,cAAeL,SAAS,GAC1M,CAACV,GAAI,WAAYC,KAAM,gBAAiBC,QAAS,KAAMC,OAAQ,EAAGC,SAAU,KAAkBY,KAAMV,aAAc,eAAgBC,MAAO,KAAkBC,UAAUS,aAAcP,SAAS,IAI9L,SAASQ,EAAmBC,EAAiBC,GAC3C,MAAMC,EAAWF,EAAGG,YAAYF,GAC1BG,EAAkB,IAAIC,MAAMH,EAASlB,QAC3C,IAAK,IAAIsB,EAAI,EAAGA,EAAIJ,EAASlB,OAAQsB,IACnCF,EAAME,GAAKJ,EAASK,aAAaD,GACnC,OAAOF,EAAMI,KAAK,GACpB,CCtCA,MAAMC,EAAyC,CAC7C,CAAC,KAAkBvB,MAAO,OAC1B,CAAC,KAAkBM,QAAS,SAC5B,CAAC,KAAkBC,KAAM,MACzB,CAAC,KAAkBI,MAAO,QAGrB,SAASa,IACd,MAAMC,EAAK,QAAWC,IAAIC,UAC1B,IAAKF,EAEH,YADA,QAAWG,QAAQ,iBAIrB,MAAMC,EAAUJ,EAAGK,QAAQC,aAAa,UAAWC,eACnD,GAAuB,IAAnBH,EAAQ/B,OAEV,YADA,QAAW8B,QAAQ,kCAIrB,MAAMK,EAAQvC,EAAwBwC,IAAKC,IAAM,IAAKA,EAAGtC,QAAS,IAAIuC,OAAOD,EAAEtC,QAAQwC,OAAQ,QAEzFC,EAAa,QAASC,MAAM,QAAS,CAACC,MAAOf,IAC7CgB,EAAW,QAASC,OAAO,WAAY,CAC3CH,MAAOd,EAAIe,MAAOX,EAAQ,GAC1Bc,OAASC,GAAmBA,EAAIC,UAAY,UAAWb,gBAInDc,EAAoE,GACpEC,EAAW,OAAQ,IACzB,IAAK,MAAMC,KAAQf,EAAO,CACxB,MAAMgB,EAAQ,QAASC,KAAKF,EAAKpD,KAAM,CACrC4C,MAAOQ,EAAK3C,QACZ8C,YAAa,aAAa5B,EAAeyB,EAAKjD,WAAaiD,EAAKjD,aAElE+C,EAAWM,KAAK,CAACJ,OAAMK,MAAOJ,IAC9BF,EAASO,OAAOL,EAAMM,KACxB,CAEA,MAAMC,EAAiB,QAASN,KAAK,6BAA8B,CAACV,OAAO,IACrEiB,EAAgB,QAASP,KAAK,2BAA4B,CAACV,OAAO,IAClEkB,EAAe,QAASR,KAAK,8BAA+B,CAACV,OAAO,IAEpEmB,EAAS,SAAU,CAACC,MAAO,8BAC9BC,IAAI,SAAU,CAACvB,EAAYG,KAC3BoB,IAAI,KAAM,UACVA,IAAId,GACJc,IAAI,KAAM,WACVA,IAAI,SAAU,CAACL,EAAgBC,EAAeC,KAC9CI,KAAK,KACJ,IACE,MAAMC,EAAStB,EAASD,MAClB1B,EAAK,EAAAkD,SAASC,UAAUC,cAAcH,GAG5C,IAAK,MAAM,KAACf,EAAI,MAAEK,KAAUP,EAC1BE,EAAK3C,QAAUgD,EAAMb,MAEvB,MAAM2B,EDXP,SACLvB,EACA9B,EACAmB,GAEA,MAAMmC,EAAenC,EAAMU,OAAQR,GAAMA,EAAE9B,SACrCgE,EAAUvD,EAAGuD,QAGbC,EAAgB,IAAIC,IAEpBC,EAA+B,IAAIrD,MAAMyB,EAAI9C,QACnD,IAAI2E,EAAY,EAEhB,IAAK,IAAI1D,EAAS,EAAGA,EAAS6B,EAAI9C,OAAQiB,IAAU,CAClD,MAAM2D,EAAM7D,EAAmBC,EAAIC,GAC7B4D,EAA2B,GAEjC,IAAK,MAAM3B,KAAQoB,EAAc,CAG/B,IAAIQ,EACJ,IAFA5B,EAAKnD,QAAQgF,UAAY,EAEmB,QAApCD,EAAQ5B,EAAKnD,QAAQiF,KAAKJ,KAChCC,EAAKvB,KAAK,CACR2B,aAAc/B,EAAKrD,GACnBqF,cAAeJ,EAAMK,MACrBC,aAAcN,EAAMK,MAAQZ,EAAQvE,OAASuE,EAAQO,EAAMK,YAASE,EACpEC,gBAAiBR,EAAM,KAEzBN,EAAce,IAAIrC,EAAKrD,IAAK2E,EAAcgB,IAAItC,EAAKrD,KAAO,GAAK,GAC/D8E,GAEJ,CACAD,EAAQzD,GAAU4D,CACpB,CAmBA,MAAO,CAACY,YAhB6BnB,EAClCzB,OAAQR,GAAMmC,EAAckB,IAAIrD,EAAExC,KAClCuC,IAAKC,IAAM,CACVxC,GAAIwC,EAAExC,GACNC,KAAMuC,EAAEvC,KACR6F,YAAa,GAAGtD,EAAElC,mCAAmCqE,EAAcgB,IAAInD,EAAExC,YACzE+F,MAAO,KACPC,IAAK,KACLC,WAAyB,IAAbzD,EAAErC,OAAe,KAAqB+F,MAAQ,KAAqBC,MAC/EC,SAAU,KAAmBC,UAC7B9F,MAAOiC,EAAEjC,MACTH,SAAUoC,EAAEpC,SACZkG,aAAc9D,EAAEtC,QAAQwC,OACxB6D,eAAe,KAGE1B,UAASC,YAChC,CC3CuB0B,CAAgBpC,EAAQjD,EAAImB,IAEvCwB,EAAcjB,OAASgB,EAAehB,QD4C3C,SACLf,EACAsC,EACAI,GAGA,MAAMiC,GAAW,QAAqBrC,GACnCpB,OAAQ0D,GAAMA,EAAEN,WAAa,KAAmBC,YACnD,QAAqBjC,EAAQ,IAAIqC,KAAajC,EAAOoB,cAGrD,MAAMe,GAAW,QAA4B7E,EAAIsC,GACjD,IAAK,IAAI3C,EAAI,EAAGA,EAAI+C,EAAOK,QAAQ1E,OAAQsB,IAAK,CAC9C,MAAMmF,GAAe,QAAkBD,EAAUlF,IAAM,IACvD,QAAkBkF,EAAUlF,GAAG,QAAamF,EAAcpC,EAAOK,QAAQpD,IAAI,GAAO,GACtF,CACF,CC3DUoF,CAA0B/E,EAAIsC,EAAQI,GAEpCT,EAAalB,OD4DlB,SACLf,EACAsC,EACAI,GAEA,MAAMsC,EAAU,GAAG1C,EAAOnE,uBACpB8G,EAASvC,EAAOK,QAAQtC,IAAKyC,GAASA,EAAK7E,QAC3C8C,EAAMnB,EAAGK,QAAQ6E,UAAUF,GACjC,IAAK,IAAIrF,EAAI,EAAGA,EAAIsF,EAAO5G,OAAQsB,IACjCwB,EAAIyC,IAAIjE,EAAGsF,EAAOtF,GAEtB,CCtEUwF,CAA6BnF,EAAIsC,EAAQI,GAE3C,QAAW0C,KAAK,mBAAmB1C,EAAOM,+BAA+BN,EAAOoB,YAAYzF,gBAC5F2B,EAAGqF,mBACL,CAAE,MAAOC,GACP,QAAWC,MAAM,0BAA0BD,EAAIE,SAAWF,KAC1DG,QAAQF,MAAMD,EAChB,IAGJpD,EAAOwD,MACT,C","sources":["webpack://bio/./src/utils/annotations/liability-scanner.ts","webpack://bio/./src/utils/annotations/liability-scanner-ui.ts"],"sourcesContent":["/* eslint-disable max-len */\nimport * as DG from 'datagrok-api/dg';\n\nimport {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';\nimport {\n SeqAnnotation, SeqAnnotationHit, RowAnnotationData,\n AnnotationVisualType, AnnotationCategory, LiabilitySeverity,\n ANNOTATION_COLORS,\n} from '@datagrok-libraries/bio/src/utils/macromolecule/annotations';\nimport {\n getOrCreateAnnotationColumn, setColumnAnnotations, setRowAnnotations,\n getColumnAnnotations, getRowAnnotations, mergeRowHits,\n} from './annotation-manager';\n\n/** A single liability scanning rule. */\nexport interface LiabilityRule {\n id: string;\n name: string;\n pattern: RegExp;\n length: number;\n severity: LiabilitySeverity;\n /** Sub-category for grouping (e.g. \"deamidation\", \"oxidation\") */\n ruleCategory: string;\n color: string;\n enabled: boolean;\n}\n\n/** Built-in liability rules for antibody engineering. */\nexport const BUILTIN_LIABILITY_RULES: LiabilityRule[] = [\n {id: 'deamid-ng', name: 'Deamidation (NG)', pattern: /NG/g, length: 2, severity: LiabilitySeverity.High, ruleCategory: 'deamidation', color: ANNOTATION_COLORS.liability.deamidation, enabled: true},\n {id: 'deamid-ns', name: 'Deamidation (NS)', pattern: /NS/g, length: 2, severity: LiabilitySeverity.Medium, ruleCategory: 'deamidation', color: ANNOTATION_COLORS.liability.deamidation, enabled: true},\n {id: 'deamid-na', name: 'Deamidation (NA)', pattern: /NA/g, length: 2, severity: LiabilitySeverity.Low, ruleCategory: 'deamidation', color: ANNOTATION_COLORS.liability.deamidation, enabled: true},\n {id: 'deamid-nd', name: 'Deamidation (ND)', pattern: /ND/g, length: 2, severity: LiabilitySeverity.Low, ruleCategory: 'deamidation', color: ANNOTATION_COLORS.liability.deamidation, enabled: true},\n {id: 'deamid-nt', name: 'Deamidation (NT)', pattern: /NT/g, length: 2, severity: LiabilitySeverity.Low, ruleCategory: 'deamidation', color: ANNOTATION_COLORS.liability.deamidation, enabled: true},\n {id: 'isom-dg', name: 'Isomerization (DG)', pattern: /DG/g, length: 2, severity: LiabilitySeverity.High, ruleCategory: 'isomerization', color: ANNOTATION_COLORS.liability.isomerization, enabled: true},\n {id: 'isom-ds', name: 'Isomerization (DS)', pattern: /DS/g, length: 2, severity: LiabilitySeverity.Medium, ruleCategory: 'isomerization', color: ANNOTATION_COLORS.liability.isomerization, enabled: true},\n {id: 'oxid-m', name: 'Oxidation (Met)', pattern: /M/g, length: 1, severity: LiabilitySeverity.Medium, ruleCategory: 'oxidation', color: ANNOTATION_COLORS.liability.oxidation, enabled: true},\n {id: 'oxid-w', name: 'Oxidation (Trp)', pattern: /W/g, length: 1, severity: LiabilitySeverity.Low, ruleCategory: 'oxidation', color: ANNOTATION_COLORS.liability.oxidation, enabled: true},\n {id: 'glyco-nxst', name: 'N-glycosylation', pattern: /N[^P][ST]/g, length: 3, severity: LiabilitySeverity.High, ruleCategory: 'glycosylation', color: ANNOTATION_COLORS.liability.glycosylation, enabled: true},\n {id: 'free-cys', name: 'Free Cysteine', pattern: /C/g, length: 1, severity: LiabilitySeverity.Info, ruleCategory: 'freeCysteine', color: ANNOTATION_COLORS.liability.freeCysteine, enabled: false},\n];\n\n/** Extracts a canonical single-letter string from a sequence handler for a given row. */\nfunction getCanonicalString(sh: ISeqHandler, rowIdx: number): string {\n const splitted = sh.getSplitted(rowIdx);\n const chars: string[] = new Array(splitted.length);\n for (let i = 0; i < splitted.length; i++)\n chars[i] = splitted.getCanonical(i);\n return chars.join('');\n}\n\nexport interface ScanLiabilitiesResult {\n annotations: SeqAnnotation[];\n rowData: RowAnnotationData[];\n totalHits: number;\n}\n\n/** Scans all rows of a macromolecule column for liability motifs.\n * Returns column-level SeqAnnotation entries + per-row SeqAnnotationHit arrays. */\nexport function scanLiabilities(\n col: DG.Column<string>,\n sh: ISeqHandler,\n rules: LiabilityRule[],\n): ScanLiabilitiesResult {\n const enabledRules = rules.filter((r) => r.enabled);\n const posList = sh.posList;\n\n // Track which rules had hits\n const ruleHitCounts = new Map<string, number>();\n\n const rowData: RowAnnotationData[] = new Array(col.length);\n let totalHits = 0;\n\n for (let rowIdx = 0; rowIdx < col.length; rowIdx++) {\n const seq = getCanonicalString(sh, rowIdx);\n const hits: SeqAnnotationHit[] = [];\n\n for (const rule of enabledRules) {\n // Reset regex lastIndex for global patterns\n rule.pattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = rule.pattern.exec(seq)) !== null) {\n hits.push({\n annotationId: rule.id,\n positionIndex: match.index,\n positionName: match.index < posList.length ? posList[match.index] : undefined,\n matchedMonomers: match[0],\n });\n ruleHitCounts.set(rule.id, (ruleHitCounts.get(rule.id) ?? 0) + 1);\n totalHits++;\n }\n }\n rowData[rowIdx] = hits;\n }\n\n // Build column-level annotations only for rules that had hits\n const annotations: SeqAnnotation[] = enabledRules\n .filter((r) => ruleHitCounts.has(r.id))\n .map((r) => ({\n id: r.id,\n name: r.name,\n description: `${r.ruleCategory} liability pattern (${ruleHitCounts.get(r.id)} hits)`,\n start: null,\n end: null,\n visualType: r.length === 1 ? AnnotationVisualType.Point : AnnotationVisualType.Motif,\n category: AnnotationCategory.Liability,\n color: r.color,\n severity: r.severity,\n motifPattern: r.pattern.source,\n autoGenerated: true,\n }));\n\n return {annotations, rowData, totalHits};\n}\n\n/** Applies liability scan results to the DataFrame (writes tags + companion column). */\nexport function applyLiabilityScanResults(\n df: DG.DataFrame,\n seqCol: DG.Column<string>,\n result: ScanLiabilitiesResult,\n): void {\n // Merge with existing annotations, removing old liability entries\n const existing = getColumnAnnotations(seqCol)\n .filter((a) => a.category !== AnnotationCategory.Liability);\n setColumnAnnotations(seqCol, [...existing, ...result.annotations]);\n\n // Write per-row data to hidden companion column, preserving region hits from numbering\n const annotCol = getOrCreateAnnotationColumn(df, seqCol);\n for (let i = 0; i < result.rowData.length; i++) {\n const existingHits = getRowAnnotations(annotCol, i) ?? [];\n setRowAnnotations(annotCol, i, mergeRowHits(existingHits, result.rowData[i], false, true));\n }\n}\n\n/** Creates a liability summary count column (total hits per row). */\nexport function createLiabilitySummaryColumn(\n df: DG.DataFrame,\n seqCol: DG.Column<string>,\n result: ScanLiabilitiesResult,\n): DG.Column<number> {\n const colName = `${seqCol.name}_liability_count`;\n const counts = result.rowData.map((hits) => hits.length);\n const col = df.columns.addNewInt(colName);\n for (let i = 0; i < counts.length; i++)\n col.set(i, counts[i]);\n return col;\n}\n","import * as grok from 'datagrok-api/grok';\nimport * as ui from 'datagrok-api/ui';\nimport * as DG from 'datagrok-api/dg';\n\nimport {_package} from '../../package';\nimport {\n BUILTIN_LIABILITY_RULES, LiabilityRule, scanLiabilities,\n applyLiabilityScanResults, createLiabilitySummaryColumn,\n} from './liability-scanner';\nimport {LiabilitySeverity} from '@datagrok-libraries/bio/src/utils/macromolecule/annotations';\n\nconst severityLabels: Record<string, string> = {\n [LiabilitySeverity.High]: 'High',\n [LiabilitySeverity.Medium]: 'Medium',\n [LiabilitySeverity.Low]: 'Low',\n [LiabilitySeverity.Info]: 'Info',\n};\n\nexport function showLiabilityScannerDialog(): void {\n const df = grok.shell.tv?.dataFrame;\n if (!df) {\n grok.shell.warning('No table open');\n return;\n }\n\n const seqCols = df.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);\n if (seqCols.length === 0) {\n grok.shell.warning('No macromolecule columns found');\n return;\n }\n\n const rules = BUILTIN_LIABILITY_RULES.map((r) => ({...r, pattern: new RegExp(r.pattern.source, 'g')}));\n\n const tableInput = ui.input.table('Table', {value: df});\n const seqInput = ui.input.column('Sequence', {\n table: df, value: seqCols[0],\n filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE,\n });\n\n // Rule checkboxes\n const ruleChecks: {rule: LiabilityRule; input: DG.InputBase<boolean>}[] = [];\n const rulesDiv = ui.divV([]);\n for (const rule of rules) {\n const check = ui.input.bool(rule.name, {\n value: rule.enabled,\n tooltipText: `Severity: ${severityLabels[rule.severity] ?? rule.severity}`,\n });\n ruleChecks.push({rule, input: check});\n rulesDiv.append(check.root);\n }\n\n const highlightInput = ui.input.bool('Highlight in cell renderer', {value: true});\n const annotColInput = ui.input.bool('Create annotation column', {value: true});\n const summaryInput = ui.input.bool('Create summary count column', {value: false});\n\n const dialog = ui.dialog({title: 'Scan Sequence Liabilities'})\n .add(ui.inputs([tableInput, seqInput]))\n .add(ui.h3('Rules'))\n .add(rulesDiv)\n .add(ui.h3('Output'))\n .add(ui.inputs([highlightInput, annotColInput, summaryInput]))\n .onOK(() => {\n try {\n const seqCol = seqInput.value!;\n const sh = _package.seqHelper.getSeqHandler(seqCol);\n\n // Apply checkbox state\n for (const {rule, input} of ruleChecks)\n rule.enabled = input.value;\n\n const result = scanLiabilities(seqCol, sh, rules);\n\n if (annotColInput.value || highlightInput.value)\n applyLiabilityScanResults(df, seqCol, result);\n\n if (summaryInput.value)\n createLiabilitySummaryColumn(df, seqCol, result);\n\n grok.shell.info(`Liability scan: ${result.totalHits} hits found across ${result.annotations.length} rules`);\n df.fireValuesChanged();\n } catch (err: any) {\n grok.shell.error(`Liability scan failed: ${err.message ?? err}`);\n console.error(err);\n }\n });\n\n dialog.show();\n}\n"],"names":["BUILTIN_LIABILITY_RULES","id","name","pattern","length","severity","High","ruleCategory","color","liability","deamidation","enabled","Medium","Low","isomerization","oxidation","glycosylation","Info","freeCysteine","getCanonicalString","sh","rowIdx","splitted","getSplitted","chars","Array","i","getCanonical","join","severityLabels","showLiabilityScannerDialog","df","tv","dataFrame","warning","seqCols","columns","bySemTypeAll","MACROMOLECULE","rules","map","r","RegExp","source","tableInput","table","value","seqInput","column","filter","col","semType","ruleChecks","rulesDiv","rule","check","bool","tooltipText","push","input","append","root","highlightInput","annotColInput","summaryInput","dialog","title","add","onOK","seqCol","_package","seqHelper","getSeqHandler","result","enabledRules","posList","ruleHitCounts","Map","rowData","totalHits","seq","hits","match","lastIndex","exec","annotationId","positionIndex","index","positionName","undefined","matchedMonomers","set","get","annotations","has","description","start","end","visualType","Point","Motif","category","Liability","motifPattern","autoGenerated","scanLiabilities","existing","a","annotCol","existingHits","applyLiabilityScanResults","colName","counts","addNewInt","createLiabilitySummaryColumn","info","fireValuesChanged","err","error","message","console","show"],"sourceRoot":""}
1
+ {"version":3,"file":"422.js","mappings":"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","sources":["webpack://bio/./src/utils/annotations/liability-scanner.ts","webpack://bio/./src/utils/annotations/liability-scanner-ui.ts"],"sourcesContent":["/* eslint-disable max-len */\nimport * as DG from 'datagrok-api/dg';\n\nimport {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';\nimport {\n SeqAnnotation, SeqAnnotationHit, RowAnnotationData,\n AnnotationVisualType, AnnotationCategory, LiabilitySeverity,\n ANNOTATION_COLORS,\n} from '@datagrok-libraries/bio/src/utils/macromolecule/annotations';\nimport {\n getOrCreateAnnotationColumn, setColumnAnnotations, setRowAnnotations,\n getColumnAnnotations, getRowAnnotations, mergeRowHits,\n} from './annotation-manager';\n\n/** A single liability scanning rule. */\nexport interface LiabilityRule {\n id: string;\n name: string;\n pattern: RegExp;\n length: number;\n severity: LiabilitySeverity;\n /** Sub-category for grouping (e.g. \"deamidation\", \"oxidation\") */\n ruleCategory: string;\n color: string;\n enabled: boolean;\n}\n\n/** Built-in liability rules for antibody engineering. */\nexport const BUILTIN_LIABILITY_RULES: LiabilityRule[] = [\n {id: 'deamid-ng', name: 'Deamidation (NG)', pattern: /NG/g, length: 2, severity: LiabilitySeverity.High, ruleCategory: 'deamidation', color: ANNOTATION_COLORS.liability.deamidation, enabled: true},\n {id: 'deamid-ns', name: 'Deamidation (NS)', pattern: /NS/g, length: 2, severity: LiabilitySeverity.Medium, ruleCategory: 'deamidation', color: ANNOTATION_COLORS.liability.deamidation, enabled: true},\n {id: 'deamid-na', name: 'Deamidation (NA)', pattern: /NA/g, length: 2, severity: LiabilitySeverity.Low, ruleCategory: 'deamidation', color: ANNOTATION_COLORS.liability.deamidation, enabled: true},\n {id: 'deamid-nd', name: 'Deamidation (ND)', pattern: /ND/g, length: 2, severity: LiabilitySeverity.Low, ruleCategory: 'deamidation', color: ANNOTATION_COLORS.liability.deamidation, enabled: true},\n {id: 'deamid-nt', name: 'Deamidation (NT)', pattern: /NT/g, length: 2, severity: LiabilitySeverity.Low, ruleCategory: 'deamidation', color: ANNOTATION_COLORS.liability.deamidation, enabled: true},\n {id: 'isom-dg', name: 'Isomerization (DG)', pattern: /DG/g, length: 2, severity: LiabilitySeverity.High, ruleCategory: 'isomerization', color: ANNOTATION_COLORS.liability.isomerization, enabled: true},\n {id: 'isom-ds', name: 'Isomerization (DS)', pattern: /DS/g, length: 2, severity: LiabilitySeverity.Medium, ruleCategory: 'isomerization', color: ANNOTATION_COLORS.liability.isomerization, enabled: true},\n {id: 'oxid-m', name: 'Oxidation (Met)', pattern: /M/g, length: 1, severity: LiabilitySeverity.Medium, ruleCategory: 'oxidation', color: ANNOTATION_COLORS.liability.oxidation, enabled: true},\n {id: 'oxid-w', name: 'Oxidation (Trp)', pattern: /W/g, length: 1, severity: LiabilitySeverity.Low, ruleCategory: 'oxidation', color: ANNOTATION_COLORS.liability.oxidation, enabled: true},\n {id: 'glyco-nxst', name: 'N-glycosylation', pattern: /N[^P][ST]/g, length: 3, severity: LiabilitySeverity.High, ruleCategory: 'glycosylation', color: ANNOTATION_COLORS.liability.glycosylation, enabled: true},\n {id: 'free-cys', name: 'Free Cysteine', pattern: /C/g, length: 1, severity: LiabilitySeverity.Info, ruleCategory: 'freeCysteine', color: ANNOTATION_COLORS.liability.freeCysteine, enabled: false},\n];\n\n/** Extracts a canonical single-letter string from a sequence handler for a given row. */\nfunction getCanonicalString(sh: ISeqHandler, rowIdx: number): string {\n const splitted = sh.getSplitted(rowIdx);\n const chars: string[] = new Array(splitted.length);\n for (let i = 0; i < splitted.length; i++)\n chars[i] = splitted.getOriginal(i);\n return chars.join('');\n}\n\nexport interface ScanLiabilitiesResult {\n annotations: SeqAnnotation[];\n rowData: RowAnnotationData[];\n totalHits: number;\n}\n\n/** Scans all rows of a macromolecule column for liability motifs.\n * Returns column-level SeqAnnotation entries + per-row SeqAnnotationHit arrays. */\nexport function scanLiabilities(\n col: DG.Column<string>,\n sh: ISeqHandler,\n rules: LiabilityRule[],\n): ScanLiabilitiesResult {\n const enabledRules = rules.filter((r) => r.enabled);\n const posList = sh.posList;\n\n // Track which rules had hits\n const ruleHitCounts = new Map<string, number>();\n\n const rowData: RowAnnotationData[] = new Array(col.length);\n let totalHits = 0;\n\n for (let rowIdx = 0; rowIdx < col.length; rowIdx++) {\n const seq = getCanonicalString(sh, rowIdx);\n const hits: SeqAnnotationHit[] = [];\n\n for (const rule of enabledRules) {\n // Reset regex lastIndex for global patterns\n rule.pattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = rule.pattern.exec(seq)) !== null) {\n hits.push({\n annotationId: rule.id,\n positionIndex: match.index,\n positionName: match.index < posList.length ? posList[match.index] : undefined,\n matchedMonomers: match[0],\n });\n ruleHitCounts.set(rule.id, (ruleHitCounts.get(rule.id) ?? 0) + 1);\n totalHits++;\n }\n }\n rowData[rowIdx] = hits;\n }\n\n // Build column-level annotations only for rules that had hits\n const annotations: SeqAnnotation[] = enabledRules\n .filter((r) => ruleHitCounts.has(r.id))\n .map((r) => ({\n id: r.id,\n name: r.name,\n description: `${r.ruleCategory} liability pattern (${ruleHitCounts.get(r.id)} hits)`,\n start: null,\n end: null,\n visualType: r.length === 1 ? AnnotationVisualType.Point : AnnotationVisualType.Motif,\n category: AnnotationCategory.Liability,\n color: r.color,\n severity: r.severity,\n motifPattern: r.pattern.source,\n autoGenerated: true,\n }));\n\n return {annotations, rowData, totalHits};\n}\n\n/** Applies liability scan results to the DataFrame (writes tags + companion column). */\nexport function applyLiabilityScanResults(\n df: DG.DataFrame,\n seqCol: DG.Column<string>,\n result: ScanLiabilitiesResult,\n): void {\n // Merge with existing annotations, removing old liability entries\n const existing = getColumnAnnotations(seqCol)\n .filter((a) => a.category !== AnnotationCategory.Liability);\n setColumnAnnotations(seqCol, [...existing, ...result.annotations]);\n\n // Write per-row data to hidden companion column, preserving region hits from numbering\n const annotCol = getOrCreateAnnotationColumn(df, seqCol);\n for (let i = 0; i < result.rowData.length; i++) {\n const existingHits = getRowAnnotations(annotCol, i) ?? [];\n setRowAnnotations(annotCol, i, mergeRowHits(existingHits, result.rowData[i], false, true));\n }\n}\n\n/** Creates a liability summary count column (total hits per row). */\nexport function createLiabilitySummaryColumn(\n df: DG.DataFrame,\n seqCol: DG.Column<string>,\n result: ScanLiabilitiesResult,\n): DG.Column<number> {\n const colName = `${seqCol.name}_liability_count`;\n const counts = result.rowData.map((hits) => hits.length);\n const col = df.columns.addNewInt(colName);\n for (let i = 0; i < counts.length; i++)\n col.set(i, counts[i]);\n return col;\n}\n","import * as grok from 'datagrok-api/grok';\nimport * as ui from 'datagrok-api/ui';\nimport * as DG from 'datagrok-api/dg';\n\nimport {_package} from '../../package';\nimport {\n BUILTIN_LIABILITY_RULES, LiabilityRule, scanLiabilities,\n applyLiabilityScanResults, createLiabilitySummaryColumn,\n} from './liability-scanner';\nimport {LiabilitySeverity} from '@datagrok-libraries/bio/src/utils/macromolecule/annotations';\n\nconst severityLabels: Record<string, string> = {\n [LiabilitySeverity.High]: 'High',\n [LiabilitySeverity.Medium]: 'Medium',\n [LiabilitySeverity.Low]: 'Low',\n [LiabilitySeverity.Info]: 'Info',\n};\n\nexport function showLiabilityScannerDialog(): void {\n const df = grok.shell.tv?.dataFrame;\n if (!df) {\n grok.shell.warning('No table open');\n return;\n }\n\n const seqCols = df.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);\n if (seqCols.length === 0) {\n grok.shell.warning('No macromolecule columns found');\n return;\n }\n\n const rules = BUILTIN_LIABILITY_RULES.map((r) => ({...r, pattern: new RegExp(r.pattern.source, 'g')}));\n\n const tableInput = ui.input.table('Table', {value: df});\n const seqInput = ui.input.column('Sequence', {\n table: df, value: seqCols[0],\n filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE,\n });\n\n // Rule checkboxes\n const ruleChecks: {rule: LiabilityRule; input: DG.InputBase<boolean>}[] = [];\n const rulesDiv = ui.divV([]);\n for (const rule of rules) {\n const check = ui.input.bool(rule.name, {\n value: rule.enabled,\n tooltipText: `Severity: ${severityLabels[rule.severity] ?? rule.severity}`,\n });\n ruleChecks.push({rule, input: check});\n rulesDiv.append(check.root);\n }\n\n const highlightInput = ui.input.bool('Highlight in cell renderer', {value: true});\n const annotColInput = ui.input.bool('Create annotation column', {value: true});\n const summaryInput = ui.input.bool('Create summary count column', {value: false});\n\n const dialog = ui.dialog({title: 'Scan Sequence Liabilities'})\n .add(ui.inputs([tableInput, seqInput]))\n .add(ui.h3('Rules'))\n .add(rulesDiv)\n .add(ui.h3('Output'))\n .add(ui.inputs([highlightInput, annotColInput, summaryInput]))\n .onOK(() => {\n try {\n const seqCol = seqInput.value!;\n const sh = _package.seqHelper.getSeqHandler(seqCol);\n\n // Apply checkbox state\n for (const {rule, input} of ruleChecks)\n rule.enabled = input.value;\n\n const result = scanLiabilities(seqCol, sh, rules);\n\n if (annotColInput.value || highlightInput.value)\n applyLiabilityScanResults(df, seqCol, result);\n\n if (summaryInput.value)\n createLiabilitySummaryColumn(df, seqCol, result);\n\n grok.shell.info(`Liability scan: ${result.totalHits} hits found across ${result.annotations.length} rules`);\n df.fireValuesChanged();\n } catch (err: any) {\n grok.shell.error(`Liability scan failed: ${err.message ?? err}`);\n console.error(err);\n }\n });\n\n dialog.show();\n}\n"],"names":["BUILTIN_LIABILITY_RULES","id","name","pattern","length","severity","High","ruleCategory","color","liability","deamidation","enabled","Medium","Low","isomerization","oxidation","glycosylation","Info","freeCysteine","getCanonicalString","sh","rowIdx","splitted","getSplitted","chars","Array","i","getOriginal","join","severityLabels","showLiabilityScannerDialog","df","tv","dataFrame","warning","seqCols","columns","bySemTypeAll","MACROMOLECULE","rules","map","r","RegExp","source","tableInput","table","value","seqInput","column","filter","col","semType","ruleChecks","rulesDiv","rule","check","bool","tooltipText","push","input","append","root","highlightInput","annotColInput","summaryInput","dialog","title","add","onOK","seqCol","_package","seqHelper","getSeqHandler","result","enabledRules","posList","ruleHitCounts","Map","rowData","totalHits","seq","hits","match","lastIndex","exec","annotationId","positionIndex","index","positionName","undefined","matchedMonomers","set","get","annotations","has","description","start","end","visualType","Point","Motif","category","Liability","motifPattern","autoGenerated","scanLiabilities","existing","a","annotCol","existingHits","applyLiabilityScanResults","colName","counts","addNewInt","createLiabilitySummaryColumn","info","fireValuesChanged","err","error","message","console","show"],"sourceRoot":""}