% Minimal example for exchangeable DSP recipes. % % This script demonstrates the framework wiring only. Set run_ids to one or % more known runs before executing it. % % Signal and parameter flow: % % 1) *This script* here entry script defines run selection and DSP options. % - run_ids selects the measured/simulated records to process. % - dsp_options contains worker configuration, database connection values, % the recipe function handle, and the parameter sweep definition. % % 1.1) *DataStorage* expands dsp_options.userParameters into concrete jobs. % Example: % dsp_options.userParameters.dd_mode = [0, 1] % creates two jobs for each run_id: % job 1: userParameters.dd_mode = 0 % job 2: userParameters.dd_mode = 1 % % 2) *submitJobs* builds the job list. % For each run_id and each Warehouse index it forwards: % dsp_runid(run_id, "recipe", @dsp_recipe_minimal, ... % "userParameters", concreteParameterStruct, ...) % % 3) *runBatch* executes the job list. % submitJobs delegates execution to runBatch. runBatch is the generic % serial/parallel executor; it handles feval/parfeval, progress updates, % result callbacks, and error callbacks, but it has no DSP, DB, Warehouse, % or recipe-specific semantics. % % 4) *dsp_runid* is the worker. % It does not own DSP algorithm choices. It only: % - opens its own DB connection if mode/load/write requires it % - loads metadata for the run_id % - loads Tx_bits, Symbols, and received scope data % - synchronizes/limits Scpe_cell occurrences % - calls the selected recipe for each occurrence % % 5) The *recipe* is the project-specific DSP layer. % dsp_recipe_minimal receives exactly: % Scpe_sig_raw: one received scope/synchronized signal occurrence % Symbols: transmitted symbols/reference % Tx_bits: transmitted bit reference % fsym, M, duob_mode: metadata from the run % userParameters: one concrete parameter struct from the sweep % % 6) *Results* flow back as a standard output struct. % submitJobs auto-creates wh.sto fields from non-empty recipe output % fields. In this example, output.ffe_package creates wh.sto.ffe_package. clearvars; % === DSP settings === % The recipe handle is the only DSP-specific dispatch point in this script. % Switch it to another function with the same signature to run another DSP % chain without changing submitJobs, runBatch, DB loading, or Warehouse logic. dsp_options = struct(); dsp_options.mode = "run_id"; dsp_options.recipe = @dsp_recipe_minimal; dsp_options.append_to_db = false; dsp_options.max_occurences = 1; dsp_options.debug_plots = true; dsp_options.database_type = "mysql"; mpi = 1; if mpi dsp_options.dataBase = "labor"; dsp_options.storage_path = "W:\labdata\ECOC Silas\ecoc_2025"; else dsp_options.dataBase = "labor_highspeed"; dsp_options.storage_path = "W:\labdata\sioe_labor\"; end dsp_options.server = "192.168.178.192"; dsp_options.port = 3306; dsp_options.user = "silas"; dsp_options.password = "silas"; db = DBHandler("dataBase", [dsp_options.dataBase],... "type", dsp_options.database_type,... "server", dsp_options.server,... "user", dsp_options.user, "password", dsp_options.password); % Parameters are expanded by DataStorage and interpreted by the recipe. % submitJobs treats this struct as transport data only; semantic meaning % belongs to dsp_recipe_minimal or any replacement recipe. dsp_options.userParameters = struct(); dsp_options.userParameters.dd_mode = [0,1]; fp = QueryFilter(); if mpi fp.where('Runs', 'symbolrate', 'EQUALS', 112e9); fp.where('Runs', 'fiber_length', 'EQUALS', 0); fp.where('Runs', 'interference_path_length', 'EQUALS', 1000); fp.where('Runs', 'sir', 'EQUALS', 52); fp.where('Runs', 'db_mode', 'EQUALS', '"no_db"'); fp.where('Runs', 'is_mpi', 'EQUALS', 1); fp.where('Runs', 'pam_level', 'EQUALS', 4); fp.where('Runs', 'wavelength', 'EQUALS', 1310); fp.where('Runs', 'v_bias', 'EQUALS', 2.65); else % fp.where('Runs', 'pam_level','EQUALS', 4); % fp.where('Runs', 'bitrate','EQUALS', 360e9); % fp.where('Runs', 'fiber_length','EQUALS', 2); % fp.where('Runs', 'is_mpi','EQUALS', 0); % fp.where('Runs', 'wavelength','EQUALS', 1310); % fp.where('Runs', 'db_mode','EQUALS', 0); % fp.where('Runs', 'rop_attenuation','EQUAL', 0); end [dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs')); run_ids = dataTable.run_id(1); if isempty(run_ids) error("run_minimal_recipe:MissingRunIds", ... "Set run_ids to one or more known run IDs before running this example."); end %% === Warehouse setup === % DataStorage defines the parameter grid. Result containers are created by % submitJobs from returned recipe output fields. wh = DataStorage(dsp_options.userParameters); %% === Run === % submitJobs returns the raw per-job results and the filled Warehouse. For a % single run_id and dd_mode = [0, 1], results is a 2-by-1 cell array. [results, wh] = submitJobs(run_ids, dsp_options, processingMode.serial, ... "wh", wh, ... "waitbar", true);