@platforma-open/milaboratories.antibody-variant-designer.block 1.0.0 → 1.1.0

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/dist/index.js CHANGED
@@ -12727,55 +12727,68 @@ const ErrorShape = objectType({
12727
12727
  });
12728
12728
  //#endregion
12729
12729
  //#region ../model/dist/index.js
12730
- const dataModel = new DataModelBuilder().from("v1").init(() => ({
12731
- dataset: void 0,
12730
+ /** Every scalar `BlockData` field's default value, in one place: `.init()`
12731
+ * seeds a new project from it, `.args()` falls back to it for a project
12732
+ * persisted before a field existed, and the settings panel shows it in the
12733
+ * field the operator has not touched. */
12734
+ const BLOCK_DATA_DEFAULTS = {
12735
+ runMode: "liabilities",
12732
12736
  rsasaBuriedCutoff: .075,
12733
12737
  actOnFixability: ["fixable", "easily_fixable"],
12734
- maxEditsPerVariant: 5,
12735
- frConfThresh: 4,
12736
- cdrConfThresh: 6,
12737
- variantsPerParent: 10,
12738
+ maxLiabilityEdits: 10,
12739
+ maxFrameworkEdits: 20,
12740
+ frConfidenceThreshold: 4,
12741
+ cdrConfidenceThreshold: 6,
12742
+ variantsPerParent: 100,
12738
12743
  candidateResiduesPerPosition: 3,
12744
+ structuralWeight: 1,
12745
+ objectiveWeight: 1,
12746
+ nonHumanPriorMargin: .05,
12747
+ maxNewLiabilities: 0,
12748
+ humanizationIgnoredLiabilities: [],
12739
12749
  lowToleranceFloor: 3,
12740
- epistasisRescoreTopK: 20,
12750
+ epistasisRescoreTopK: 20
12751
+ };
12752
+ const dataModel = new DataModelBuilder().from("v1").init(() => ({
12753
+ dataset: void 0,
12754
+ ...BLOCK_DATA_DEFAULTS,
12741
12755
  variantsTableState: createPlDataTableStateV2(),
12742
- liabilitiesTableState: createPlDataTableStateV2()
12756
+ liabilitiesTableState: createPlDataTableStateV2(),
12757
+ alignmentModel: {}
12743
12758
  }));
12744
12759
  const STRUCTURE_PDB_COLUMN = "pl7.app/structure/pdb";
12745
12760
  const LEAD_SELECTION_COLUMN = "pl7.app/lead-selection";
12746
12761
  function isStructuresDataset(spec) {
12747
12762
  return spec.kind === "PColumn" && spec.name === STRUCTURE_PDB_COLUMN && spec.annotations?.["pl7.app/isAnchor"] === "true";
12748
12763
  }
12749
- /** One step's skip TSV: `clonotypeKey \t reason \t detail`, header row
12750
- * first, reason and detail empty when that clonotype passed. Absent and
12751
- * empty are equivalent to the reduce below, so only non-empty-reason rows
12752
- * are kept. */
12753
- function parseSkipRows(tsv) {
12764
+ const DEFAULT_REJECTION_OBJECTIVE = "liability";
12765
+ function parseRejectionRows(tsv) {
12754
12766
  const rows = /* @__PURE__ */ new Map();
12755
12767
  for (const line of tsv.split("\n").slice(1)) {
12756
12768
  if (line.length === 0) continue;
12757
- const [clonotypeKey, reason, detail] = line.split(" ");
12758
- if (reason) rows.set(clonotypeKey, {
12769
+ const [clonotypeKey, reason, detail, rejectedType, objective] = line.split(" ");
12770
+ if (reason) rows.set(`${clonotypeKey}\t${objective || DEFAULT_REJECTION_OBJECTIVE}`, {
12759
12771
  reason,
12760
- detail: detail ?? ""
12772
+ detail: detail ?? "",
12773
+ rejectedType: rejectedType || "parent",
12774
+ objective: objective || DEFAULT_REJECTION_OBJECTIVE
12761
12775
  });
12762
12776
  }
12763
12777
  return rows;
12764
12778
  }
12765
- /** Per clonotype, the first non-empty reason (and its detail) in step
12766
- * order: index-and-scan, then read-tolerance, then build-variants. A
12767
- * clonotype named in more than one file is kept once, at its earliest
12768
- * step. */
12769
- function reduceSkips(stepSkipTsvs) {
12770
- const byClonotype = /* @__PURE__ */ new Map();
12771
- for (const tsv of stepSkipTsvs) for (const [clonotypeKey, row] of parseSkipRows(tsv)) if (!byClonotype.has(clonotypeKey)) byClonotype.set(clonotypeKey, row);
12772
- return byClonotype;
12773
- }
12774
- function reduceSkippedClonotypes(stepSkipTsvs) {
12775
- return [...reduceSkips(stepSkipTsvs)].map(([clonotypeKey, { reason, detail }]) => ({
12776
- clonotypeKey,
12777
- reason,
12778
- detail
12779
+ /** Per (clonotype, objective) pair, the first non-empty reason (and its detail) in step
12780
+ * order: index-and-scan, then read-tolerance, then build-variants. A pair named in more than
12781
+ * one file is kept once, at its earliest step — a parent named by two objectives keeps both
12782
+ * rows, and one named twice by the same objective keeps only its earliest. */
12783
+ function reduceRejections(stepRejectionTsvs) {
12784
+ const byPair = /* @__PURE__ */ new Map();
12785
+ for (const tsv of stepRejectionTsvs) for (const [pairKey, row] of parseRejectionRows(tsv)) if (!byPair.has(pairKey)) byPair.set(pairKey, row);
12786
+ return byPair;
12787
+ }
12788
+ function reduceRejectedClonotypes(stepRejectionTsvs) {
12789
+ return [...reduceRejections(stepRejectionTsvs)].map(([pairKey, row]) => ({
12790
+ clonotypeKey: pairKey.slice(0, pairKey.lastIndexOf(" ")),
12791
+ ...row
12779
12792
  }));
12780
12793
  }
12781
12794
  function tableFromAccessorOutput(ctx, outputName, tableState) {
@@ -12784,31 +12797,47 @@ function tableFromAccessorOutput(ctx, outputName, tableState) {
12784
12797
  const provider = AccessorColumnsProvider(acc);
12785
12798
  const snapshots = provider.getColumns();
12786
12799
  if (snapshots.length === 0) return void 0;
12787
- const anchorSpec = (snapshots.find((s) => s.getSpec().name !== "pl7.app/label") ?? snapshots[0]).getSpec();
12800
+ const anchorSpec = (snapshots.find((s) => s.getSpec().name !== "pl7.app/label" && s.getSpec().annotations?.["pl7.app/isLinkerColumn"] !== "true") ?? snapshots[0]).getSpec();
12788
12801
  return createPlDataTableV3(ctx, {
12789
12802
  columns: {
12790
12803
  sources: [provider],
12791
12804
  anchors: { main: anchorSpec },
12792
12805
  selector: {
12793
12806
  mode: "enrichment",
12794
- maxHops: 0
12807
+ maxHops: 1
12795
12808
  }
12796
12809
  },
12797
12810
  tableState
12798
12811
  });
12799
12812
  }
12813
+ /** The alignment group's PColumns, or undefined when the result was computed by
12814
+ * a build that did not yet write this output. */
12815
+ function alignmentColumns(ctx) {
12816
+ return ctx.outputs?.resolve({
12817
+ field: "alignmentData",
12818
+ assertFieldType: "Input",
12819
+ allowPermanentAbsence: true
12820
+ })?.getPColumns();
12821
+ }
12800
12822
  const platforma$1 = BlockModelV3.create(dataModel).args((data) => {
12801
12823
  if (!data.dataset?.primary?.column) throw new Error("Pick a 3D structures dataset");
12802
12824
  return {
12803
12825
  primaryRef: data.dataset.primary,
12804
12826
  subsetRef: data.dataset.primary.filter,
12827
+ runMode: data.runMode ?? BLOCK_DATA_DEFAULTS.runMode,
12805
12828
  rsasaBuriedCutoff: data.rsasaBuriedCutoff,
12806
12829
  actOnFixability: [...new Set(data.actOnFixability)].sort(),
12807
- maxEditsPerVariant: data.maxEditsPerVariant,
12808
- frConfThresh: data.frConfThresh,
12809
- cdrConfThresh: data.cdrConfThresh,
12830
+ maxLiabilityEdits: data.maxLiabilityEdits ?? data.maxEditsPerVariant ?? BLOCK_DATA_DEFAULTS.maxLiabilityEdits,
12831
+ maxFrameworkEdits: data.maxFrameworkEdits ?? BLOCK_DATA_DEFAULTS.maxFrameworkEdits,
12832
+ frConfidenceThreshold: data.frConfidenceThreshold ?? data.frConfThresh ?? BLOCK_DATA_DEFAULTS.frConfidenceThreshold,
12833
+ cdrConfidenceThreshold: data.cdrConfidenceThreshold ?? data.cdrConfThresh ?? BLOCK_DATA_DEFAULTS.cdrConfidenceThreshold,
12810
12834
  variantsPerParent: data.variantsPerParent,
12811
12835
  candidateResiduesPerPosition: data.candidateResiduesPerPosition,
12836
+ structuralWeight: data.structuralWeight ?? data.wStruct ?? BLOCK_DATA_DEFAULTS.structuralWeight,
12837
+ objectiveWeight: data.objectiveWeight ?? data.wObj ?? BLOCK_DATA_DEFAULTS.objectiveWeight,
12838
+ nonHumanPriorMargin: data.nonHumanPriorMargin ?? BLOCK_DATA_DEFAULTS.nonHumanPriorMargin,
12839
+ maxNewLiabilities: data.maxNewLiabilities ?? BLOCK_DATA_DEFAULTS.maxNewLiabilities,
12840
+ humanizationIgnoredLiabilities: [...new Set(data.humanizationIgnoredLiabilities ?? BLOCK_DATA_DEFAULTS.humanizationIgnoredLiabilities)].sort(),
12812
12841
  lowToleranceFloor: data.lowToleranceFloor,
12813
12842
  epistasisRescoreTopK: data.epistasisRescoreTopK,
12814
12843
  indexAndScanCpu: data.indexAndScanCpu,
@@ -12837,15 +12866,20 @@ const platforma$1 = BlockModelV3.create(dataModel).args((data) => {
12837
12866
  case "stale-selection": return "The selected structures dataset is no longer available. Pick it again, or add a 3D Structure Prediction block upstream.";
12838
12867
  default: return cause;
12839
12868
  }
12840
- }).outputWithStatus("variantsTable", (ctx) => tableFromAccessorOutput(ctx, "variantsData", ctx.data.variantsTableState)).outputWithStatus("liabilitiesTable", (ctx) => tableFromAccessorOutput(ctx, "liabilitiesData", ctx.data.liabilitiesTableState)).output("synthesisCsv", (ctx) => ctx.outputs?.resolve("synthesisCsv")?.getRemoteFileHandle()).output("skippedClonotypes", (ctx) => {
12841
- const liabilitiesSkip = ctx.outputs?.resolve("liabilitiesSkip")?.getDataAsString();
12842
- const toleranceSkip = ctx.outputs?.resolve("toleranceSkip")?.getDataAsString();
12843
- const variantsSkip = ctx.outputs?.resolve("variantsSkip")?.getDataAsString();
12844
- if (liabilitiesSkip === void 0 || toleranceSkip === void 0 || variantsSkip === void 0) return;
12845
- return reduceSkippedClonotypes([
12846
- liabilitiesSkip,
12847
- toleranceSkip,
12848
- variantsSkip
12869
+ }).outputWithStatus("variantsTable", (ctx) => tableFromAccessorOutput(ctx, "variantsData", ctx.data.variantsTableState)).outputWithStatus("liabilitiesTable", (ctx) => tableFromAccessorOutput(ctx, "liabilitiesData", ctx.data.liabilitiesTableState)).output("synthesisCsv", (ctx) => ctx.outputs?.resolve("synthesisCsv")?.getRemoteFileHandle()).outputWithStatus("rejectedClonotypes", (ctx) => {
12870
+ const rejectedTsv = (name) => ctx.outputs?.resolve({
12871
+ field: name,
12872
+ assertFieldType: "Input",
12873
+ allowPermanentAbsence: true
12874
+ })?.getDataAsString();
12875
+ const liabilitiesRejected = rejectedTsv("liabilitiesRejected");
12876
+ const toleranceRejected = rejectedTsv("toleranceRejected");
12877
+ const variantsRejected = rejectedTsv("variantsRejected");
12878
+ if (liabilitiesRejected === void 0 || toleranceRejected === void 0 || variantsRejected === void 0) return;
12879
+ return reduceRejectedClonotypes([
12880
+ liabilitiesRejected,
12881
+ toleranceRejected,
12882
+ variantsRejected
12849
12883
  ]);
12850
12884
  }).output("clonotypeLabelsPf", (ctx) => {
12851
12885
  const pCols = ctx.outputs?.resolve("liabilitiesData")?.getPColumns();
@@ -12855,6 +12889,12 @@ const platforma$1 = BlockModelV3.create(dataModel).args((data) => {
12855
12889
  const axis = (ctx.outputs?.resolve("liabilitiesData")?.getPColumns())?.[0]?.spec.axesSpec[0];
12856
12890
  if (axis === void 0) return void 0;
12857
12891
  return getAxisId(axis);
12892
+ }).output("alignmentPf", (ctx) => {
12893
+ const pCols = alignmentColumns(ctx);
12894
+ if (pCols === void 0 || pCols.length === 0) return void 0;
12895
+ return ctx.createPFrame(pCols);
12896
+ }).output("alignmentAxisSpec", (ctx) => {
12897
+ return alignmentColumns(ctx)?.[0]?.spec.axesSpec[0];
12858
12898
  }).sections(() => [
12859
12899
  {
12860
12900
  type: "link",
@@ -12868,8 +12908,8 @@ const platforma$1 = BlockModelV3.create(dataModel).args((data) => {
12868
12908
  },
12869
12909
  {
12870
12910
  type: "link",
12871
- href: "/skipped",
12872
- label: "Skipped"
12911
+ href: "/rejection-causes",
12912
+ label: "Objective Findings"
12873
12913
  }
12874
12914
  ]).done();
12875
12915
  //#endregion