import type { AssayFeature, CalibrationPoint, InstrumentRunItemInput, ReagentTemplateInput, SampleRecord, } from './types' import { normalizeAssayFeature, normalizeReagent, } from './assayNormalizers' import { idFromName } from './builderIdUtils' export function normalizeMetaboliteFeatures( metabolites: Array, responseUnit: string, ): AssayFeature[] { return metabolites.map((metabolite, index) => { if (typeof metabolite === 'string') { return { id: idFromName(metabolite, `metabolite-${index + 1}`), name: metabolite, type: 'metabolite', unit: responseUnit, metadata: { quantitation: 'targeted' }, } } const feature = normalizeAssayFeature(metabolite) return { ...feature, type: feature.type ?? 'metabolite', unit: feature.unit ?? responseUnit, metadata: { quantitation: 'targeted', ...feature.metadata, }, } }) } export function normalizeInternalStandardReagents( internalStandards: Array, ): ReagentTemplateInput[] { return internalStandards.map((standard, index) => { if (typeof standard === 'string') { return { id: idFromName(standard, `internal-standard-${index + 1}`), name: standard, kind: 'compound', metadata: { role: 'internal-standard' }, } } const reagent = normalizeReagent(standard) return { ...reagent, kind: standard.kind ?? 'compound', metadata: { role: 'internal-standard', ...reagent.metadata, }, } }) } export function targetedMetabolomicsRunItems( samples: SampleRecord[], calibrationPoints: CalibrationPoint[], includeQc: boolean, ): InstrumentRunItemInput[] { const calibrationItems = calibrationPoints .filter(point => point.role !== 'qc' || includeQc) .filter(point => point.role === 'blank' || point.role === 'standard' || point.role === 'qc') .map((point): InstrumentRunItemInput => ({ id: `${point.id}-run`, kind: calibrationRunItemKind(point.role), name: point.level, metadata: { concentration: point.concentration, unit: point.unit, role: point.role, }, })) const sampleItems = samples.map((sample): InstrumentRunItemInput => ({ sampleId: sample.sampleId, name: sample.name ?? sample.sampleId, kind: 'sample', })) return [...calibrationItems, ...sampleItems] } export function firstFeatureName(features: AssayFeature[], fallback: string): string { return features.find(feature => feature.name)?.name ?? fallback } function calibrationRunItemKind(role: CalibrationPoint['role']): 'blank' | 'standard' | 'qc' { if (role === 'blank' || role === 'standard' || role === 'qc') return role return 'standard' }