function [weights, dose] = linlsqOptimization(optSettings) % Input: optSettings structure, defined as follows: % optSettings % .prescInfo % .savePresc = 'yes' or 'no' (defaults to 'no') % .presc (prescription structure, which has the form: % .presc.siz = [M N Q] size of each beamlet % .presc.tissue = Structure array of tissue-specific % prescription. savePrescription subfunction has details. % Defaults to an empty matrix. % .prescFile (defaults to 'prescription.txt') % % .beamletInfo % .saveBeamlets = 'yes' or 'no' (defaults to 'no') % .saveBeamletHeader = 'yes' or 'no' (defaults to 'no') % .beamletFolder (defaults to 'beamlets') % .beamlets (cell array of Matlab-style sparse beamlets stored as: % .beamlets{n}.Dij{m}, where Dij contains the sparse data) % Defaults to an empty matrix. % .beamletBatchBaseName (defaults to 'beamletbatch') % .beamletBatchExtension (defaults to 'bin') % .beamletHeaderFileName (defaults to 'beamlet_header.txt') % .Nbeamlets (defaults to 1) % .Nbeamletbatches (defaults to 1) % .beamletDim (defaults to [1 1 1]) % % .optInfo % .saveOptInfo = 'yes' or 'no' (defaults to 'no') % .optRun = 'yes' or 'no' (defaults to 'no') % .waitForResults = 'yes' or 'no' (defaults to 'no') % .optFolder (Folder containing optimizer's Visual C++ code) % Defaults to 'C:\rtflynn\library\matlabAdditions\optimization\linlsq\linlsqOpt' % .inputFolder (defaults to 'input') % .outputFolder (defaults to 'output') % .inputFile (defaults to optInput.txt) % .Niterations (Defaults to 100) % .Nperbatch (Defaults to 50) % .doseBatchBaseName (defaults to 'dosebatch') % .doseBatchExtension (defaults to 'img') % .weightBatchBaseName (defaults to 'weightbatch') % .weightBatchExtension (defaults to 'img') % .optExeName (defaults to 'linlsqOpt.exe') % .objFuncFileName (defaults to 'objFunc.bin') % % .initialGuessInfo % .saveInitialGuess = 'yes' or 'no' (defaults to 'no') % .w0 (initial guess for all beamlet weights, defaults to empty matrix) % .initBeamWeightFile (defaults to 'init_beam_weight_file') % % Outputs: % w optimized beamlet weights % dose optimized dose distribution % % Outputs are empty matrices unless the 'waitForResults' flag is set to % 'yes'. Otherwise, load results at a later time. % Check input structure for inconistencies, set defaults for fields that % were optional and not included. optSettings = parseInput(optSettings); % From this point on, it is assumed that all fields that are required for % any functions for the rest of this script are present. origDir = pwd; % copy the directory path from which this script was called warning off; % Change to the directory containing the linlsqOpt source code. cd(optSettings.optInfo.optFolder); % save prescription info savePrescription(optSettings); % save beamlet info saveBeamlets(optSettings); % save initial guess info saveInitialGuess(optSettings); % save optimization info saveOptInfo(optSettings); % run optimizer [weights, dose] = runOptimizer(optSettings); cd(origDir); % go back to the original directory function optSettings = parseInput(optSettings) % Checks the optSettings input structure for inconsistencies and applies % defaults to optional fields that were not included in the input % structure. % set optimizer defaults optSettingsDefault.prescInfo.savePresc = 'no'; optSettingsDefault.prescInfo.presc = []; optSettingsDefault.prescInfo.prescFileName = 'prescription.txt'; optSettingsDefault.beamletInfo.saveBeamlets = 'no'; optSettingsDefault.beamletInfo.saveBeamletHeader = 'no'; optSettingsDefault.beamletInfo.beamletFolder = 'beamlets'; optSettingsDefault.beamletInfo.beamlets = []; optSettingsDefault.beamletInfo.beamletBatchBaseName = 'beamletbatch'; optSettingsDefault.beamletInfo.beamletBatchExtension = 'bin'; optSettingsDefault.beamletInfo.beamletHeaderFileName = 'beamlet_header.txt'; optSettingsDefault.beamletInfo.Nbeamlets = 1; optSettingsDefault.beamletInfo.Nbeamletbatches = 1; optSettingsDefault.beamletInfo.beamletDim = [1 1 1]; optSettingsDefault.optInfo.saveOptInfo = 'no'; optSettingsDefault.optInfo.optRun = 'no'; optSettingsDefault.optInfo.waitForResults = 'no'; optSettingsDefault.optInfo.optFolder = ... 'C:\rtflynn\library\matlabAdditions\optimization\linlsq\linlsqOpt'; optSettingsDefault.optInfo.inputFolder = 'input'; optSettingsDefault.optInfo.outputFolder = 'output'; optSettingsDefault.optInfo.inputFile = 'optInput.txt'; optSettingsDefault.optInfo.Niterations = 100; optSettingsDefault.optInfo.Nperbatch = 50; optSettingsDefault.optInfo.doseBatchBaseName = 'dosebatch'; optSettingsDefault.optInfo.doseBatchExtension = 'img'; optSettingsDefault.optInfo.weightBatchBaseName = 'weightbatch'; optSettingsDefault.optInfo.weightBatchExtension = 'img'; optSettingsDefault.optInfo.optExeName = 'linlsqOpt.exe'; optSettingsDefault.optInfo.objFuncFileName = 'objFunc.bin'; optSettingsDefault.optInfo.modFactor = 1e10; optSettingsDefault.initialGuessInfo.saveInitialGuess = 'no'; optSettingsDefault.initialGuessInfo.w0 = []; optSettingsDefault.initialGuessInfo.initBeamWeightFile = 'init_beam_weight_file.img'; % Traverse the optSettings structure tree, and, whenever a leaf is missing % in the tree, fill it in with its default value. nodeVec = [1 1]; % vector corresponding to nodes in the structure tree while length(nodeVec) > 1 % traverse as long as we're not back at the top of the tree % Create a field access string, which is used to access the node % referred to by nodeVec. fldAccStr = 'optSettingsDefault'; for k=2:length(nodeVec) eval(['fieldNames = fieldnames(' fldAccStr ');']); fldAccStr = [fldAccStr '.' fieldNames{nodeVec(k)}]; end % Check if the field is a number or a string (leaf). eval(['numFlag = isnumeric(' fldAccStr ');']); eval(['charFlag = ischar(' fldAccStr ');']); if numFlag == 1 | charFlag == 1 % found a leaf % Traverse input structure, searching for leaves that exist in the % default structure but do not exist in the input structure. This % is done by working down the input tree until either a node or a % leaf is missing from the input fldAccStrInp = 'optSettings'; fldAccStrDummy = 'optSettingsDefault'; for k=2:length(nodeVec) eval(['fieldNamesDummy = fieldnames(' fldAccStrDummy ');']); eval(['fieldFlag = isfield(' fldAccStrInp ',''' fieldNamesDummy{nodeVec(k)} ''');']); if fieldFlag == 1 fldAccStrInp = [fldAccStrInp '.' fieldNamesDummy{nodeVec(k)}]; fldAccStrDummy = [fldAccStrDummy '.' fieldNamesDummy{nodeVec(k)}]; else % Leaf cannot exist, so set it to its default. [tok,rem] = strtok(fldAccStr,'.'); fldAccStrInp = ['optSettings' rem]; eval([fldAccStrInp ' = ' fldAccStr ';']); break; end end % go to the next node vector while length(nodeVec) > 1 fldAccStr = 'optSettingsDefault'; for k=2:length(nodeVec) eval(['fieldNames = fieldnames(' fldAccStr ');']); fldAccStr = [fldAccStr '.' fieldNames{nodeVec(k)}]; end % Go to next leaf or nodes on the same level, if one exists. if nodeVec(end) + 1 <= length(fieldNames) nodeVec(end) = nodeVec(end) + 1; break; else % No more leaves or nodes on this level, so go up a level. nodeVec(:,end) = []; end end else % found another field that is not a leaf nodeVec = [nodeVec 1]; % go down a level in the tree end end % If beamlets were included with optSettings, ensure that the % Nbeamletbatches, Nbeamlets, and beamletDim fields are consistent if ~isempty(optSettings.beamletInfo.beamlets) % get the beamlet dimensions [Xcount,Ycount,Zcount] = size(full(optSettings.beamletInfo.beamlets{1}.Dij{1})); optSettings.beamletInfo.beamletDim = [Xcount Ycount Zcount]; optSettings.beamletInfo.Nbeamletbatches = numel(optSettings.beamletInfo.beamlets); optSettings.beamletInfo.Nbeamlets = 0; for k=1:optSettings.beamletInfo.Nbeamletbatches optSettings.beamletInfo.Nbeamlets = optSettings.beamletInfo.Nbeamlets ... + numel(optSettings.beamletInfo.beamlets{k}.Dij); end else % If optSettings.prescInfo.presc.siz was defined, then that field % should contain beamlet dimensions. if isfield(optSettings.prescInfo.presc,'siz') optSettings.beamletInfo.beamletDim = optSettings.prescInfo.presc.siz; end end function savePrescription(optSettings) % If the savePresc field is 'yes', saves a prescription structure to a file % format that is useable by the linear least squares optimizer. %% .prescInfo %% .savePresc = 'yes' or 'no' % .presc (prescription structure, which has the form: % .presc.siz = [M N Q] size of each beamlet % .presc.tissue = structure array of tissue-specific % prescription. savePrescription subfunction has details. % .prescFile (defaults to 'prescription.txt') infValue = 10e10; % value of infinity % Check the savePresc flag. If 'no', do not save prescription if strcmp(lower(optSettings.prescInfo.savePresc),'no') return; end % create input and output folders success = mkdir([optSettings.optInfo.optFolder '/' optSettings.optInfo.inputFolder]); success = mkdir([optSettings.optInfo.optFolder '/' optSettings.optInfo.outputFolder]); % Check the prescription structure to ensure all proper fields are present. prescTissueFields = {'name' 'alpha' 'betaVPlus' 'dVPlus' 'vPlus' 'betaVMinus' ... 'dVMinus' 'vMinus' 'betaPlus' 'betaMinus' 'ind' 'dPlus' 'dMinus'}; if isempty(optSettings.prescInfo.presc) error('optSettings.prescInfo.presc not defined -- define it or set optSettings.prescInfo.savePresc to ''no'''); end if ~isfield(optSettings.prescInfo.presc,'siz') error('Missing ''siz'' field from optSettings.prescInfo.presc structure'); end % siz is present, so make sure it is a 3 element vector if numel(optSettings.prescInfo.presc.siz) ~= 3 error('The ''siz'' field from optSettings.prescInfo.presc structure must be a 3-element vector'); end if ~isfield(optSettings.prescInfo.presc,'tissue') error('Missing ''tissue'' field from prescInfo.presc structure'); end % search for subfields of tissue field for k=1:numel(prescTissueFields) if ~isfield(optSettings.prescInfo.presc.tissue,prescTissueFields{k}) error(['Missing ''' prescTissueFields{k} ''' field from optSettings.prescInfo.presc.tissue structure']); end end % write the prescription file fid = fopen([optSettings.optInfo.optFolder '\' optSettings.optInfo.inputFolder '\' optSettings.prescInfo.prescFileName],'w'); if fid == -1 error('Failed to open prescription file.'); end fprintf(fid,'Ntissue\n'); fprintf(fid,[num2str(numel(optSettings.prescInfo.presc.tissue)) '\n\n']); for k=1:numel(optSettings.prescInfo.presc.tissue) % write prescription parameters for each tissue type % write the current tissue number fprintf(fid,'tissueNum\n'); fprintf(fid,[num2str(k-1) '\n']); fprintf(fid,'name\n'); fprintf(fid,[optSettings.prescInfo.presc.tissue(k).name '\n']); % throughout writing process, always check for infinities before printing values % write the tissue importance fprintf(fid,'alpha\n'); if isinf(optSettings.prescInfo.presc.tissue(k).alpha) fprintf(fid,[num2str(infValue) '\n']); else fprintf(fid,[num2str(optSettings.prescInfo.presc.tissue(k).alpha) '\n']); end fprintf(fid,'betaVPlus\n'); if isinf(optSettings.prescInfo.presc.tissue(k).betaVPlus) fprintf(fid,[num2str(infValue) '\n']); else fprintf(fid,[num2str(optSettings.prescInfo.presc.tissue(k).betaVPlus) '\n']); end fprintf(fid,'dVPlus\n'); if isinf(optSettings.prescInfo.presc.tissue(k).dVPlus) fprintf(fid,[num2str(infValue) '\n']); else fprintf(fid,[num2str(optSettings.prescInfo.presc.tissue(k).dVPlus) '\n']); end fprintf(fid,'vPlus\n'); if isinf(optSettings.prescInfo.presc.tissue(k).vPlus) fprintf(fid,[num2str(infValue) '\n']); else fprintf(fid,[num2str(optSettings.prescInfo.presc.tissue(k).vPlus) '\n']); end fprintf(fid,'betaVMinus\n'); if isinf(optSettings.prescInfo.presc.tissue(k).betaVMinus) fprintf(fid,[num2str(infValue) '\n']); else fprintf(fid,[num2str(optSettings.prescInfo.presc.tissue(k).betaVMinus) '\n']); end fprintf(fid,'dVMinus\n'); if isinf(optSettings.prescInfo.presc.tissue(k).dVMinus) fprintf(fid,[num2str(infValue) '\n']); else fprintf(fid,[num2str(optSettings.prescInfo.presc.tissue(k).dVMinus) '\n']); end fprintf(fid,'vMinus\n'); if isinf(optSettings.prescInfo.presc.tissue(k).vMinus) fprintf(fid,[num2str(infValue) '\n']); else fprintf(fid,[num2str(optSettings.prescInfo.presc.tissue(k).vMinus) '\n']); end fprintf(fid,'betaPlus\n'); if isinf(optSettings.prescInfo.presc.tissue(k).betaPlus) fprintf(fid,[num2str(infValue) '\n']); else fprintf(fid,[num2str(optSettings.prescInfo.presc.tissue(k).betaPlus) '\n']); end % create a name for the underdose penalty prescription file dose_presc_filename = [regexprep(optSettings.prescInfo.presc.tissue(k).name,{' ','\','/'},'') 'DosePlus.bin']; fprintf(fid,'dosePlusFilename\n'); fprintf(fid,[optSettings.optInfo.inputFolder '/' dose_presc_filename '\n']); % save the mask as a sparse matrix fid2 = fopen([optSettings.optInfo.optFolder '\' optSettings.optInfo.inputFolder '\' dose_presc_filename],'wb'); fwrite(fid2,optSettings.prescInfo.presc.siz,'int'); fwrite(fid2,length(optSettings.prescInfo.presc.tissue(k).ind),'int'); fwrite(fid2,optSettings.prescInfo.presc.tissue(k).ind-1,'int'); fwrite(fid2,optSettings.prescInfo.presc.tissue(k).dPlus,'single'); fclose(fid2); fprintf(fid,'betaMinus\n'); if isinf(optSettings.prescInfo.presc.tissue(k).betaMinus) fprintf(fid,[num2str(infValue) '\n']); else fprintf(fid,[num2str(optSettings.prescInfo.presc.tissue(k).betaMinus) '\n']); end % create a name for the overdose penalty prescription file dose_presc_filename = [regexprep(optSettings.prescInfo.presc.tissue(k).name,{' ','\','/'},'') 'DoseMinus.bin']; fprintf(fid,'doseMinusFilename\n'); fprintf(fid,[optSettings.optInfo.inputFolder '/' dose_presc_filename '\n']); % save the mask as a sparse matrix fid2 = fopen([optSettings.optInfo.optFolder '\' optSettings.optInfo.inputFolder '\' dose_presc_filename],'wb'); fwrite(fid2,optSettings.prescInfo.presc.siz,'int'); fwrite(fid2,length(optSettings.prescInfo.presc.tissue(k).ind),'int'); fwrite(fid2,optSettings.prescInfo.presc.tissue(k).ind-1,'int'); fwrite(fid2,optSettings.prescInfo.presc.tissue(k).dMinus,'single'); fclose(fid2); fprintf(fid,'\n'); end fclose(fid); function saveBeamlets(optSettings) % Saves a set of beamlets to filename. Dij is a cell array of beamlets, % each of which must be sparse 2D Matlab matrices. % %% .beamletInfo %% .saveBeamlets = 'yes' or 'no' (if 'yes', beamlets saved) %% .beamletFolder (required, folder containing beamlets their header) % .beamlets (cell array of Matlab-style sparse beamlets stored as: % .beamlets{n}.Dij{m}, where Dij contains the sparse data) % .beamletBatchBaseName (defaults to 'beamletbatch') % .beamletBatchExtension (defaults to 'bin') % .beamletHeaderFileName (defaults to 'beamlet_header.txt') % .Nbeamlets % .Nbeamletbatches % .beamletDim % Check if the beamlet header will need to be saved if strcmp(lower(optSettings.beamletInfo.saveBeamletHeader),'no') ... && strcmp(lower(optSettings.beamletInfo.saveBeamlets),'no') return; end if strcmp(lower(optSettings.beamletInfo.saveBeamlets),'yes') % delete all of the old beamlets and header info success = rmdir([optSettings.optInfo.optFolder '/' optSettings.beamletInfo.beamletFolder],'s'); mkdir([optSettings.optInfo.optFolder '/' optSettings.beamletInfo.beamletFolder]); end % create a folder for the beamlets if it doesn't already exist mkdir(optSettings.beamletInfo.beamletFolder); % create the beamlet header file fid = fopen([optSettings.beamletInfo.beamletFolder '/' optSettings.beamletInfo.beamletHeaderFileName],'w'); if fid == -1 error('Failed to open beamlet header file.'); end fprintf(fid,'beamletDim\n'); fprintf(fid,'%g %g %g\n',optSettings.beamletInfo.beamletDim); fprintf(fid,'Nbeamlets\n'); fprintf(fid,'%g\n',optSettings.beamletInfo.Nbeamlets); fprintf(fid,'Nbeamletbatches\n'); fprintf(fid,'%g\n',optSettings.beamletInfo.Nbeamletbatches); fprintf(fid,'beamletFolder\n'); fprintf(fid,[optSettings.beamletInfo.beamletFolder '\n']); fprintf(fid,'beamletBatchBaseName\n'); fprintf(fid,[optSettings.beamletInfo.beamletBatchBaseName '\n']); fprintf(fid,'beamletBatchExtension\n'); fprintf(fid,[optSettings.beamletInfo.beamletBatchExtension '\n']); fclose(fid); % Check if the beamlets need to be saved if strcmp(lower(optSettings.beamletInfo.saveBeamlets),'no') return; end if isempty(optSettings.beamletInfo.beamlets) error('No beamlets to save -- supply beamlets or set saveBeamlets to ''no'''); end % Save the beamlets beamletNum = 0; for k=1:optSettings.beamletInfo.Nbeamletbatches beamletFileName = [optSettings.beamletInfo.beamletFolder '/' ... optSettings.beamletInfo.beamletBatchBaseName num2str(k-1) '.' ... optSettings.beamletInfo.beamletBatchExtension]; fid = fopen(beamletFileName,'wb'); if fid == -1 error(['Failed to open ' beamletFileName]); end Nbib = numel(optSettings.beamletInfo.beamlets{k}.Dij); % number of beamlet in batch fwrite(fid,Nbib,'int'); for m=1:Nbib % dimensions of current beamlet [Nx,Ny,Nz] = size(full(optSettings.beamletInfo.beamlets{k}.Dij{m})); if Nx - optSettings.beamletInfo.beamletDim(1) ~= 0 ... || Ny - optSettings.beamletInfo.beamletDim(2) ~= 0 ... || Nz - optSettings.beamletInfo.beamletDim(3) ~= 0 error(['Dimensions of optSettings.beamletInfo.beamlets{' ... num2str(k) '}.Dij{' num2str(m) '} are not (' ... num2str(optSettings.beamletInfo.beamletDim(1)) ',' ... num2str(optSettings.beamletInfo.beamletDim(2)) ',' ... num2str(optSettings.beamletInfo.beamletDim(3)) ')']); end % save the beamlet fwrite(fid,beamletNum,'int'); % beamlet number fwrite(fid,optSettings.beamletInfo.beamletDim,'int'); % beamlet dimensions ind = find(optSettings.beamletInfo.beamlets{k}.Dij{m}); % beamlet indices ind = ind - 1; % convert Matlab indices to C indices fwrite(fid,numel(ind),'int'); % number of non-zero indices fwrite(fid,ind,'int'); % non-zero indices fwrite(fid,nonzeros(optSettings.beamletInfo.beamlets{k}.Dij{m}),'float'); beamletNum = beamletNum + 1; end fclose(fid); % close the current beamlet batch end function saveInitialGuess(optSettings) % save the initial guess % exit if the initial guess is not to be saved if strcmp(lower(optSettings.initialGuessInfo.saveInitialGuess),'no') return; end % create input and output folders success = mkdir([optSettings.optInfo.optFolder '/' optSettings.optInfo.inputFolder]); success = mkdir([optSettings.optInfo.optFolder '/' optSettings.optInfo.outputFolder]); initBeamWeightFile = [optSettings.optInfo.optFolder '\' optSettings.optInfo.inputFolder ... '\' optSettings.initialGuessInfo.initBeamWeightFile]; fid = fopen(initBeamWeightFile,'wb'); if fid == -1 error(['Failed to open initial beam weight file: ' initBeamWeightFile]); end fwrite(fid,optSettings.initialGuessInfo.w0,'float'); fclose(fid); function saveOptInfo(optSettings) % Exit if optimization info is not supposed to be saved if strcmp(lower(optSettings.optInfo.saveOptInfo),'no') return; end % create input and output folders success = mkdir([optSettings.optInfo.optFolder '/' optSettings.optInfo.inputFolder]); success = mkdir([optSettings.optInfo.optFolder '/' optSettings.optInfo.outputFolder]); % create the optimization input file optInfoFileName = [optSettings.optInfo.optFolder '/' optSettings.optInfo.inputFile]; fid = fopen(optInfoFileName,'w'); if fid == -1 error(['Failed to open optimization input file: ' optInfoFileName]); end fprintf(fid,'Niterations\n'); fprintf(fid,'%d\n',optSettings.optInfo.Niterations); fprintf(fid,'Nperbatch\n'); fprintf(fid,'%d\n',optSettings.optInfo.Nperbatch); fprintf(fid,'prescFile\n'); fprintf(fid,[optSettings.optInfo.inputFolder '/' optSettings.prescInfo.prescFileName '\n']); fprintf(fid,'initBeamWeightFile\n'); fprintf(fid,[optSettings.optInfo.inputFolder '/' optSettings.initialGuessInfo.initBeamWeightFile '\n']); fprintf(fid,'beamletHeaderFileName\n'); fprintf(fid,[optSettings.beamletInfo.beamletFolder '/' optSettings.beamletInfo.beamletHeaderFileName '\n']); fprintf(fid,'doseBatchBaseName\n'); fprintf(fid,[optSettings.optInfo.outputFolder '/' optSettings.optInfo.doseBatchBaseName '\n']); fprintf(fid,'doseBatchExtension\n'); fprintf(fid,[optSettings.optInfo.doseBatchExtension '\n']); fprintf(fid,'weightBatchBaseName\n'); fprintf(fid,[optSettings.optInfo.outputFolder '/' optSettings.optInfo.weightBatchBaseName '\n']); fprintf(fid,'weightBatchExtension\n'); fprintf(fid,[optSettings.optInfo.weightBatchExtension '\n']); fprintf(fid,'objFuncFileName\n'); fprintf(fid,[optSettings.optInfo.outputFolder '/' optSettings.optInfo.objFuncFileName '\n']); fprintf(fid,'modFactor\n'); fprintf(fid,[num2str(optSettings.optInfo.modFactor) '\n']); fclose(fid); % copy the most recent build of optimizer to the optFolder exeDebugFile = [optSettings.optInfo.optFolder '\Debug\linlsqOpt.exe']; exeFile = [optSettings.optInfo.optFolder '\' optSettings.optInfo.optExeName]; success = copyfile(exeDebugFile,exeFile); if success == 0 error(['Error copying ' exeDebugFile ' to ' exeFile]); end function [weights, dose] = runOptimizer(optSettings) dose = []; weights = []; % Exit function of optimizer is not to be run. if strcmp(lower(optSettings.optInfo.optRun),'no') return; end currDir = pwd; % save a copy of the current directory path % do the optimization delete('optDone.txt'); % delete the old dose file if it exists fprintf('Running optimizer...\n'); % run the optimization from the console eval(['! ' optSettings.optInfo.optExeName ' ' optSettings.optInfo.inputFile ' &']); % Exit if the user did not wish to wait for results if strcmp(lower(optSettings.optInfo.waitForResults),'no') return; end % Check for the flag indicating that the optimization is finished while ~exist('optDone.txt','file') pause(1); % pause before resuming end % Optimization finished, so load the beamlet weights fid = fopen([optSettings.optInfo.outputFolder '/' ... optSettings.optInfo.weightBatchBaseName num2str(optSettings.optInfo.Niterations) '.' ... optSettings.optInfo.weightBatchExtension],'rb'); if fid == -1 error('Unable to open optimized weight results.'); end weights = fread(fid,'float'); fclose(fid); % load the dose distribution fid = fopen([optSettings.optInfo.outputFolder '/' ... optSettings.optInfo.doseBatchBaseName num2str(optSettings.optInfo.Niterations) '.' ... optSettings.optInfo.doseBatchExtension],'rb'); if fid == -1 error('Unable to open optimized dose results.'); end dose = fread(fid,'float'); try dose = reshape(dose,optSettings.beamletInfo.beamletDim); catch error(['Unable to reshape optimized dose distribution. Ensure ' ... 'that optSettings.beamletInfo.beamletDim field matches dose grid dimensions']); end