@platforma-sdk/model 1.30.3 → 1.30.21

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/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const PlatformaSDKVersion = "1.30.3";
1
+ export declare const PlatformaSDKVersion = "1.30.21";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,WAAW,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/model",
3
- "version": "1.30.3",
3
+ "version": "1.30.21",
4
4
  "description": "Platforma.bio SDK / Block Model",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",
@@ -21,7 +21,7 @@
21
21
  "utility-types": "^3.11.0",
22
22
  "canonicalize": "~2.1.0",
23
23
  "zod": "~3.23.8",
24
- "@milaboratories/pl-model-common": "^1.14.0",
24
+ "@milaboratories/pl-model-common": "^1.14.1",
25
25
  "@milaboratories/pl-error-like": "^1.12.1"
26
26
  },
27
27
  "devDependencies": {
@@ -31,8 +31,8 @@
31
31
  "jest": "^29.7.0",
32
32
  "@jest/globals": "^29.7.0",
33
33
  "ts-jest": "^29.2.6",
34
- "@platforma-sdk/eslint-config": "1.0.3",
35
- "@milaboratories/platforma-build-configs": "1.0.3"
34
+ "@milaboratories/platforma-build-configs": "1.0.3",
35
+ "@platforma-sdk/eslint-config": "1.0.3"
36
36
  },
37
37
  "scripts": {
38
38
  "type-check": "node ./scripts/save-package-version.cjs && tsc --noEmit --composite false",
@@ -1,12 +1,14 @@
1
1
  import type {
2
2
  AxisId,
3
3
  CanonicalizedJson,
4
+ DataInfo,
4
5
  PColumn,
6
+ PColumnSpec,
5
7
  PColumnSpecId,
6
8
  PColumnValues,
7
9
  PFrameHandle,
8
10
  PObjectId,
9
- ValueType } from '@milaboratories/pl-model-common';
11
+ } from '@milaboratories/pl-model-common';
10
12
  import {
11
13
  canonicalizeJson,
12
14
  getAxisId,
@@ -49,21 +51,21 @@ function getKeysCombinations(idsLists: AxisId[][]) {
49
51
 
50
52
  /** Check if axes of secondary column are exactly in axes of main column */
51
53
  function checkFullCompatibility(
52
- mainColumn: PColumn<TreeNodeAccessor | PColumnValues>,
53
- secondaryColumn: PColumn<TreeNodeAccessor | PColumnValues>,
54
+ mainColumn: PColumnSpec,
55
+ secondaryColumn: PColumnSpec,
54
56
  ): boolean {
55
- const mainAxesIds = mainColumn.spec.axesSpec.map(getAxisId);
56
- const secondaryAxesIds = secondaryColumn.spec.axesSpec.map(getAxisId);
57
+ const mainAxesIds = mainColumn.axesSpec.map(getAxisId);
58
+ const secondaryAxesIds = secondaryColumn.axesSpec.map(getAxisId);
57
59
  return secondaryAxesIds.every((id) => mainAxesIds.some((mainId) => matchAxisId(mainId, id) && matchAxisId(id, mainId)));
58
60
  }
59
61
 
60
62
  /** Check if axes of secondary column are in axes of main column, but they can have compatible difference in domains */
61
63
  function checkCompatibility(
62
- mainColumn: PColumn<TreeNodeAccessor | PColumnValues>,
63
- secondaryColumn: PColumn<TreeNodeAccessor | PColumnValues>,
64
+ mainColumn: PColumnSpec,
65
+ secondaryColumn: PColumnSpec,
64
66
  ): boolean {
65
- const mainAxesIds = mainColumn.spec.axesSpec.map(getAxisId);
66
- const secondaryAxesIds = secondaryColumn.spec.axesSpec.map(getAxisId);
67
+ const mainAxesIds = mainColumn.axesSpec.map(getAxisId);
68
+ const secondaryAxesIds = secondaryColumn.axesSpec.map(getAxisId);
67
69
  return secondaryAxesIds.every((id) => mainAxesIds.some((mainId) => matchAxisId(mainId, id)));
68
70
  }
69
71
 
@@ -73,17 +75,17 @@ export const LABEL_ANNOTATION = 'pl7.app/label';
73
75
  /** Main column can have additional domains, if secondary column (meta-column) has all axes match main column axes
74
76
  we can add its copy with missed domain fields for compatibility */
75
77
  function getAdditionalColumnsForPair(
76
- mainColumn: PColumn<TreeNodeAccessor | PColumnValues>,
77
- secondaryColumn: PColumn<TreeNodeAccessor | PColumnValues>,
78
- ): PColumn<TreeNodeAccessor | PColumnValues>[] {
78
+ mainColumn: PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor> | PColumnValues>,
79
+ secondaryColumn: PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor> | PColumnValues>,
80
+ ): PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor> | PColumnValues>[] {
79
81
  const mainAxesIds = mainColumn.spec.axesSpec.map(getAxisId);
80
82
  const secondaryAxesIds = secondaryColumn.spec.axesSpec.map(getAxisId);
81
83
 
82
- const isFullCompatible = checkFullCompatibility(mainColumn, secondaryColumn);
84
+ const isFullCompatible = checkFullCompatibility(mainColumn.spec, secondaryColumn.spec);
83
85
  if (isFullCompatible) { // in this case it isn't necessary to add more columns
84
86
  return [];
85
87
  }
86
- const isCompatible = checkCompatibility(mainColumn, secondaryColumn);
88
+ const isCompatible = checkCompatibility(mainColumn.spec, secondaryColumn.spec);
87
89
  if (!isCompatible) { // in this case it is impossible to add some compatible column
88
90
  return [];
89
91
  }
@@ -155,8 +157,10 @@ function getAdditionalColumnsForPair(
155
157
  });
156
158
  }
157
159
 
158
- export function getAdditionalColumns(columns: PColumn<TreeNodeAccessor | PColumnValues>[]): PColumn<TreeNodeAccessor | PColumnValues>[] {
159
- const additionalColumns: PColumn<TreeNodeAccessor | PColumnValues>[] = [];
160
+ export function getAdditionalColumns(
161
+ columns: PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor> | PColumnValues>[],
162
+ ): PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor> | PColumnValues>[] {
163
+ const additionalColumns: PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor> | PColumnValues>[] = [];
160
164
  for (let i = 0; i < columns.length; i++) {
161
165
  for (let j = i + 1; j < columns.length; j++) {
162
166
  const column1 = columns[i];
@@ -173,9 +177,9 @@ export function getAdditionalColumns(columns: PColumn<TreeNodeAccessor | PColumn
173
177
  }
174
178
 
175
179
  export function enrichColumnsWithCompatible(
176
- mainColumns: PColumn<TreeNodeAccessor | PColumnValues>[],
177
- secondaryColumns: PColumn<TreeNodeAccessor | PColumnValues>[],
178
- ): PColumn<TreeNodeAccessor | PColumnValues>[] {
180
+ mainColumns: PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor> | PColumnValues>[],
181
+ secondaryColumns: PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor> | PColumnValues>[],
182
+ ): PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor> | PColumnValues>[] {
179
183
  const mainColumnsIds = new Set<PObjectId>();
180
184
  const mainColumnsBySpec = new Map<CanonicalizedJson<PColumnSpecId>, typeof mainColumns[number]>();
181
185
  mainColumns.forEach((column) => {
@@ -191,7 +195,7 @@ export function enrichColumnsWithCompatible(
191
195
  if (mainColumnsBySpec.has(spec)) continue;
192
196
 
193
197
  for (const mainColumn of mainColumnsBySpec.values()) {
194
- if (checkCompatibility(mainColumn, secondaryColumn)) {
198
+ if (checkCompatibility(mainColumn.spec, secondaryColumn.spec)) {
195
199
  secondaryColumnsBySpec.set(spec, secondaryColumn);
196
200
  break;
197
201
  }
@@ -201,26 +205,16 @@ export function enrichColumnsWithCompatible(
201
205
  return [...mainColumnsBySpec.values(), ...secondaryColumnsBySpec.values()];
202
206
  }
203
207
 
204
- const VALUE_TYPES: ValueType[] = [
205
- 'Int',
206
- 'Long',
207
- 'Float',
208
- 'Double',
209
- 'String',
210
- 'Bytes',
211
- ];
212
-
213
208
  export function createPFrameForGraphs<A, U>(
214
209
  ctx: RenderCtx<A, U>,
215
- blockColumns?: PColumn<TreeNodeAccessor | PColumnValues>[],
210
+ blockColumns: PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor> | PColumnValues>[] | undefined,
216
211
  ): PFrameHandle | undefined {
217
- if (blockColumns === undefined) return undefined;
212
+ if (!blockColumns) return undefined;
218
213
 
219
214
  const upstreamColumns = ctx.resultPool
220
215
  .getData()
221
216
  .entries.map((v) => v.obj)
222
- .filter(isPColumn)
223
- .filter((column) => VALUE_TYPES.includes(column.spec.valueType));
217
+ .filter(isPColumn);
224
218
 
225
219
  const columnsWithCompatibleFromUpstream = enrichColumnsWithCompatible(blockColumns, upstreamColumns);
226
220
 
@@ -1,4 +1,5 @@
1
1
  import type {
2
+ AxisId,
2
3
  AxisSpec,
3
4
  CanonicalizedJson,
4
5
  DataInfo,
@@ -365,7 +366,39 @@ export function getMatchingLabelColumns(
365
366
  columns: PColumnIdAndSpec[],
366
367
  allLabelColumns: PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor>>[],
367
368
  ): PColumn<TreeNodeAccessor | DataInfo<TreeNodeAccessor>>[] {
368
- const colId = (id: PObjectId, domain?: Record<string, string>) => {
369
+ // split input columns into label and value columns
370
+ const inputLabelColumns: typeof columns = [];
371
+ const inputValueColumns: typeof columns = [];
372
+ for (const column of columns) {
373
+ if (isLabelColumn(column.spec)) {
374
+ inputLabelColumns.push(column);
375
+ } else {
376
+ inputValueColumns.push(column);
377
+ }
378
+ }
379
+
380
+ // collect distinct axes of value columns
381
+ const unlabeledAxes: AxisId[] = [];
382
+ for (const column of inputValueColumns) {
383
+ for (const axis of column.spec.axesSpec) {
384
+ const axisId = getAxisId(axis);
385
+ if (!unlabeledAxes.some((id) => matchAxisId(id, axisId))) {
386
+ unlabeledAxes.push(axisId);
387
+ }
388
+ }
389
+ }
390
+
391
+ // remove axes matched by input label columns
392
+ for (const labelColumn of inputLabelColumns) {
393
+ const labelAxisId = getAxisId(labelColumn.spec.axesSpec[0]);
394
+ const labelMatch = unlabeledAxes.findIndex((axisId) => matchAxisId(axisId, labelAxisId));
395
+ if (labelMatch !== -1) {
396
+ unlabeledAxes.splice(labelMatch, 1);
397
+ }
398
+ }
399
+
400
+ // warning: changing this id will break backward compatibility
401
+ const colId = (id: PObjectId, domain?: Record<string, string>): PObjectId => {
369
402
  let wid = id.toString();
370
403
  if (domain) {
371
404
  for (const k in domain) {
@@ -373,39 +406,35 @@ export function getMatchingLabelColumns(
373
406
  wid += domain[k];
374
407
  }
375
408
  }
376
- return wid;
409
+ return wid as PObjectId;
377
410
  };
378
411
 
379
- const labelColumns = new Map<string, typeof allLabelColumns[number]>();
380
- for (const col of columns) {
381
- for (const axis of col.spec.axesSpec) {
382
- const axisId = getAxisId(axis);
383
- for (const labelColumn of allLabelColumns) {
384
- const labelAxis = labelColumn.spec.axesSpec[0];
385
- const labelAxisId = getAxisId(labelColumn.spec.axesSpec[0]);
386
- if (matchAxisId(axisId, labelAxisId)) {
387
- const dataDomainLen = Object.keys(axisId.domain ?? {}).length;
388
- const labelDomainLen = Object.keys(labelAxisId.domain ?? {}).length;
389
- if (dataDomainLen > labelDomainLen) {
390
- const id = colId(labelColumn.id, axisId.domain);
391
-
392
- labelColumns.set(id, {
393
- id: id as PObjectId,
394
- spec: {
395
- ...labelColumn.spec,
396
- axesSpec: [{ ...axisId, annotations: labelAxis.annotations }],
397
- },
398
- data: labelColumn.data,
399
- });
400
- } else {
401
- labelColumns.set(colId(labelColumn.id), labelColumn);
402
- }
403
- }
412
+ // search label columns for unmatched axes
413
+ const labelColumns: typeof allLabelColumns = [];
414
+ for (const labelColumn of allLabelColumns) {
415
+ const labelAxis = labelColumn.spec.axesSpec[0];
416
+ const labelAxisId = getAxisId(labelAxis);
417
+ const labelMatch = unlabeledAxes.findIndex((axisId) => matchAxisId(axisId, labelAxisId));
418
+ if (labelMatch !== -1) {
419
+ const axisId = unlabeledAxes[labelMatch];
420
+ const dataDomainLen = Object.keys(axisId.domain ?? {}).length;
421
+ const labelDomainLen = Object.keys(labelAxis.domain ?? {}).length;
422
+ if (dataDomainLen > labelDomainLen) {
423
+ labelColumns.push({
424
+ id: colId(labelColumn.id, axisId.domain),
425
+ spec: {
426
+ ...labelColumn.spec,
427
+ axesSpec: [{ ...axisId, annotations: labelAxis.annotations }],
428
+ },
429
+ data: labelColumn.data,
430
+ });
431
+ } else {
432
+ labelColumns.push(labelColumn);
404
433
  }
434
+ unlabeledAxes.splice(labelMatch, 1);
405
435
  }
406
436
  }
407
-
408
- return [...labelColumns.values()];
437
+ return labelColumns;
409
438
  }
410
439
 
411
440
  /** Check if all columns are computed */
@@ -25,7 +25,7 @@ export const TraceEntry = z.object({
25
25
  label: z.string(),
26
26
  });
27
27
  export type TraceEntry = z.infer<typeof TraceEntry>;
28
- type FullTraceEntry = TraceEntry & { fullType: string; occurenceIndex: number };
28
+ type FullTraceEntry = TraceEntry & { fullType: string; occurrenceIndex: number };
29
29
 
30
30
  export const Trace = z.array(TraceEntry);
31
31
  export type Trace = z.infer<typeof Trace>;
@@ -50,7 +50,7 @@ export function deriveLabels<T>(
50
50
  ): RecordsWithLabel<T>[] {
51
51
  const importances = new Map<string, number>();
52
52
 
53
- // number of times certain type occured among all of the
53
+ // number of times certain type occurred among all of the
54
54
  const numberOfRecordsWithType = new Map<string, number>();
55
55
 
56
56
  const enrichedRecords = values.map((value) => {
@@ -88,13 +88,13 @@ export function deriveLabels<T>(
88
88
 
89
89
  const fullTrace: FullTrace = [];
90
90
 
91
- const occurences = new Map<string, number>();
91
+ const occurrences = new Map<string, number>();
92
92
  for (let i = trace.length - 1; i >= 0; --i) {
93
93
  const { type: typeName } = trace[i];
94
94
  const importance = trace[i].importance ?? 0;
95
- const occurenceIndex = (occurences.get(typeName) ?? 0) + 1;
96
- occurences.set(typeName, occurenceIndex);
97
- const fullType = `${typeName}@${occurenceIndex}`;
95
+ const occurrenceIndex = (occurrences.get(typeName) ?? 0) + 1;
96
+ occurrences.set(typeName, occurrenceIndex);
97
+ const fullType = `${typeName}@${occurrenceIndex}`;
98
98
  numberOfRecordsWithType.set(fullType, (numberOfRecordsWithType.get(fullType) ?? 0) + 1);
99
99
  importances.set(
100
100
  fullType,
@@ -103,7 +103,7 @@ export function deriveLabels<T>(
103
103
  importance - (trace.length - i) * DistancePenalty,
104
104
  ),
105
105
  );
106
- fullTrace.push({ ...trace[i], fullType, occurenceIndex });
106
+ fullTrace.push({ ...trace[i], fullType, occurrenceIndex: occurrenceIndex });
107
107
  }
108
108
  fullTrace.reverse();
109
109
  return {
@@ -160,27 +160,27 @@ export function deriveLabels<T>(
160
160
  // * *
161
161
  // T0 T1 T2 T3 T4 T5
162
162
  // *
163
- // additinalType = 3
163
+ // additionalType = 3
164
164
  //
165
165
  // Resulting set: T0, T1, T3
166
166
  //
167
167
  let includedTypes = 0;
168
- let additinalType = 0;
168
+ let additionalType = 0;
169
169
  while (includedTypes < mainTypes.length) {
170
170
  const currentSet = new Set<string>();
171
171
  if (ops.includeNativeLabel) currentSet.add(LabelTypeFull);
172
172
  for (let i = 0; i < includedTypes; ++i) currentSet.add(mainTypes[i]);
173
- currentSet.add(mainTypes[additinalType]);
173
+ currentSet.add(mainTypes[additionalType]);
174
174
 
175
175
  const candidateResult = calculate(currentSet);
176
176
 
177
177
  // checking if labels uniquely separate our records
178
178
  if (candidateResult !== undefined && new Set(candidateResult.map((c) => c.label)).size === values.length) return candidateResult;
179
179
 
180
- additinalType++;
181
- if (additinalType >= mainTypes.length) {
180
+ additionalType++;
181
+ if (additionalType >= mainTypes.length) {
182
182
  includedTypes++;
183
- additinalType = includedTypes;
183
+ additionalType = includedTypes;
184
184
  }
185
185
  }
186
186