├── .gitignore
├── LICENSE.md
├── QSPToolbox
├── bakery
│ ├── convertResultTableToStruct.m
│ ├── createSimResultTable.m
│ ├── exampleWfSteps_scratch
│ │ ├── axes.txt
│ │ ├── pointsRT.txt
│ │ ├── step1_burst_simulation.m
│ │ ├── step2_set_up_mapel_options.m
│ │ ├── step3_screen_worksheet.m
│ │ └── step4_vpop_expansion.m
│ ├── plotInterventionVPopOverlay.m
│ ├── plotVarsAcrossVPIntervention.m
│ ├── plotVarsOptions.m
│ ├── prccSensitivityOptions.m
│ ├── readAllResultStruct.m
│ ├── removeVPopInterventions.m
│ ├── runPRCCSensitivity.m
│ └── simulateWorksheetIndDoses.m
├── cohort
│ ├── addVariedVPs.m
│ ├── bestNofM.m
│ ├── calculateControlCoefficients.m
│ ├── classes
│ │ ├── bestNofMOptions.m
│ │ ├── calculateControlCoefficientsOptions.m
│ │ ├── clusterPickOptions.m
│ │ ├── clusterTestOptions.m
│ │ ├── runControlCoefficientsSimulationsOptions.m
│ │ ├── sobolSampleOptions.m
│ │ ├── sobolSensitivityOptions.m
│ │ ├── univariateSweepOptions.m
│ │ ├── univariateSweepOutputAnalysisOptions.m
│ │ └── varyAxesOptions.m
│ ├── createResponseSummaryTable.m
│ ├── createScreenTable.m
│ ├── pickClusterVPs.m
│ ├── runControlCoefficientsSimulations.m
│ ├── runSobolSample.m
│ ├── runSobolSensitivity.m
│ ├── runUnivariateSweep.m
│ ├── runUnivariateSweepOutputAnalysis.m
│ ├── screenWorksheetVPs.m
│ ├── testClusterSizes.m
│ └── utility
│ │ ├── getLinearIndependentVectors.m
│ │ ├── getMinimalEdgeSet.m
│ │ ├── resamplePCASpace.m
│ │ ├── selectNbest.m
│ │ └── varyAxes.m
├── deprecationManagement
│ ├── checkUpdateObjectVersion.m
│ ├── deprecated
│ │ ├── VPopRECISTnoBin.m
│ │ ├── expandVPopEffNAutoSplitSave.m
│ │ └── mapelOptionsRECISTnoBin.m
│ ├── updateBinTableFormat.m
│ ├── updateTablesWithSubpopReference.m
│ └── updateTablesWithSubpopformat.m
├── docs
│ └── Cheng_2017_AAPSJ.pdf
├── examples
│ ├── data
│ │ ├── fluorescence_quench_internalization_data_n87_ab1.txt
│ │ ├── xenograft_data_1200115_n87_buffer_only.txt
│ │ ├── xenograft_data_1200147_n87_ab1_only.txt
│ │ ├── xenograft_data_1200147_n87_buffer_only.txt
│ │ ├── xenograft_data_95305073_hep3b.txt
│ │ └── xenograft_data_95305073_n87.txt
│ ├── example01.m
│ ├── example02.m
│ ├── example03.m
│ ├── example04.m
│ ├── example05.m
│ ├── example06.m
│ ├── example07.m
│ └── miscellaneous
│ │ ├── adc_platform_public_v0p15p1.sbproj
│ │ ├── calculateGFunctionSi.m
│ │ ├── example_cohort_worksheet1.mat
│ │ ├── example_intervention_file.txt
│ │ ├── example_vp_file.txt
│ │ ├── example_vpop.mat
│ │ └── gfunction_test.sbproj
├── external
│ ├── compare_correlation_coefficients
│ │ ├── compare_correlation_coefficients.m
│ │ └── license.txt
│ ├── genpath_exclude
│ │ ├── genpath_exclude.m
│ │ └── license.txt
│ ├── herrorbar
│ │ ├── herrorbar.m
│ │ └── license.txt
│ ├── kstest_2s_2d
│ │ ├── kstest_2s_2d.m
│ │ ├── license.txt
│ │ ├── quadrantCount.m
│ │ └── weightedKS2D.m
│ ├── myfisher
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── myfisher.m
│ ├── myfisher22
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── myfisher22.m
│ ├── myfisher23
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── myfisher23.m
│ ├── myfisher24
│ │ ├── license.txt
│ │ └── myfisher24.m
│ ├── nnls
│ │ ├── Readme.txt
│ │ ├── license.txt
│ │ ├── nnls.m
│ │ └── nnlstest1.m
│ └── weightedcorrs
│ │ ├── license.txt
│ │ └── weightedcorrs.m
├── initQSPToolbox.m
├── io
│ ├── loadMapelOptions.m
│ ├── loadVPop.m
│ ├── loadWorksheet.m
│ ├── loadWorksheetAutoMerge.m
│ ├── readExperimentData.m
│ ├── readInterventionTable.m
│ ├── readQSPModel.m
│ ├── readVPTable.m
│ ├── saveMapelOptions.m
│ ├── saveVPop.m
│ ├── saveWorksheet.m
│ ├── saveWorksheetAutoSplit.m
│ ├── saveWorksheetNoCompression.m
│ └── writeResultStruct.m
├── misc
│ └── oncology_trial_data_integration.R
├── plotting
│ ├── classes
│ │ ├── plotAcrossVPOptions.m
│ │ ├── plotCoefficientsOptions.m
│ │ └── plotOptions.m
│ ├── plotAcrossIntervention.m
│ ├── plotAcrossVP.m
│ ├── plotBRVPop.m
│ ├── plotBinVPop.m
│ ├── plotBiomarker.m
│ ├── plotCoefficients.m
│ ├── plotDist2DVPop.m
│ ├── plotDistCDFVPop.m
│ ├── plotInterventionVPop.m
│ ├── plotMnSDVPop.m
│ ├── plotPWHist.m
│ ├── plotSeparateAcrossIntervention.m
│ └── plotSimExpDataVPop.m
├── population
│ ├── adjustLambda.m
│ ├── classes
│ │ ├── @VPop
│ │ │ ├── VPop.m
│ │ │ ├── addPredTableVals.m
│ │ │ ├── addTableSimVals.m
│ │ │ ├── assignCoeffs.m
│ │ │ ├── assignIndices.m
│ │ │ ├── assignPWs.m
│ │ │ ├── get.m
│ │ │ ├── getSimData.m
│ │ │ ├── startPWs.m
│ │ │ └── startProbs.m
│ │ ├── VPopRECIST.m
│ │ ├── correlationOptions.m
│ │ ├── expandVPopEffNOptions.m
│ │ ├── mapelOptions.m
│ │ └── mapelOptionsRECIST.m
│ ├── createVPRangeTable.m
│ ├── dataImport
│ │ ├── convertExpDataTo2DDistTable.m
│ │ ├── convertExpDataToBinTable.m
│ │ ├── convertExpDataToCorTable.m
│ │ ├── convertExpDataToDistTable.m
│ │ ├── convertExpDataToMnSDTable.m
│ │ ├── convertMapelOptionsToExpDataTable.m
│ │ ├── convertResponseTypeToExpDataTable.m
│ │ ├── createBinTable.m
│ │ ├── createBinTableRECIST.m
│ │ ├── createDistTable.m
│ │ ├── createDistTableRECIST.m
│ │ ├── createExpDataTable.m
│ │ ├── createExpDataTableRECIST.m
│ │ ├── createMnSDTable.m
│ │ ├── createMnSDTableRECIST.m
│ │ ├── createResponseTablesRECIST.m
│ │ └── createSubpopTable.m
│ ├── evaluateCorrelations.m
│ ├── evaluateGOF.m
│ ├── evaluateMSE.m
│ ├── expandVPopEffN.m
│ ├── linearCalibration
│ │ ├── classes
│ │ │ ├── LinearCalibration.m
│ │ │ └── LinearCalibrationOptions.m
│ │ └── increaseEffNWithLinearCalibrate.m
│ ├── mapel.m
│ ├── mapelLinearExpand.m
│ ├── restartMapel.m
│ ├── restartMapelLinearExpand.m
│ ├── statistics
│ │ ├── addPD2Vals.m
│ │ ├── alignCDFs.m
│ │ ├── alignCDFsPreGrid.m
│ │ ├── alignSamples.m
│ │ ├── checkExpDataCorrelations.m
│ │ ├── checkLN.m
│ │ ├── compositeGOF.m
│ │ ├── compositeGOFRECIST.m
│ │ ├── contingency2N.m
│ │ ├── hbe.m
│ │ ├── predNPDTFLS.m
│ │ ├── regressPD2ScaleFactor.m
│ │ ├── weightedKS.m
│ │ ├── weightedKSPreGrid.m
│ │ ├── woodF.m
│ │ ├── wtdBinProb.m
│ │ ├── wtdMean.m
│ │ └── wtdStd.m
│ ├── testExpandVPopSettings.m
│ └── utility
│ │ ├── align2DPDFs.m
│ │ ├── calculateExpWeight.m
│ │ ├── calculateExpWeightFix.m
│ │ ├── calculateExpWeightFixSingle.m
│ │ ├── combineBins.m
│ │ ├── createRECISTSimFilter.m
│ │ ├── evaluateObjective.m
│ │ ├── evaluateObjectiveNoBin.m
│ │ ├── expandWorksheetVPsFromVPop.m
│ │ ├── extractLowPs.m
│ │ ├── findFit.m
│ │ ├── getInitialPWs.m
│ │ ├── hyperTransform.m
│ │ ├── initializeOptionPropertiesToVPop.m
│ │ ├── initializeVPopPropertiesToOption.m
│ │ ├── invHyperTransform.m
│ │ ├── loadCommonNames.m
│ │ ├── normalizeWeights.m
│ │ ├── probsToProbVect.m
│ │ ├── scoreWorksheetVPs.m
│ │ ├── scoreWorksheetVPsLC.m
│ │ ├── spreadPWsToNeighbors.m
│ │ ├── subsetWorksheetVPop.m
│ │ ├── transferPWtoChildren.m
│ │ └── updateSubpopTableVPs.m
├── test
│ └── unitTests.m
├── visp
│ ├── createViSPInput.m
│ ├── loadViSPResult.m
│ └── utility
│ │ ├── CreateExportedModel.m
│ │ ├── GetDoseNames.m
│ │ ├── GetIndices.m
│ │ ├── GetParamNamesAndValuesToStoreInDB.m
│ │ ├── SetSimulationOptionsInExportedModel.m
│ │ └── UpdateSimBioModel.m
└── worksheet
│ ├── axis
│ ├── addAxisDef.m
│ ├── getAxisDef.m
│ ├── getAxisDefBounds.m
│ ├── getAxisDefIDs.m
│ ├── getVPCoeffs.m
│ ├── getVPValues.m
│ ├── resetAxis.m
│ ├── resetAxisBounds.m
│ └── utility
│ │ └── setAxisDefBounds.m
│ ├── classes
│ ├── axisDef.m
│ ├── axisVP.m
│ ├── responseTypeElementAxis.m
│ ├── responseTypeElementBounds.m
│ ├── responseTypeElementPoints.m
│ ├── responseTypeResult.m
│ ├── resultTable.m
│ └── simulateOptions.m
│ ├── convertVPCoefficientsToVariants.m
│ ├── copyWorksheet.m
│ ├── createWorksheet.m
│ ├── data
│ ├── getExpData.m
│ └── getExpDataIDs.m
│ ├── diffWorksheets.m
│ ├── getResultOutputforIntervention.m
│ ├── intervention
│ ├── createIntervention.m
│ ├── extractInterventionTypeElements.m
│ ├── getDoseNames.m
│ ├── getInterventionIDs.m
│ └── removeInterventions.m
│ ├── mergeWorksheets.m
│ ├── model
│ ├── compileModel.m
│ ├── getModelCompartmentIDs.m
│ ├── getModelObservableIDs.m
│ ├── getModelParameterIDs.m
│ └── getModelSpeciesIDs.m
│ ├── removeDuplicateVPs.m
│ ├── responseType
│ ├── addResponseTypeElement.m
│ ├── createResponseType.m
│ ├── getResponseType.m
│ ├── getResponseTypeElementIDs.m
│ ├── getResponseTypeIDs.m
│ ├── utility
│ │ ├── evaluateAxisObjective.m
│ │ ├── evaluateBoundsObjectiveWtIntRangeCE.m
│ │ ├── evaluatePointObjectiveCV.m
│ │ ├── evaluatePointObjectiveRange.m
│ │ ├── evaluatePointObjectiveWtIntMedCE.m
│ │ ├── evaluatePointObjectiveWtIntRangeCE.m
│ │ ├── evaluatePointObjectiveWtRange.m
│ │ ├── evaluatePointObjectiveWtRangeCE.m
│ │ ├── evaluateResponseType.m
│ │ └── evaluateResponseTypeElement.m
│ └── verifyResponseType.m
│ ├── results
│ ├── convertSimData.m
│ └── filterResults.m
│ ├── simulateWorksheet.m
│ ├── simulateWorksheetIterateTolerance.m
│ ├── utility
│ ├── calculateIndividualElementValues.m
│ ├── checkNWorkers.m
│ ├── getOptimizationAxes.m
│ ├── getSimulateValuesDoses.m
│ ├── getSimulateValuesDosesSep.m
│ ├── getUniqueBaseVPVariantSets.m
│ ├── particleSwarmCohortWrapper.m
│ ├── runModelforOptimization.m
│ ├── runSimulations.m
│ ├── runSingleSimulation.m
│ ├── runWorksheetCohortOptimization.m
│ ├── runWorksheetVPOptimization.m
│ ├── verifyFullResults.m
│ └── verifySimData.m
│ ├── variant
│ ├── getVariantNames.m
│ ├── getVariantTypeElements.m
│ ├── getVariantTypes.m
│ └── utility
│ │ ├── flattenVariantstoElements.m
│ │ └── updateElementAxisValues.m
│ └── vp
│ ├── createVP.m
│ ├── createVPs.m
│ ├── getPatientgroup.m
│ ├── getVP.m
│ ├── getVPIDs.m
│ ├── keepVPs.m
│ └── removeVPs.m
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Mac files
2 | .DS_Store
3 | *.asv
4 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018, Bristol-Myers Squibb
2 | All rights reserved.
3 |
4 | 'Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 |
8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 |
10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 |
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.'
--------------------------------------------------------------------------------
/QSPToolbox/bakery/exampleWfSteps_scratch/axes.txt:
--------------------------------------------------------------------------------
1 | axisID elementNames elementTypes bounds1_1 bounds1_2 scale1
2 | axisShedding par_ag_shed_rate_t parameter 0 10 linear
3 | axisInternalization par_ag_endocytosis parameter 0 3.5 linear
4 | axisWallPoreA par_fraction_capillary_pore_area_per_unit_thickness_a parameter 5 50 linear
5 | axisWallPoreB par_fraction_capillary_pore_area_per_unit_thickness_b parameter 0.2 1.95 linear
6 | axisShedClearance par_shed_antigen_clearance_p1 parameter 5 300 linear
7 | axisLabelExport par_payload_secretion_rate parameter 0 24 linear
8 | axisICFFraction par_tumor_extravascular_volume_fraction_icf parameter 0.5 0.8 linear
9 | axisVascularFraction par_tumor_volume_fraction_vascular parameter 0.005 0.05 linear
10 | axisRCapRange par_capillary_radius_max parameter 8 15 linear
11 | axisVCapRange par_capillary_radius_exponent parameter 2.43e-05 0.000219 linear
12 | axisLesionLinGrowth par_tumor_grow_rate_linear parameter 8.3 74.7 linear
13 | axisLesionExpGrowth par_tumor_grow_rate_exp parameter 0.0244 0.219 linear
14 | axisInitialTumorMass par_initial_tumor_mass parameter 0.0763 0.24 linear
15 |
--------------------------------------------------------------------------------
/QSPToolbox/bakery/exampleWfSteps_scratch/pointsRT.txt:
--------------------------------------------------------------------------------
1 | rtID elementNames modelYVar modelYVarType interventionID expDataID expDataTimeVar expDataYVar objectiveType weight
2 | culture_internalized N87_agx parrule_payload_fraction_of_initial_bound_intracellular parameter culture_internalization fluorescence_quench_internalization_data_n87_ab1 time_day internalized_fr wtintrangece 1
3 | buffer_injection_1200147_growth_assay N87_agx parrule_tumor_volume parameter buffer_injection_1200147_shed_assay xenograft_data_1200147_n87_buffer_only TIME_PLUS_11_DAY TUMOR_VOLUME_L wtintrangece 1
4 | buffer_injection_1200147_shed_assay N87_agx parrule_shed_total_plasma_concentration parameter buffer_injection_1200147_shed_assay xenograft_data_1200147_n87_buffer_only TIME_PLUS_11_DAY SOLAG_NANOMOLEPL wtintrangece 1
5 | antibody_injection_1200147_growth_assay N87_agx parrule_tumor_volume parameter antibody_injection_1200147_shed_assay xenograft_data_1200147_n87_ab1_only TIME_PLUS_11_DAY TUMOR_VOLUME_L wtintrangece 1
6 | antibody_injection_1200147_shed_assay N87_agx parrule_shed_total_plasma_concentration parameter antibody_injection_1200147_shed_assay xenograft_data_1200147_n87_ab1_only TIME_PLUS_11_DAY SOLAG_NANOMOLEPL wtintrangece 1
7 | agxab1pet_injection N87_agx parrule_payload_total_apparent_pet_tumor_nanomole_per_gram parameter agxab1pet_injection xenograft_data_95305073_n87 time_10delayed_day accumulation_N87_nmole_per_gram_tumor wtintrangece 1
8 |
--------------------------------------------------------------------------------
/QSPToolbox/cohort/utility/getLinearIndependentVectors.m:
--------------------------------------------------------------------------------
1 | function [VPCoeffsLI, VPind] = getLinearIndependentVectors(VPCoeffs)
2 | % This function takes an input matrix where columns are
3 | % VPs and tested for linear independence.
4 | % It will preferentially pick out columns in the order provided.
5 | %
6 | % ARGUMENTS
7 | % VPCoeffs: A matrix of VP coefficients
8 | %
9 | % RETURNS
10 | % VPCoeffsLI: A matrix of VP coefficients
11 | % that are linearly independent.
12 | % VPind: Indices of the VPs in the returned
13 | % matrix from the input matrix
14 | %
15 |
16 | % This will force to select the first vector of
17 | % collinar vector pairs, if any
18 | %VPCoeffs = fliplr(VPCoeffs);
19 | [nRows, nCols] = size(VPCoeffs);
20 | VPCoeffsT = VPCoeffs';
21 | R1=1;
22 | % We will force what is probably a larger tolerance value to
23 | % be more conservative
24 | tolerance = 1E-8;
25 | excludeInd = nan(1,0);
26 | for I=1:size(VPCoeffsT,1)
27 | R2=rank(VPCoeffsT(1:I,:),tolerance);
28 | if R2~=R1
29 | excludeInd = [excludeInd,I];
30 | end
31 | R1=R2+1;
32 | end
33 | VPind = [1:nCols];
34 | VPind(excludeInd) = [];
35 | VPCoeffsLI = VPCoeffs(:,VPind);
36 | end
--------------------------------------------------------------------------------
/QSPToolbox/cohort/utility/getMinimalEdgeSet.m:
--------------------------------------------------------------------------------
1 | function edgeVPIDs = getMinimalEdgeSet(parentVPs)
2 | % This function takes a cell array of cell arrays of identification strings
3 | % as an imput and returns a cell of identification strings
4 | % including at least one indentificaiton string from each set in the
5 | % original cell array of cell arrays.
6 | %
7 | % This function was written to help with the selection of a minimum set of
8 | % edge VPs. i.e. where each inner array
9 | % {{VPID1, VPID2}; {VPID2, VPID3, VPID4}; ... }
10 | % Could have multiple VPs that are a tied for some characteristic, i.e.
11 | % being and edge, and we want to provide a cell array of VPIDs that
12 | % includes one VP from all the edges, preferably the smallest set possible.
13 | %
14 | % Arguments:
15 | % parentVPs A cell array of cell array of strings. i.e.:
16 | % {{VPID1, VPID2}; {VPID2, VPID3, VPID4}; {VPID5}; ... }
17 | %
18 | % Returns:
19 | % edgeVPIDs A cell array of strings containing at least one entry from
20 | % from every set in parentVPs. i.e.:
21 | % {VPID2, VPID5, ... }
22 | %
23 |
24 | nParentCandidates = length(parentVPs);
25 | parentVPsPass = cell(1,length(parentVPs));
26 | parentsPassCounter = 1;
27 | for checkCounter =1 : nParentCandidates
28 | curCheckParents = parentVPs{checkCounter};
29 | % We need to compare to other parents in the list to
30 | % 1. pick the best parent that might cover multiple edges and
31 | % 2. minimize double counting for edges
32 | [~, curCheckSize] = size(curCheckParents);
33 |
34 | if checkCounter < nParentCandidates
35 | curCheckscore = zeros(nParentCandidates-(checkCounter),curCheckSize);
36 | % First check the current set of parents against the ones
37 | % further down the list in case one of the parents
38 | % in the current set appears there.
39 | for otherParentCounter = (checkCounter + 1) : nParentCandidates
40 | testParents = parentVPs{otherParentCounter};
41 | curCheckscore(otherParentCounter - checkCounter,:) = ismember(curCheckParents,testParents);
42 | end
43 | otherParentIndices = (checkCounter + 1) : nParentCandidates;
44 | % After we have the comparison for the current parents,
45 | % we pick the one with highest score as compared to
46 | % other rows
47 | sumParentScores = sum(curCheckscore,1);
48 | bestIndex = find(sumParentScores == max(sumParentScores));
49 | if length(bestIndex) > 1
50 | % In case of a tie
51 | bestIndex = bestIndex(1);
52 | end
53 | % Now we note the other VP sets that contained the best
54 | % parent
55 | curCheckscore = curCheckscore(:,bestIndex);
56 | % These are the rows where we found a match and can
57 | % substitute in the current best parent
58 | substituteOtherParentIndex = otherParentIndices(find(curCheckscore));
59 | if length(substituteOtherParentIndex) > 0
60 | parentVPs(substituteOtherParentIndex) = {{curCheckParents{bestIndex}}};
61 | end
62 | parentVPsPass{checkCounter} = curCheckParents{bestIndex};
63 |
64 | else
65 | % For the last entry, we do no comparison
66 | parentVPsPass{checkCounter} = curCheckParents{1};
67 | end
68 |
69 | end
70 | edgeVPIDs = unique(parentVPsPass,'stable');
71 | end
--------------------------------------------------------------------------------
/QSPToolbox/cohort/utility/resamplePCASpace.m:
--------------------------------------------------------------------------------
1 | function myVPs = resamplePCASpace(myNeighborsAndSelf,myVPIndex,relStd,nChildren,outputBounds)
2 | % This function transform VPs into PCA space, resamples around the parent VP
3 | % according to their variance, and transforms the new VPs back.
4 | %
5 | % ARGUMENTS
6 | % myNeighborsAndSelf: matrix with VP of interest and neightbording VPs.
7 | % VPs are assumed to be column vectors.
8 | % myVPIndex: column index of "parent" VP to sample around
9 | % relStd: Relative scaling of standard deviation for sampling. The value
10 | % will be squared to scale the relative variance of resampling in
11 | % PCA space, which will also take into account the variance
12 | % of each principal component
13 | % nChildren: number of children VPs
14 | % outputBounds: an nAxis x 2 matrix of bounds on the output
15 | % values above or below will be truncated to this
16 | % value.
17 | % i.e. a matrix with rows [0 1] if the input is
18 | % normalized between 0 and 1.
19 | %
20 | % RETURNS
21 | % myVPs: VPs that have been resampled
22 | %
23 | [nDim,nParents] = size(myNeighborsAndSelf);
24 | myNeighborsAndSelf=myNeighborsAndSelf';
25 | myMean = mean(myNeighborsAndSelf,1);
26 | myNeighborsAndSelf=myNeighborsAndSelf-mean(myNeighborsAndSelf,1);
27 |
28 | % Use MATLAB's function
29 | [eigenV,transData,varV,tsd,varN] = pca(myNeighborsAndSelf,'Algorithm','eig');
30 |
31 | % Now that we have eigenVectors, transform just the VPs of interest
32 | transData = myNeighborsAndSelf(myVPIndex,:)*eigenV;
33 |
34 | % Sample in PCA space taking the eigenvalues and
35 | % relative scaling into consideration
36 | % reScale = 1/sqrt((2*pi())^nDim*sum(varV));
37 | reScale = 1/sqrt(sum(varV));
38 | transData=transData+reScale*mvnrnd(zeros(1,nDim),(relStd^2)*(varV.*eye(nDim)),nChildren);
39 |
40 | % Transform back
41 | myVPs = transData * (eigenV') + myMean;
42 | myVPs = myVPs';
43 | [replaceRow,replaceCol] = find(myVPs < outputBounds(:,1));
44 | replaceIndices = find(myVPs < outputBounds(:,1));
45 | if ~isempty(replaceRow)
46 | myVPs(replaceIndices) = outputBounds(replaceRow,1);
47 | end
48 | [replaceRow,replaceCol] = find(myVPs > outputBounds(:,2));
49 | replaceIndices = find(myVPs > outputBounds(:,2));
50 | if ~isempty(replaceIndices)
51 | myVPs(replaceIndices) = outputBounds(replaceRow,2);
52 | end
53 |
54 | end
55 |
--------------------------------------------------------------------------------
/QSPToolbox/cohort/utility/varyAxes.m:
--------------------------------------------------------------------------------
1 | function newWorksheet = varyAxes(oldWorksheet, myVaryAxesOptions)
2 | % Create a worksheet by varying selected VPs randomly along their
3 | % mechanistic axes.
4 | %
5 | % ARGUMENTS
6 | % oldWorksheet: Starting worksheet. Note the mechanistic axes must be
7 | % defined first before calling this function.
8 | % myVaryAxesOptions: Options for creating new VPs with the varied axes
9 | %
10 | % RETURNS
11 | % newWorksheet: Worksheet that incudes the base VPs and the new VPs
12 | %
13 |
14 | % First check whether sufficient input arguments are provided
15 | continueFlag = false;
16 | if nargin > 2
17 | warning(['Too many input arguments to ',mfilename, '. Arguments should be: oldWorksheet; and optionally: myVaryAxesOptions.'])
18 | continueFlag = false;
19 | elseif nargin > 1
20 | continueFlag = true;
21 | elseif nargin > 0
22 | myVaryAxesOptions = varyAxesOptions();
23 | myVaryAxesOptions.baseVPIDs = getVPIDs(oldWorksheet);
24 | myVaryAxesOptions.varyAxisIDs = getAxisDefIDs(oldWorksheet);
25 | continueFlag = true;
26 | else
27 | warning(['Insufficient input arguments to ',mfilename, '. Arguments should be: oldWorksheet; and optionally: myVaryAxesOptions.'])
28 | end
29 |
30 | % Check whether the input arguments make sense
31 | if continueFlag
32 | passTestFlag = myVaryAxesOptions.verify(oldWorksheet);
33 | if ~passTestFlag
34 | continueFlag = false;
35 | end
36 | if length(myVaryAxesOptions.varyAxisIDs) < 1
37 | continueFlag = false;
38 | warning(['Must vary at least one axis in ',mfilename, '.'])
39 | end
40 | if length(myVaryAxesOptions.baseVPIDs) < 1
41 | continueFlag = false;
42 | warning(['Must select at least one base VP in ',mfilename, '.'])
43 | end
44 | end
45 |
46 | if continueFlag
47 | myBaseVPIDs = myVaryAxesOptions.baseVPIDs;
48 | % If we pass the checks, we can create the new worksheet and add the
49 | % VPs.
50 | newWorksheet = copyWorksheet(oldWorksheet, myBaseVPIDs, false);
51 | for vpCounter = 1 : length(myBaseVPIDs)
52 | subCallVaryOptions = myVaryAxesOptions;
53 | subCallVaryOptions.baseVPIDs = {myBaseVPIDs{vpCounter}};
54 | newWorksheet = addVariedVPs(newWorksheet, subCallVaryOptions);
55 | end
56 | else
57 | warning(['Unable to run ',mfilename,', returning input worksheet.'])
58 | newWorksheet = oldWorksheet;
59 | end
--------------------------------------------------------------------------------
/QSPToolbox/deprecationManagement/updateBinTableFormat.m:
--------------------------------------------------------------------------------
1 | function myUpdatedObject = updateBinTableFormat(myInputObject)
2 | % This is a function to update the bin tables from the old
3 | % format to the new one with allowed variable bin numbers.
4 | % The transition was made around in-house rev1043.
5 | %
6 | % ARGUMENTS:
7 | % myInputObject: A VPop, VPopRECIST, VPopRECISTnoBin,
8 | % mapelOptions, mapelOptionsRECIST, or
9 | % mapelOptionsRECISTnoBin object to convert.
10 | %
11 | % RETURNS:
12 | % myUpdatedObject A VPop, VPopRECIST, VPopRECISTnoBin,
13 | % mapelOptions, mapelOptionsRECIST, or
14 | % mapelOptionsRECISTnoBin object with
15 | % the new binTable.
16 |
17 |
18 |
19 | continueFlag = true;
20 | if nargin > 1
21 | continueFlag = false;
22 | warning(['Too many input arguments for ',mfilename,'. Should provide: a VPop, VPopRECIST, VPopRECISTnoBin, mapelOptions, mapelOptionsRECIST, or mapelOptionsRECISTnoBin.'])
23 | continueFlag = false;
24 | elseif nargin > 0
25 | continueFlag = true;
26 | else
27 | warning(['Insufficient input arguments for ',mfilename,'. Should provide: a VPop, VPopRECIST, VPopRECISTnoBin, mapelOptions, mapelOptionsRECIST, or mapelOptionsRECISTnoBin.'])
28 | continueFlag = false;
29 | end
30 |
31 | if ~(isa(myInputObject,'VPop') || isa(myInputObject,'VPopRECIST') || isa(myInputObject,'VPopRECISTnoBin') || isa(myInputObject,'mapelOptions') || isa(myInputObject,'mapelOptionsRECIST') || isa(myInputObject,'mapelOptionsRECISTnoBin'))
32 | warning(['Wrong input arguments for ',mfilename,'. Should provide: a VPop, VPopRECIST, VPopRECISTnoBin, mapelOptions, mapelOptionsRECIST, or mapelOptionsRECISTnoBin.'])
33 | continueFlag = false;
34 | end
35 |
36 | if continueFlag
37 | myUpdatedObject = myInputObject;
38 | if ~isempty(myInputObject.binTable)
39 | [nRows, nCols] = size(myInputObject.binTable);
40 | if (isa(myInputObject,'VPop') || isa(myInputObject,'mapelOptions'))
41 | referenceCol = 9;
42 | else
43 | referenceCol = 12;
44 | end
45 | myUpdateTable = myInputObject.binTable(:,1:referenceCol);
46 | binEdges = cell(nRows,1);
47 | expBins = cell(nRows,1);
48 | predBins = cell(nRows,1);
49 | for rowCounter = 1 : nRows
50 | curEdges = [myInputObject.binTable{rowCounter,'binEdge1'},myInputObject.binTable{rowCounter,'binEdge2'},myInputObject.binTable{rowCounter,'binEdge3'}];
51 | curExpBins = [myInputObject.binTable{rowCounter,'expBin1'}, myInputObject.binTable{rowCounter,'expBin2'}, myInputObject.binTable{rowCounter,'expBin3'}, myInputObject.binTable{rowCounter,'expBin4'}];
52 | curPredBins = [myInputObject.binTable{rowCounter,'predBin1'}, myInputObject.binTable{rowCounter,'predBin2'}, myInputObject.binTable{rowCounter,'predBin3'}, myInputObject.binTable{rowCounter,'predBin4'}];
53 | binEdges{rowCounter} = curEdges;
54 | expBins{rowCounter} = curExpBins;
55 | predBins{rowCounter} = curPredBins;
56 | end
57 | myUpdateTable = [myInputObject.binTable(:,1:referenceCol), table(binEdges), myInputObject.binTable(:,'expN'), table(expBins), myInputObject.binTable(:,'predN'), table(predBins)];
58 | myUpdatedObject.binTable = myUpdateTable;
59 | end
60 | end
61 | end
--------------------------------------------------------------------------------
/QSPToolbox/deprecationManagement/updateTablesWithSubpopReference.m:
--------------------------------------------------------------------------------
1 | function myUpdatedObject = updateTablesWithSubpopReference(myInputObject)
2 | % This is a function to update the tables attached to mapelOptions
3 | % and VPop objects to include a row for the subpopulation index.
4 | % The transition was made around in-house rev1100.
5 | %
6 | % ARGUMENTS:
7 | % myInputObject: A VPop, VPopRECIST, VPopRECISTnoBin,
8 | % mapelOptions, mapelOptionsRECIST, or
9 | % mapelOptionsRECISTnoBin object to convert.
10 | %
11 | % RETURNS:
12 | % myUpdatedObject A VPop, VPopRECIST, VPopRECISTnoBin,
13 | % mapelOptions, mapelOptionsRECIST, or
14 | % mapelOptionsRECISTnoBin object with
15 | % the tables.
16 |
17 | continueFlag = true;
18 | if nargin > 1
19 | continueFlag = false;
20 | warning(['Too many input arguments for ',mfilename,'. Should provide: a VPop, VPopRECIST, mapelOptions, or mapelOptionsRECIST.'])
21 | continueFlag = false;
22 | elseif nargin > 0
23 | continueFlag = true;
24 | else
25 | warning(['Insufficient input arguments for ',mfilename,'. Should provide: a VPop, VPopRECIST, mapelOptions, or mapelOptionsRECIST.'])
26 | continueFlag = false;
27 | end
28 |
29 | if ~(isa(myInputObject,'VPop') || isa(myInputObject,'VPopRECIST') || isa(myInputObject,'mapelOptions') || isa(myInputObject,'mapelOptionsRECIST') )
30 | warning(['Wrong input arguments for ',mfilename,'. Should provide: a VPop, VPopRECIST, mapelOptions, mapelOptionsRECIST.'])
31 | continueFlag = false;
32 | end
33 |
34 | myUpdatedObject = myInputObject;
35 |
36 | if continueFlag
37 | updateFlag = false;
38 | if isa(myInputObject, 'VPopRECIST') || isa(myInputObject, 'mapelOptionsRECIST')
39 | updateTables = {'expData','mnSDTable','binTable','distTable','distTable2D','corTable','brTableRECIST','rTableRECIST'};
40 | elseif isa(myInputObject, 'VPop') || isa(myInputObject, 'mapelOptions')
41 | updateTables = {'expData','mnSDTable','binTable','distTable','distTable2D','corTable'};
42 | end
43 | for tableCounter = 1:length(updateTables)
44 | curTable = myInputObject.(updateTables{tableCounter});
45 | [nRows, nCols] = size(curTable);
46 | if nRows > 0
47 | curNames = curTable.Properties.VariableNames;
48 | if ~isequal(curNames{1},'subpopNo')
49 | newCol = num2cell(ones(nRows,1));
50 | newCol = cell2table(newCol);
51 | newCol.Properties.VariableNames = {'subpopNo'};
52 | curTable = [newCol,curTable];
53 | updateFlag = true;
54 | myUpdatedObject.(updateTables{tableCounter}) = curTable;
55 | end
56 | end
57 | end
58 | if updateFlag
59 | warning(['Detected missing columns and added subpopNo columns to update the ',class(myInputObject),' tables to the new format. Note that you will have to manually add a subpopTable to the object, which can be created by calling createSubpopTable with the appropriate worksheet.'])
60 | end
61 | else
62 | warning(['Unable to run ',mfilename,'. Returning input object.'])
63 | end
--------------------------------------------------------------------------------
/QSPToolbox/docs/Cheng_2017_AAPSJ.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BMSQSP/QSPToolbox/42cb4425292c5ecdf4954b6251346503746671d0/QSPToolbox/docs/Cheng_2017_AAPSJ.pdf
--------------------------------------------------------------------------------
/QSPToolbox/examples/data/fluorescence_quench_internalization_data_n87_ab1.txt:
--------------------------------------------------------------------------------
1 | time_min time_hr time_day USUBJID internalized_pct internalized_fr
2 | 0 0 0 n87_140530_1 -1.1777 -0.0118
3 | 5 0.083333333 0.003472222 n87_140530_1 5.5553 0.0556
4 | 15 0.25 0.010416667 n87_140530_1 3.9869 0.0399
5 | 30 0.5 0.020833333 n87_140530_1 2.2115 0.0221
6 | 60 1 0.041666667 n87_140530_1 8.261 0.0826
7 | 180 3 0.125 n87_140530_1 14.7973 0.148
8 | 360 10 0.25 n87_140530_1 17.5534 0.1755
9 | 960 16 0.666666667 n87_140530_1 35.4818 0.3548
10 | 0 0 0 n87_140530_2 3.5562 0.0356
11 | 5 0.083333333 0.003472222 n87_140530_2 1.622 0.0162
12 | 15 0.25 0.010416667 n87_140530_2 -0.1189 -0.0012
13 | 30 0.5 0.020833333 n87_140530_2 1.7725 0.0177
14 | 60 1 0.041666667 n87_140530_2 -2.565 -0.0256
15 | 180 3 0.125 n87_140530_2 12.6384 0.1264
16 | 360 10 0.25 n87_140530_2 12.4294 0.1243
17 | 960 16 0.666666667 n87_140530_2 13.5016 0.135
18 | 0 0 0 n87_140530_3 -2.4715 -0.0247
19 | 5 0.083333333 0.003472222 n87_140530_3 6.5642 0.0656
20 | 15 0.25 0.010416667 n87_140530_3 1.3601 0.0136
21 | 30 0.5 0.020833333 n87_140530_3 3.0604 0.0306
22 | 60 1 0.041666667 n87_140530_3 8.0236 0.0802
23 | 180 3 0.125 n87_140530_3 7.1955 0.072
24 | 360 10 0.25 n87_140530_3 22.5344 0.2253
25 | 960 16 0.666666667 n87_140530_3 11.438 0.1144
26 |
--------------------------------------------------------------------------------
/QSPToolbox/examples/data/xenograft_data_95305073_hep3b.txt:
--------------------------------------------------------------------------------
1 | USUBJID LESIONID time_day time_10delayed_day mouse_weight_kg HEP3B_xenograft_volume_L HEP3B_xenograft_weight_g dose_nmole accumulation_HEP3B_nmole_per_gram_tumor accumulation_HEP3B_nM
2 | 95305073_01 95305073_01_HEP3B 0 10 0.0234 7.20E-05 0.0756 0.398222222 . .
3 | 95305073_01 95305073_01_HEP3B 0.904861111 10.90486111 . . . . 0.028533658 29.96034139
4 | 95305073_01 95305073_01_HEP3B 3.946527778 13.94652778 . . . . 0.019360283 20.32829666
5 | 95305073_01 95305073_01_HEP3B 4.985416667 14.98541667 . . . . 0.015274073 16.03777657
6 | 95305073_01 95305073_01_HEP3B 5.954166667 15.95416667 . . . . 0.014487834 15.21222525
7 | 95305073_01 95305073_01_HEP3B 6.842361111 16.84236111 . . . . 0.012779208 13.41816843
8 | 95305073_02 95305073_02_HEP3B 0 10 0.0231 0.000275 0.28875 0.384 . .
9 | 95305073_02 95305073_02_HEP3B 0.904861111 10.90486111 . . . . 0.021093635 22.14831705
10 | 95305073_02 95305073_02_HEP3B 3.946527778 13.94652778 . . . . 0.012500204 13.1252146
11 | 95305073_02 95305073_02_HEP3B 4.985416667 14.98541667 . . . . 0.010634318 11.16603431
12 | 95305073_02 95305073_02_HEP3B 5.954166667 15.95416667 . . . . 0.009731509 10.21808438
13 | 95305073_02 95305073_02_HEP3B 6.842361111 16.84236111 . . . . 0.009094142 9.5488486
14 |
--------------------------------------------------------------------------------
/QSPToolbox/examples/data/xenograft_data_95305073_n87.txt:
--------------------------------------------------------------------------------
1 | USUBJID LESIONID time_day time_10delayed_day mouse_weight_kg N87_xenograft_volume_L N87_xenograft_weight_g dose_nmole accumulation_N87_nmole_per_gram_tumor accumulation_N87_nM
2 | 95305073_01 95305073_01_N87 0 10 0.0234 0.000275 0.28875 0.398222222 . .
3 | 95305073_01 95305073_01_N87 0.904861111 10.90486111 . . . . 0.043004686 45.15492015
4 | 95305073_01 95305073_01_N87 3.946527778 13.94652778 . . . . 0.036532076 38.35867968
5 | 95305073_01 95305073_01_N87 4.985416667 14.98541667 . . . . 0.031291797 32.85638648
6 | 95305073_01 95305073_01_N87 5.954166667 15.95416667 . . . . 0.028603717 30.03390327
7 | 95305073_01 95305073_01_N87 6.842361111 16.84236111 . . . . 0.027529224 28.90568513
8 | 95305073_02 95305073_02_N87 0 10 0.0231 0.000144 0.1512 0.384 . .
9 | 95305073_02 95305073_02_N87 0.904861111 10.90486111 . . . . 0.042124625 44.23085675
10 | 95305073_02 95305073_02_N87 3.946527778 13.94652778 . . . . 0.032647504 34.27987931
11 | 95305073_02 95305073_02_N87 4.985416667 14.98541667 . . . . 0.028955969 30.40376693
12 | 95305073_02 95305073_02_N87 5.954166667 15.95416667 . . . . 0.023960432 25.1584534
13 | 95305073_02 95305073_02_N87 6.842361111 16.84236111 . . . . 0.023771687 24.96027157
14 |
--------------------------------------------------------------------------------
/QSPToolbox/examples/miscellaneous/adc_platform_public_v0p15p1.sbproj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BMSQSP/QSPToolbox/42cb4425292c5ecdf4954b6251346503746671d0/QSPToolbox/examples/miscellaneous/adc_platform_public_v0p15p1.sbproj
--------------------------------------------------------------------------------
/QSPToolbox/examples/miscellaneous/calculateGFunctionSi.m:
--------------------------------------------------------------------------------
1 | function [mySi,mySTi] = calculateGFunctionSi(aimatrix)
2 | % A simple function to calculate the analytical solutions for
3 | % first order (Si) and total (STi) sensitivity indices in
4 | % Sobol's G function,
5 | % given an nAi X 1 matrix of ai values
6 | % See:
7 | % Saltelli, A., et al. (2009). "Global Sensitivity Analysis: The Primer."
8 | % p. 123-125 for the analytical sensitivity index calculation.
9 | %
10 | % ARGUMENTS:
11 | % aimatrix
12 | %
13 | % RETURNS:
14 | % mySi
15 | % mySTi
16 |
17 | nAi = length(aimatrix);
18 | % vi is the variance in term
19 | vi = zeros(nAi,1);
20 | for curAiCounter = 1 : nAi
21 | vi(curAiCounter) = 1/(3*(1+aimatrix(curAiCounter))^2);
22 | end
23 |
24 | % We also calculat the total variances
25 | vti = zeros(nAi,1);
26 | for curAiCounter = 1 : nAi
27 | vti(curAiCounter) = vi(curAiCounter);
28 | for hotCounter = 2 : nAi
29 | curCombs = combnk([1:nAi],hotCounter);
30 | combFinder = (curCombs == curAiCounter);
31 | combFinder = find(sum(combFinder,2)>0);
32 | curCombs = curCombs(combFinder,:);
33 | [nRows, nCols] = size(curCombs);
34 | curTerm = 0;
35 | for curRow = 1 : nRows
36 | tempTerm = 1;
37 | for curCol = 1 : nCols
38 | tempTerm = tempTerm * vi(curCombs(curRow,curCol));
39 | end
40 | curTerm = curTerm + tempTerm;
41 | end
42 | vti(curAiCounter) = vti(curAiCounter) + curTerm;
43 | end
44 | end
45 |
46 | vProd = 1;
47 | for i = 1 : nAi
48 | vProd = vProd * (1 + vi(i));
49 | end
50 |
51 | vTot = -1 + vProd;
52 |
53 | mySi = vi / vTot;
54 | mySTi = vti / vTot;
55 |
56 | end
--------------------------------------------------------------------------------
/QSPToolbox/examples/miscellaneous/example_cohort_worksheet1.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BMSQSP/QSPToolbox/42cb4425292c5ecdf4954b6251346503746671d0/QSPToolbox/examples/miscellaneous/example_cohort_worksheet1.mat
--------------------------------------------------------------------------------
/QSPToolbox/examples/miscellaneous/example_intervention_file.txt:
--------------------------------------------------------------------------------
1 | ID culture_internalization buffer_injection_1200147_shed_assay antibody_injection_1200147_shed_assay agxab1pet_injection
2 | VARIANT cellular_disposition_payload___inert_disable_export initialization___10_day initialization___10_day initialization___10_day
3 | VARIANT tumor_pd___n87_culture_no_growth initial_masses___1200147_buffer_n87_body_mass_only initial_masses___1200147_ab1_n87_body_mass_only initial_masses___agxab1pet_95305073_n87_body_mass_only
4 | VARIANT linker_and_payload_chemistry___stable dosing_duration___ip_mouse_as_iv_infusion tumor_transport_settings_payload___null
5 | VARIANT fixed_lesion_characteristics___culture payload_adcc_effect_switches___activate_adcc_day_11
6 | VARIANT initialization___0_day
7 | VARIANT prebound_adc___all_1a
8 | VARIANT initial_masses___culture
9 | VARIANT tumor_transport_settings_payload___null
10 | DOSE antibody_injection_1200147_shed_assay agxab1_pet_20140711_avg
11 |
--------------------------------------------------------------------------------
/QSPToolbox/examples/miscellaneous/example_vp_file.txt:
--------------------------------------------------------------------------------
1 | ID n87_xenograft_scenario_0006
2 | VARIANT molecular_and_plasma_pk_parameters_payload___null
3 | VARIANT molecular_and_plasma_pk_parameters_antibody___bmsaaaaaa_agxadc_mouse
4 | VARIANT tumor_transport_settings_payload___permeation_only
5 | VARIANT tumor_transport_settings_antibody___permeation_only
6 | VARIANT cellular_disposition_payload___secrete_and_degrade_150901_scenario_6
7 | VARIANT tumor_pd___bmsaaaaaa_n87_xenograft_1200115_control_estimate_150901_1200147_n87_ab1_adcc_death_effect
8 | VARIANT linker_and_payload_chemistry___stable
9 | VARIANT antigen_antibody_binding___ab1_agx_bivalent
10 | VARIANT fixed_lesion_characteristics___bmsaaaaaa_agxab1pet_95305073_150901_scenario_6_fg_alt
11 | VARIANT cellular_disposition_antibody___ab1_n87_estimate_150901_shedding_alt
12 | VARIANT antigen_shedding_and_transport___agx_a431h9_murine_xenograft_alt_tumor_degradation_no_peripheral_dissociation
13 | VARIANT initialization___10_day
14 | VARIANT size_dependent_clearance___null
15 | VARIANT prebound_adc___none
16 | VARIANT variable_shedding___off
17 | VARIANT tumor_transport_settings_shed___permeation_only
18 | VARIANT initial_masses___agxab1pet_95305073_n87
19 | VARIANT dosing_duration___iv_bolus
20 | VARIANT payload_adcc_effect_switches___off
21 |
--------------------------------------------------------------------------------
/QSPToolbox/examples/miscellaneous/example_vpop.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BMSQSP/QSPToolbox/42cb4425292c5ecdf4954b6251346503746671d0/QSPToolbox/examples/miscellaneous/example_vpop.mat
--------------------------------------------------------------------------------
/QSPToolbox/examples/miscellaneous/gfunction_test.sbproj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BMSQSP/QSPToolbox/42cb4425292c5ecdf4954b6251346503746671d0/QSPToolbox/examples/miscellaneous/gfunction_test.sbproj
--------------------------------------------------------------------------------
/QSPToolbox/external/compare_correlation_coefficients/compare_correlation_coefficients.m:
--------------------------------------------------------------------------------
1 | % This function compare if two correlation coefficients are significantly
2 | % different.
3 | % The correlation coefficients were tansfered to z scores using fisher's r
4 | % to z transformation.
5 | % ref: http://core.ecu.edu/psyc/wuenschk/docs30/CompareCorrCoeff.pdf
6 | %--------------------------------------------------------------------------
7 | % Inputs: (1) r1: correlation coefficient of the first correlation (2) r2:
8 | % correlation coefficient of the second correlation (3) n1: number of
9 | % samples used to compute the first correlation (4) n2: number of samples
10 | % used to compute the second correlation
11 | %--------------------------------------------------------------------------
12 | % Output: (1) p: p value, the probability that H0 (the correlation
13 | % coefficiets are not different) is correct
14 | %--------------------------------------------------------------------------
15 | % Example :
16 | % x = rand(20,1);
17 | % y1= x+rand(20,1)*0.05;
18 | % y2= x+rand(20,1)*0.5;
19 | % r1=corr(x,y1);
20 | % r1=corr(x,y2);
21 | % p = compare_correlation_coefficients(r1,r2,length(x),length(x));
22 | %--------------------------------------------------------------------------
23 | function p = compare_correlation_coefficients(r1,r2,n1,n2)
24 | t_r1 = 0.5*log((1+r1)/(1-r1));
25 | t_r2 = 0.5*log((1+r2)/(1-r2));
26 | z = (t_r1-t_r2)/sqrt(1/(n1-3)+1/(n2-3));
27 | p = (1-normcdf(abs(z),0,1))*2;
28 | end
--------------------------------------------------------------------------------
/QSPToolbox/external/compare_correlation_coefficients/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013, Sisi Ma
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/QSPToolbox/external/genpath_exclude/genpath_exclude.m:
--------------------------------------------------------------------------------
1 | % pathStr = genpath_exclude(basePath,ignoreDirs)
2 | %
3 | % Extension of Matlab's "genpath" function, except this will exclude
4 | % directories (and their sub-tree) given by "ignoreDirs".
5 | %
6 | %
7 | %
8 | % Inputs:
9 | % basePath: string. The base path for which to generate path string.
10 | %
11 | % excludeDirs: cell-array of strings. all directory names to ignore. Note,
12 | % these strings are passed into regexp surrounded by
13 | % '^' and '$'. If your directory name contains special
14 | % characters to regexp, they must be escaped. For example,
15 | % use '\.svn' to ignore ".svn" directories. You may also
16 | % use regular expressions to ignore certian patterns. For
17 | % example, use '*._ert_rtw' to ignore all directories ending
18 | % with "_ert_rtw".
19 | %
20 | % Outputs:
21 | % pathStr: string. semicolon delimited string of paths. (see genpath)
22 | %
23 | % See also genpath
24 | %
25 | % ---CVS Keywords----
26 | % $Author: jhopkin $
27 | % $Date: 2009/10/27 19:06:19 $
28 | % $Name: $
29 | % $Revision: 1.5 $
30 |
31 | % $Log: genpath_exclude.m,v $
32 | % Revision 1.6 2020/11/26 19:06:19 bjs
33 | % Exclude MATLAB "package" directories, "+"
34 | %
35 | % Revision 1.5 2009/10/27 19:06:19 jhopkin
36 | % fixed regexp handling. added more help comments
37 | %
38 | % Revision 1.4 2008/11/25 19:04:29 jhopkin
39 | % minor cleanup. Made input more robust so that if user enters a string as 'excudeDir' rather than a cell array of strings this function will still work. (did this by moving the '^' and '$' to surround the entire regexp string, rather than wrapping them around each "excludeDir")
40 | %
41 | % Revision 1.3 2008/11/25 18:43:10 jhopkin
42 | % added help comments
43 | %
44 | % Revision 1.1 2008/11/22 00:23:01 jhopkin
45 | % *** empty log message ***
46 | %
47 |
48 | function p = genpath_exclude(d,excludeDirs)
49 | % if the input is a string, then use it as the searchstr
50 | if ischar(excludeDirs)
51 | excludeStr = excludeDirs;
52 | else
53 | excludeStr = '';
54 | if ~iscellstr(excludeDirs)
55 | error('excludeDirs input must be a cell-array of strings');
56 | end
57 |
58 | for i = 1:length(excludeDirs)
59 | excludeStr = [excludeStr '|^' excludeDirs{i} '$'];
60 | end
61 | end
62 |
63 |
64 | % Generate path based on given root directory
65 | files = dir(d);
66 | if isempty(files)
67 | return
68 | end
69 |
70 | % Add d to the path even if it is empty.
71 | p = [d pathsep];
72 |
73 | % set logical vector for subdirectory entries in d
74 | isdir = logical(cat(1,files.isdir));
75 | %
76 | % Recursively descend through directories which are neither
77 | % private nor "class" directories.
78 | %
79 | dirs = files(isdir); % select only directory entries from the current listing
80 |
81 | for i=1:length(dirs)
82 | dirname = dirs(i).name;
83 | %NOTE: regexp ignores '.', '..', '@.*', and 'private' directories by default.
84 | if ~any(regexp(dirname,['^\.$|^\.\.$|^\@.*|^\+.*|^private$|^resources$|' excludeStr ],'start'))
85 | p = [p genpath_exclude(fullfile(d,dirname),excludeStr)]; % recursive calling of this function.
86 | end
87 | end
88 | end
89 |
--------------------------------------------------------------------------------
/QSPToolbox/external/genpath_exclude/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009, Jesse Hopkins
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/QSPToolbox/external/herrorbar/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009, Jos van der Geest
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/QSPToolbox/external/kstest_2s_2d/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017, Dylan Muir
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/QSPToolbox/external/kstest_2s_2d/quadrantCount.m:
--------------------------------------------------------------------------------
1 | function quadrantChecks = quadrantCount(x1, x2)
2 | % This function is roughly a 2D equivalent to creating the comparison grid for the
3 | % 1D KS test. Here, all of the quadrant comparisons are run for each point in
4 | % x1 as a reference against x2
5 | %
6 | % Arguments
7 | % x1: 2xN1 matrix of reference points
8 | % x2: 2xN2 matrix of reference points
9 | %
10 | % Returns
11 | % quadrantChecks N1x(4 quadrants * N2)
12 | % matrix of binary comparisons
13 |
14 | [~,nsample1] = size(x1);
15 | [~,nsample2] = size(x2);
16 |
17 | % - A function handle to perform comparisons in all possible directions
18 | pointCompare = @(x, point)([((x(1,:) > point(1)) & (x(2,:) > point(2))),...
19 | ((x(1, :) <= point(1)) & (x(2, :) > point(2))),...
20 | ((x(1, :) <= point(1)) & (x(2, :) <= point(2))),...
21 | ((x(1, :) > point(1)) & (x(2, :) <= point(2)))]);
22 |
23 | quadrantChecks = false(nsample1,4*nsample2);
24 | for j = 1:(nsample1)
25 | point = x1(:,j);
26 | quadrantChecks(j,:) = pointCompare(x2, point);
27 | end
28 |
29 |
30 |
--------------------------------------------------------------------------------
/QSPToolbox/external/myfisher/README.md:
--------------------------------------------------------------------------------
1 | # myfisher
2 | Fisher's Exact Probability Test for a RxC matrix.
3 | Fisher's exact test permits calculation of precise probabilities in situation
4 | where, as a consequence of small cell frequencies, the much more rapid normal
5 | approximation and chi-square calculations are liable to be inaccurate.
6 | The Fisher's exact test involves the computations of several factorials
7 | to obtain the probability of the observed and each of the more extreme tables.
8 | Factorials growth quickly, so it's necessary use logarithms of factorials.
9 | This computations is very easy in Matlab because:
10 | x!=gamma(x+1) and log(x!)=gammaln(x+1).
11 | Moreover, when the matrix has many Rows and Columns, the computation of all the
12 | set of possible matrices is very time expensive.
13 | This function uses this strategy:
14 | 1) if the input is a 2x2, 2x3, 2x4 or 3x3 matrix it uses (or download) ad hoc,
15 | previously written by me, function;
16 | 2) else it uses a Monte Carlo approach.
17 | Finally, this function uses the Peter J. Acklam rldecode function, and so I
18 | want to acknowledge him.
19 |
20 | Created by Giuseppe Cardillo
21 | giuseppe.cardillo-edta@poste.it
22 |
23 | To cite this file, this would be an appropriate format:
24 | Cardillo G. (2010) MyFisher: the definitive function for the Fisher's exact
25 | and conditional test for any RxC matrix
26 | http://www.mathworks.com/matlabcentral/fileexchange/26883
27 |
--------------------------------------------------------------------------------
/QSPToolbox/external/myfisher22/README.md:
--------------------------------------------------------------------------------
1 | # myfisher22
2 | Fisher's exact test onto a 2x2 matrix
3 | Fisher's exact test of 2x2 contingency tables permits calculation of
4 | precise probabilities in situation where, as a consequence of small cell
5 | frequencies, the much more rapid normal approximation and chi-square
6 | calculations are liable to be inaccurate. The Fisher's exact test involves
7 | the computations of several factorials to obtain the probability of the
8 | observed and each of the more extreme tables. Factorials growth quickly,
9 | so it's necessary use logarithms of factorials. This computations is very
10 | easy in Matlab because x!=gamma(x+1) and log(x!)=gammaln(x+1). This
11 | function is fully vectorized to speed up the computation.
12 | The routine coumputes the Power and, if necessary, the sample sizes needed
13 | to achieve a power=0.80 using a modified asymptotic normal method with
14 | continuity correction as described by Hardeo Sahai and Anwer Khurshid in
15 | Statistics in Medicine, 1996, Vol. 15, Issue 1: 1-21.
16 |
17 | Syntax: myfisher22(x,alpha,plts)
18 |
19 | Inputs:
20 | X - 2x2 data matrix
21 | ALPHA - significance level (default = 0.05).
22 | PLTS - Flag to set if you don't want (0) or want (1) view the plot
23 | of Wald Statistics distribution (default=0)
24 | Outputs:
25 | - Three p-values
26 | - Power and sample sizes
27 |
28 | Created by Giuseppe Cardillo
29 | giuseppe.cardillo-edta@poste.it
30 |
31 | To cite this file, this would be an appropriate format:
32 | Cardillo G. (2007) MyFisher22: a very compact routine for Fisher's exact
33 | test on 2x2 matrix
34 | http://www.mathworks.com/matlabcentral/fileexchange/15434
35 |
--------------------------------------------------------------------------------
/QSPToolbox/external/myfisher23/README.md:
--------------------------------------------------------------------------------
1 | # myfisher23
2 | Fisher's Exact Probability Test on 2x3 matrix.
3 | Fisher's exact test of 2x3 contingency tables permits calculation of
4 | precise probabilities in situation where, as a consequence of small cell
5 | frequencies, the much more rapid normal approximation and chi-square
6 | calculations are liable to be inaccurate. The Fisher's exact test involves
7 | the computations of several factorials to obtain the probability of the
8 | observed and each of the more extreme tables. Factorials growth quickly,
9 | so it's necessary use logarithms of factorials. This computations is very
10 | easy in Matlab because x!=gamma(x+1) and log(x!)=gammaln(x+1). This
11 | function is fully vectorized to speed up the computation.
12 |
13 | Syntax: p=myfisher23(x)
14 |
15 | Inputs:
16 | X - 2x3 data matrix
17 | Outputs:
18 | - Three p-values
19 |
20 | Created by Giuseppe Cardillo
21 | giuseppe.cardillo-edta@poste.it
22 |
23 | To cite this file, this would be an appropriate format:
24 | Cardillo G. (2007) MyFisher23: a very compact routine for Fisher's exact
25 | test on 2x3 matrix
26 | http://www.mathworks.com/matlabcentral/fileexchange/15399
27 |
--------------------------------------------------------------------------------
/QSPToolbox/external/myfisher24/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2008, Giuseppe Cardillo
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/QSPToolbox/external/nnls/Readme.txt:
--------------------------------------------------------------------------------
1 | nnls - Alternative to lsqnonneg: can be faster on large problems,
2 | improved convergence control, optional restart vector
3 |
4 | Solves non negative least squares:
5 | min wrt x: (d-Cx)'*(d-Cx) subject to: x>=0
6 |
7 | This version of nnls aims to solve convergance problems that can occur
8 | with the 2011-2012 version of lsqnonneg, and provides a fast solution of
9 | large problems. Includes an option to give initial positive terms for x
10 | for faster solution of iterative problems using nnls.
11 |
12 | For some large problems nnls can be faster than lsqnonneg,
13 | see test file (nnlstest.m).
14 |
15 |
16 | Simple usage: x=nnls(C,d)
17 |
18 | [x,w,info]=nnls(C,d,opts)
19 | C Coefficient matrix
20 | d Rhs vector
21 | opts Struct containing options: (optional)
22 | .Accy 0 fast version, 1 refines final value (default),
23 | 2 uses accurate steps but very slow on large cases,
24 | faster on small cases, result usually identical to 1
25 | .Order True or [], or order to initially include positive terms
26 | if included will supply info.Order, if x0 available use
27 | find(x0>0), but best saved from previous run of nnls
28 | .Tol Tolerance test value, default zero, use multiple of eps
29 | .Iter Maximum number of iterations, should not be needed.
30 |
31 | x Positive solution vector x>=0
32 | w Lagrange multiplier vector w(x==0)<= approx zero
33 | info Struct with extra information:
34 | .iter Number of iterations used
35 | .wsc0 Estimated size of errors in w
36 | .wsc Maximum of test values for w
37 | .Order Order variables used, use to restart nnls with opts.Order
38 |
39 | Examples in nnlstest.m
40 |
--------------------------------------------------------------------------------
/QSPToolbox/external/nnls/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012, Bill Whiten
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/QSPToolbox/external/weightedcorrs/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2008, Liber Eleutherios
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/QSPToolbox/external/weightedcorrs/weightedcorrs.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BMSQSP/QSPToolbox/42cb4425292c5ecdf4954b6251346503746671d0/QSPToolbox/external/weightedcorrs/weightedcorrs.m
--------------------------------------------------------------------------------
/QSPToolbox/initQSPToolbox.m:
--------------------------------------------------------------------------------
1 | function initQSPtoolbox()
2 | % Initialize Quantiative Systems Pharmacology Toolbox. This script should
3 | % be run from the command line when you want to start using the toolbox.
4 | % ARGUMENTS
5 | % None
6 | %
7 | % RETURNS
8 | % None
9 | %
10 |
11 | % Get the toolbox directory
12 | rootPath=which('initQSPToolbox.m');
13 | global QSPTDIR
14 | QSPTDIR = rootPath(1:end-(length('initQSPToolbox.m')+1));
15 |
16 | % Add QSP toolbox paths
17 | path(path,[QSPTDIR, filesep, 'external',filesep,'genpath_exclude']);
18 | myPaths = genpath_exclude(QSPTDIR,{'docs','\.svn'});
19 | if (~isdeployed)
20 | addpath(myPaths);
21 | end
22 |
--------------------------------------------------------------------------------
/QSPToolbox/io/loadMapelOptions.m:
--------------------------------------------------------------------------------
1 | function myMapelOptions = loadMapelOptions(myFileName, myPath, myFormat)
2 | % Load a mapelOptions object from file.
3 | %
4 | % ARGUMENTS
5 | % fileName: a filename, suffix will be appended based on format
6 | % path: (optional) save file path
7 | % format: (optional)save file format, currently only support 'mat'
8 | %
9 | % RETURNS
10 | % myMapelOptions
11 | %
12 |
13 | % Perform initial checks on the provided arguments
14 | flagContinue = true;
15 | if nargin > 3
16 | warning(['Too many arguments provided to ',mfilename,', require: fileName, and optionally path, format.'])
17 | flagContinue = false;
18 | elseif nargin > 2
19 | flagContinue = true;
20 | elseif nargin > 1
21 | myFormat = 'mat';
22 | flagContinue = true;
23 | elseif nargin > 0
24 | myPath = '';
25 | flagContinue = true;
26 | myFormat = 'mat';
27 | else
28 | warning(['Insufficient arguments provided to ',mfilename,', require: fileName, and optionally path, format.'])
29 | flagContinue = false;
30 | end
31 | myMapelOptions = mapelOptions;
32 |
33 | if flagContinue
34 | if ~(sum(ismember({'mat'},lower(myFormat))) == 1)
35 | warning(['Unsupported file format specified in ',mfilename,'. Support: "mat".'])
36 | flagContinue = false;
37 | else
38 | myFormat = lower(myFormat);
39 | % This doesn't need to be specified for load
40 | % saveVersion = '-v7.3';
41 | end
42 | end
43 |
44 | if flagContinue
45 | if strcmp('mat', myFormat)
46 | fullFileName = [myPath,myFileName,'.',myFormat];
47 | myMapelOptions = load(fullFileName, '-mat');
48 | myMapelOptions = myMapelOptions.myMapelOptions;
49 | myMapelOptions = checkUpdateObjectVersion(myMapelOptions);
50 | end
51 | else
52 | warning('Unable to load in ',mfilename,'. Returning a blank mapelOptions.')
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/QSPToolbox/io/loadVPop.m:
--------------------------------------------------------------------------------
1 | function myVPop = loadVPop(myFileName, myPath, myFormat)
2 | % Load a virtual population from file.
3 | %
4 | % ARGUMENTS
5 | % fileName: a filename, suffix will be appended based on format
6 | % path: (optional) save file path
7 | % format: (optional)save file format, currently only support 'mat'
8 | %
9 | % RETURNS
10 | % myVPop
11 | %
12 |
13 | % Perform initial checks on the provided arguments
14 | flagContinue = true;
15 | if nargin > 3
16 | warning(['Too many arguments provided to ',mfilename,', require: fileName, and optionally path, format.'])
17 | flagContinue = false;
18 | elseif nargin > 2
19 | flagContinue = true;
20 | elseif nargin > 1
21 | myFormat = 'mat';
22 | flagContinue = true;
23 | elseif nargin > 0
24 | myPath = '';
25 | flagContinue = true;
26 | myFormat = 'mat';
27 | else
28 | warning(['Insufficient arguments provided to ',mfilename,', require: fileName, and optionally path, format.'])
29 | flagContinue = false;
30 | end
31 | myVPop = VPop;
32 |
33 | if flagContinue
34 | if ~(sum(ismember({'mat'},lower(myFormat))) == 1)
35 | warning(['Unsupported file format specified in ',mfilename,'. Support: "mat".'])
36 | flagContinue = false;
37 | else
38 | myFormat = lower(myFormat);
39 | % This doesn't need to be specified for load
40 | % saveVersion = '-v7.3';
41 | end
42 | end
43 |
44 | if flagContinue
45 | if strcmp('mat', myFormat)
46 | fullFileName = [myPath,myFileName,'.',myFormat];
47 | myVPop = load(fullFileName, '-mat');
48 | myVPop = myVPop.myVPop;
49 | myVPop = checkUpdateObjectVersion(myVPop);
50 | end
51 | else
52 | warning('Unable to load in ',mfilename,'. Returning a blank VPop.')
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/QSPToolbox/io/loadWorksheetAutoMerge.m:
--------------------------------------------------------------------------------
1 | function myWorksheet = loadWorksheetAutoMerge(myFileName, myPath, myFormat)
2 | % Load a worksheet to file.
3 | %
4 | % ARGUMENTS
5 | % fileName: a filename, suffix will be appended based on format
6 | % path: (optional) save file path
7 | % format: (optional)save file format, currently only support 'mat'
8 | %
9 | % RETURNS
10 | % myWorksheet
11 | %
12 |
13 | % Perform initial checks on the provided arguments
14 | flagContinue = true;
15 | if nargin > 3
16 | warning(['Too many arguments provided to ',mfilename,', require: fileName, and optionally path, format.'])
17 | flagContinue = false;
18 | elseif nargin > 2
19 | flagContinue = true;
20 | elseif nargin > 1
21 | myFormat = 'mat';
22 | flagContinue = true;
23 | elseif nargin > 0
24 | myPath = '';
25 | flagContinue = true;
26 | myFormat = 'mat';
27 | else
28 | warning(['Insufficient arguments provided to ',mfilename,', require: fileName, and optionally path, format.'])
29 | flagContinue = false;
30 | end
31 | %myWorksheet = createWorksheet();
32 |
33 | if flagContinue
34 | if ~(sum(ismember({'mat'},lower(myFormat))) == 1)
35 | warning(['Unsupported file format specified in ',mfilename,'. Support: "mat".'])
36 | flagContinue = false;
37 | else
38 | myFormat = lower(myFormat);
39 | % saveVersion doesn't need to be specified for load
40 | end
41 | end
42 |
43 | if flagContinue
44 | if strcmp('mat', myFormat)
45 | checkFiles = 0;
46 | checkFileName = [myPath,[myFileName,'___',num2str(checkFiles+1)],'.',myFormat];
47 | while exist(checkFileName,'file') == 2
48 | checkFiles = checkFiles + 1;
49 | checkFileName = [myPath,[myFileName,'___',num2str(checkFiles+1)],'.',myFormat];
50 | end
51 | if checkFiles>0
52 | myWorksheet = loadWorksheet([myFileName,'___',num2str(1)], myPath, myFormat);
53 | for splitCounter=2:(checkFiles)
54 | curWorksheet = loadWorksheet([myFileName,'___',num2str(splitCounter)], myPath, myFormat);
55 | myWorksheet=mergeWorksheets(myWorksheet,curWorksheet);
56 | end
57 | else
58 | myWorksheet = loadWorksheet(myFileName, myPath, myFormat);
59 | end
60 | end
61 | else
62 | warning(['Unable to load in ',mfilename,'. Returning an empty worksheet.'])
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/QSPToolbox/io/saveMapelOptions.m:
--------------------------------------------------------------------------------
1 | function saveMapelOptions(myMapelOptions,myFileName, myFormat, myPath)
2 | % Save a mapelOptions object to file.
3 | %
4 | % ARGUMENTS
5 | % myMapelOptions: a mapelOptions object
6 | % fileName: a filename, suffix will be appended based on format
7 | % format: (optional)save file format, currently only support 'mat'
8 | % path: (optional) save file path
9 | %
10 | % RETURNS
11 | % nothing
12 | %
13 |
14 | % Perform initial checks on the provided arguments
15 | flagContinue = true;
16 | if nargin > 4
17 | warning(['Too many arguments provided to ',mfilename,', require: myMapelOptions, fileName, and optionally format, path.'])
18 | flagContinue = false;
19 | elseif nargin > 3
20 | flagContinue = true;
21 | elseif nargin > 2
22 | myPath = '';
23 | flagContinue = true;
24 | elseif nargin > 1
25 | myPath = '';
26 | flagContinue = true;
27 | myFormat = 'mat';
28 | else
29 | warning(['Insufficient arguments provided to ',mfilename,', require: myMapelOptions, fileName, and optionally format, path.'])
30 | flagContinue = false;
31 | end
32 |
33 | % Create the new worksheet and verify the IDs
34 | if flagContinue
35 | if ~(sum(ismember({'mat'},lower(myFormat))) == 1)
36 | warning(['Unsupported file format specified in ',mfilename,'. Support: "mat".'])
37 | flagContinue = false;
38 | else
39 | myFormat = lower(myFormat);
40 | % Force v7.3, which is needed to save files > 2GB.
41 | % However, the HDF5 format used by v7.3 may be slow.
42 | % I'm still exploring whether any optimization is possible or
43 | % needed to improve read/write times.
44 | saveVersion = '-v7.3';
45 | end
46 | end
47 |
48 | if flagContinue
49 | if strcmp('mat', myFormat)
50 | fullFileName = [myPath,myFileName,'.',myFormat];
51 | save(fullFileName, 'myMapelOptions', saveVersion);
52 | end
53 | else
54 | warning('Unable to save in ',mfilename,'. Exiting without save...')
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/QSPToolbox/io/saveVPop.m:
--------------------------------------------------------------------------------
1 | function saveVPop(myVPop,myFileName, myFormat, myPath)
2 | % Save a VPop object to file.
3 | %
4 | % ARGUMENTS
5 | % myVPop: a VPop
6 | % fileName: a filename, suffix will be appended based on format
7 | % format: (optional)save file format, currently only support 'mat'
8 | % path: (optional) save file path
9 | %
10 | % RETURNS
11 | % nothing
12 | %
13 |
14 | % Perform initial checks on the provided arguments
15 | flagContinue = true;
16 | if nargin > 4
17 | warning(['Too many arguments provided to ',mfilename,', require: myVPop, fileName, and optionally format, path.'])
18 | flagContinue = false;
19 | elseif nargin > 3
20 | flagContinue = true;
21 | elseif nargin > 2
22 | myPath = '';
23 | flagContinue = true;
24 | elseif nargin > 1
25 | myPath = '';
26 | flagContinue = true;
27 | myFormat = 'mat';
28 | else
29 | warning(['Insufficient arguments provided to ',mfilename,', require: myVPop, fileName, and optionally format, path.'])
30 | flagContinue = false;
31 | end
32 |
33 | % Create the new worksheet and verify the IDs
34 | if flagContinue
35 | if ~(sum(ismember({'mat'},lower(myFormat))) == 1)
36 | warning(['Unsupported file format specified in ',mfilename,'. Support: "mat".'])
37 | flagContinue = false;
38 | else
39 | myFormat = lower(myFormat);
40 | % Force v7.3, which is needed to save files > 2GB.
41 | % However, the HDF5 format used by v7.3 may be slow.
42 | % I'm still exploring whether any optimization is possible or
43 | % needed to improve read/write times.
44 | saveVersion = '-v7.3';
45 | end
46 | end
47 |
48 | if flagContinue
49 | if strcmp('mat', myFormat)
50 | fullFileName = [myPath,myFileName,'.',myFormat];
51 | % This is fast to recalculate and can take up space on disk
52 | myVPop.coeffsDist='';
53 | save(fullFileName, 'myVPop', saveVersion);
54 | end
55 | else
56 | warning('Unable to save in ',mfilename,'. Exiting without save...')
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/QSPToolbox/io/writeResultStruct.m:
--------------------------------------------------------------------------------
1 | function myFID = writeResultStruct(myResult, myFileName)
2 | % This function takes a results structure and writes it to a tab-delimited
3 | % text file. Note that you need to include the file extension in
4 | % myFileName and should be in the desired directory.
5 | %
6 | % ARGUMENTS
7 | % myResult: A struct with the desired data;
8 | % essentially a result struct.
9 | % myFileName: The name of the file to write to.
10 | %
11 | % RETURNS
12 | % myFID: A file identifier for MATLAB.
13 | %
14 |
15 | % Perform initial checks on the provided arguments
16 | flagContinue = true;
17 |
18 | myFID = 0;
19 |
20 | if nargin > 2
21 | warning(['Too many input arguments to ',mfilename,'. Require: mySimStruct, myFileName.'])
22 | flagContinue = false;
23 | elseif nargin < 2
24 | warning(['Insufficient input arguments to ',mfilename,'. Require: mySimStruct, myFileName.'])
25 | flagContinue = false;
26 | end
27 |
28 | if flagContinue
29 | if ~strcmp(class(myResult),'struct')
30 | warning(['Expecting a result structure with "Name" and "Data" fields in call to ',mfilename,'. Exiting.'])
31 | flagContinue = false;
32 | end
33 | if ~strcmp(class(myFileName),'char')
34 | warning(['Expecting a string for a filename in call to ',mfilename,'. Exiting.'])
35 | flagContinue = false;
36 | end
37 | end
38 |
39 | if flagContinue
40 | if ~((sum(ismember(fields(myResult),'Names')) == 1) & (sum(ismember(fields(myResult),'Data')) == 1))
41 | warning(['Expecting a result structure with "Name" and "Data" fields in call to ',mfilename,'. Exiting.'])
42 | flagContinue = false;
43 | end
44 | end
45 |
46 | if flagContinue
47 | myFID=fopen(myFileName,'wt');
48 | nCols = length(myResult.Names);
49 | for colCounter = 1:nCols-1
50 | fprintf(myFID,[myResult.Names{colCounter},'\t']);
51 | end
52 | fprintf(myFID, [myResult.Names{nCols},'\n']);
53 | [nRows,nCols] = size(myResult.Data);
54 | for rowCounter = 1:nRows
55 | fprintf(myFID,'%e\t',myResult.Data(rowCounter,1:(nCols-1)));
56 | fprintf(myFID,'%e\n',myResult.Data(rowCounter,nCols));
57 | end
58 | fclose(myFID);
59 | else
60 | warning(['Unable to complete ', mfilename,', exiting.'])
61 | end
62 | end
63 |
--------------------------------------------------------------------------------
/QSPToolbox/plotting/plotCoefficients.m:
--------------------------------------------------------------------------------
1 | function plotHandle = plotCoefficients(myWorksheet, myPlotCoefficientsOptions)
2 | % This function plots the axis coefficients for all of the VPs in a
3 | % worksheet.
4 | %
5 | % ARGUMENTS
6 | % myWorksheet: (required) Worksheet with coefficients
7 | % myPlotCoefficientsOptions: (optional) Optional structure to adjust the plotting
8 | %
9 | % RETURNS
10 | % plotHandle
11 | %
12 | plotHandle = [];
13 | flagExpData = false;
14 |
15 | if nargin > 2
16 | flagContinue = false;
17 | warning(['Too many input arguments to ',mfilename,'. Required: myWorksheet; optional: myPlotCoefficientsOptions.'])
18 | elseif nargin > 1
19 | flagContinue = true;
20 | elseif nargin > 0
21 | flagContinue = true;
22 | myPlotCoefficientsOptions = plotCoefficientsOptions;
23 | end
24 |
25 | if flagContinue
26 | if ~strcmp(class(myPlotCoefficientsOptions),'plotCoefficientsOptions')
27 | flagContinue = false;
28 | warning('Invalid plotOptions for ',mfilename,'.')
29 | end
30 | allCoefficients = (getVPCoeffs(myWorksheet));
31 | [nAxis, nVP] = size(allCoefficients);
32 | if nAxis < 1
33 | flagContinue = false;
34 | warning('Worksheet contains no axes to plot for call to ',mfilename,'.')
35 | end
36 | end
37 |
38 | if (flagContinue)
39 | allCoefficients = transpose(allCoefficients);
40 | allAxisIDs = getAxisDefIDs(myWorksheet);
41 | nAxis = length(allAxisIDs);
42 | rng('default');
43 | randColors = rand(nVP,3);
44 | jitterVals = 0.5*rand(nVP,1)-.25;
45 | plotHandle = figure;
46 | plotOrder = 1:nAxis;
47 | if myPlotCoefficientsOptions.flagSort
48 | coefficientRange = max(allCoefficients,[],1) - min(allCoefficients,[],1);
49 | [~, plotOrder] = sort(coefficientRange,'ascend');
50 | end
51 | for plotCounter = 1 : nAxis
52 | subplot(nAxis, 1, plotCounter);
53 | yPos = (nAxis - plotCounter)/(nAxis+1) + 0.5/(nAxis+1);
54 | pos = get(gca, 'Position');
55 | pos(1) = myPlotCoefficientsOptions.leftPosition;
56 | pos(3) = myPlotCoefficientsOptions.width;
57 | set(gca, 'Position', pos);
58 | [ksdens, u, bb]=ksdensity(allCoefficients(:,plotOrder(plotCounter)));
59 | ksdens=ksdens/max(ksdens)*0.3;
60 | median=nanmedian(allCoefficients(:,plotOrder(plotCounter)));
61 | scatter(allCoefficients(:,plotOrder(plotCounter)),jitterVals,10,randColors,'filled');
62 | ylim([-0.3 0.3]);
63 | xlim(myPlotCoefficientsOptions.xLim);
64 | set(gca, 'YTick', [0]);
65 | set(gca, 'YTickLabel', {allAxisIDs{plotOrder(plotCounter)}},'TickLabelInterpreter','none');
66 | set(gca,'box','on');
67 | grid on;
68 | set(gca,'fontsize', myPlotCoefficientsOptions.fontSize);
69 | if plotCounter < nAxis
70 | set(gca,'XTickLabel', '');
71 | end
72 | end
73 | if myPlotCoefficientsOptions.flagSave
74 | if length(myPlotCoefficientsOptions.fileName) > 0
75 | print([myPlotCoefficientsOptions.fileName,'.tif'],'-dtiff','-r300');
76 | else
77 | theDate = date;
78 | formatOut = 'yymmdd';
79 | theDate = datestr(theDate,formatOut);
80 | print(['worksheetAxisCoefficients_',theDate,'.tif'],'-dtiff','-r300');
81 | end
82 | end
83 | end
84 |
85 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/classes/@VPop/assignCoeffs.m:
--------------------------------------------------------------------------------
1 | function obj = assignCoeffs(obj, myWorksheet)
2 | % Copy the VP coefficients from a worksheet to the `coeffsTable` property of the
3 | % VPop object.
4 | %
5 | % EXAMPLE
6 | % >> myVPop.assignCoeffs(myWorksheet)
7 | %
8 | % SEE ALSO
9 | % VPop.coeffsTable
10 | mycoeffsTable = getVPCoeffs(myWorksheet);
11 | obj.coeffsTable = mycoeffsTable;
12 | end
13 |
--------------------------------------------------------------------------------
/QSPToolbox/population/classes/@VPop/assignIndices.m:
--------------------------------------------------------------------------------
1 | function obj = assignIndices(obj, myWorksheet, myMapelOptions)
2 | % This method takes a worksheet and mapelOptions structure and
3 | % creates a bin table and other poperties needed for the virtual
4 | % population and MAPEL algorithm.
5 | %
6 | % ARGUMENT
7 | % (self)
8 | % myWorksheet: a worksheet structure, with VPs, axes, and
9 | % coefficients
10 | % myMapelOptions: an instace of mapelOptions, with
11 | % properties
12 | % nBins
13 | % equalBinBreaks
14 | %
15 | % RETURNS
16 | % (self): properties of the virtual population are updated:
17 | % indexTable
18 | % binEdges
19 | % binMidPoints
20 | %
21 | % SEE ALSO
22 | % VPop.indexTable, VPop.binEdges, VPop.binMidPoints
23 | % mapelOptions
24 |
25 | myVPCoeffs = getVPCoeffs(myWorksheet);
26 | [nAxis, nVP] = size(myVPCoeffs);
27 | myIndexTable = ones(nAxis, nVP);
28 | nBins = myMapelOptions.nBins;
29 | myBinEdges = nan(nAxis, (nBins+1));
30 | myBinMidPoints = nan(nAxis, nBins);
31 | equalBinBreaks = myMapelOptions.equalBinBreaks;
32 | for axisCounter = 1 : nAxis
33 | % We currently only implement continuous variables from
34 | % the paper/R MAPEL
35 | if equalBinBreaks
36 | % Rather than scaling based on the sampled min and
37 | % max as in the R MAPEL algorithm, we adjust according
38 | % to the allowed,
39 | % and this range is [0, 1] by the axis definition.
40 | myBinEdges(axisCounter,:) = (0:1/nBins:1);
41 | else
42 | myPercentiles = (0:1/nBins:1)';
43 | myBinEdges(axisCounter,:) = (quantile(myVPCoeffs(axisCounter,:),myPercentiles));
44 | end
45 | % We'll use the cdf convention that FX(x) = P(X <= x), so
46 | % check if a value is <= the bin upper cutoff in order to
47 | % assign it.
48 | % Note that effectively we want to ignore the first bin of 0
49 | % as a cutoff and lump this in with the first bin.
50 | for binCounter = 1 : nBins
51 | myBinMidPoints(axisCounter,binCounter) = (myBinEdges(axisCounter,binCounter) + myBinEdges(axisCounter,binCounter+1))/2;
52 | % First bins are assigned an index of 0 by this method.
53 | myIndexTable(axisCounter, :) = myIndexTable(axisCounter, :) + (myVPCoeffs(axisCounter, :) > myBinEdges(axisCounter,binCounter+1));
54 | end
55 | end
56 | obj.indexTable = myIndexTable;
57 | obj.binEdges = myBinEdges;
58 | obj.binMidPoints = myBinMidPoints;
59 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/classes/@VPop/get.m:
--------------------------------------------------------------------------------
1 | function value = get(obj, propName)
2 | % value = get(vpop, propName) get the value of property `propName` from the virtual
3 | % population object.
4 | switch propName
5 | case 'coeffsTable'
6 | value = obj.coeffsTable;
7 | case 'coeffsDist'
8 | value = obj.coeffsDist;
9 | case 'pwStrategy'
10 | value = obj.pwStrategy;
11 | case 'indexTable'
12 | value = obj.indexTable;
13 | case 'binEdges'
14 | value = obj.binEdges;
15 | case 'binMidPoints'
16 | value = obj.binMidPoints;
17 | case 'binProbs'
18 | value = obj.binProbs;
19 | case 'pws'
20 | value = obj.pws;
21 | case 'mnSDTable'
22 | value = obj.mnSDTable;
23 | case 'binTable'
24 | value = obj.binTable;
25 | case 'distTable'
26 | value = obj.distTable;
27 | case 'distTable2D'
28 | value = obj.distTable2D;
29 | case 'corTable'
30 | value = obj.corTable;
31 | case 'subpopTable'
32 | value = obj.subpopTable;
33 | case 'expData'
34 | value = obj.expData;
35 | case 'simData'
36 | value = obj.simData;
37 | case 'gofMn'
38 | value = obj.gofMn;
39 | case 'gofSD'
40 | value = obj.gofSD;
41 | case 'gofBin'
42 | value = obj.gofBin;
43 | case 'gofDist'
44 | value = obj.gofDist;
45 | case 'gofDist2D'
46 | value = obj.gofDist2D;
47 | case 'gofCor'
48 | value = obj.gofCor;
49 | case 'gof'
50 | value = obj.gof;
51 | case 'spreadOut'
52 | value = obj.spreadOut;
53 | case 'minIndPVal'
54 | value = obj.minIndPVal;
55 | case 'useEffN'
56 | value = obj.useEffN;
57 | case 'exactFlag'
58 | value = obj.exactFlag;
59 | case 'optimizeTimeLimit'
60 | value = obj.optimizeTimeLimit;
61 | case 'optimizeType'
62 | value = obj.optimizeType;
63 | case 'optimizePopSize'
64 | value = obj.optimizePopSize;
65 | case 'objectiveLimit'
66 | value = obj.objectiveLimit;
67 | case 'poolRestart'
68 | value = obj.poolRestart;
69 | case 'poolClose'
70 | value = obj.poolClose;
71 | case 'intSeed'
72 | value = obj.intSeed;
73 | case 'tol'
74 | value = obj.tol;
75 | case 'nIters'
76 | value = obj.nIters;
77 | case 'minEffN'
78 | value = obj.minEffN;
79 | otherwise
80 | error(['Error: ',propName ,' is not a valid ',mfilename,' property.'])
81 | end
82 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/classes/@VPop/startPWs.m:
--------------------------------------------------------------------------------
1 | function obj = startPWs(obj, myWorksheet, myRandomStart)
2 | % This method initializes pws, and is used
3 | % prior to the optimization.
4 | % Only relevant for obj.pwStrategy = 'direct'
5 | %
6 | % ARGUMENTS
7 | % (self)
8 | % myRandomStart: A boolean variable (true/false), if true
9 | % prevalence weights will be set
10 | % randomly and if false they will be uniform
11 | %
12 | % SEE ALSO
13 | % VPop.pws, VPop.pwStrategy
14 | if nargin < 1
15 | myRandomStart = false;
16 | end
17 | mycoeffsTable = getVPCoeffs(myWorksheet);
18 | [nAxis, nVP] = size(mycoeffsTable);
19 | if ~myRandomStart
20 | myUniformStartProbs = ones(1,nVP) ./ nVP;
21 | else
22 | myUniformStartProbs = rand([1, nVP]);
23 | myUniformStartProbsSum=sum(myUniformStartProbs);
24 | for axisCounter = 1 : nVP
25 | myUniformStartProbs(1,axisCounter) = myUniformStartProbs(1,axisCounter)/myUniformStartProbsSum;
26 | end
27 | end
28 | obj.pws = myUniformStartProbs;
29 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/classes/@VPop/startProbs.m:
--------------------------------------------------------------------------------
1 | function obj = startProbs(obj, myRandomStart)
2 | % This method initializes bin probabilities, and is used
3 | % prior to the optization.
4 | % Only relevant for obj.pwStrategy = 'bin'
5 | %
6 | % ARGUMENTS
7 | % (self)
8 | % myRandomStart: A boolean variable (true/false), if true
9 | % the bin probabilities will be set
10 | % randomly and if false they will be uniform
11 | if nargin < 1
12 | myRandomStart = false;
13 | end
14 | myBinMidPoints = obj.binMidPoints;
15 | [nAxes, nBins] = size(myBinMidPoints);
16 | if ~myRandomStart
17 | myUniformStartProbs = ones(nAxes, nBins) ./ nBins;
18 | else
19 | myUniformStartProbs = rand([nAxes, nBins]);
20 | for axisCounter = 1 : nAxes
21 | myUniformStartProbs(axisCounter,:) = myUniformStartProbs(axisCounter,:)/sum(myUniformStartProbs(axisCounter,:));
22 | end
23 | end
24 | obj.binProbs = myUniformStartProbs;
25 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/dataImport/convertExpDataToDistTable.m:
--------------------------------------------------------------------------------
1 | function myDistTable = convertExpDataToDistTable(myVPop)
2 | % This function takes experimental data and
3 | % converts it to a mean/sd table format for use in MAPEL
4 | %
5 | % ARGUMENTS:
6 | % myVPop: A VPop object with a populated expData field. A
7 | % mapelOptions structure is also OK.
8 | %
9 | % RETURNS
10 | % myDistTable
11 | %
12 |
13 | continueFlag = true;
14 | if nargin > 1
15 | continueFlag = false;
16 | warning(['Too many input arguments for ',mfilename,'. Should provide: myVPop.'])
17 | continueFlag = false;
18 | elseif nargin > 0
19 | continueFlag = true;
20 | else
21 | warning(['Insufficient input arguments for ',mfilename,'. Should provide: myVPop.'])
22 | continueFlag = false;
23 | end
24 |
25 | if continueFlag
26 | if sum(ismember({'VPop','VPopRECIST','VPopRECISTnoBin','mapelOptions','mapelOptionsRECIST','mapelOptionsRECISTnoBin'},class(myVPop))) < 1
27 | warning(['Wrong input arguments for ',mfilename,'. Should provide: myVPop (or mapelOptions).'])
28 | continueFlag = false;
29 | end
30 | end
31 |
32 | if continueFlag
33 | if sum(ismember({'table'},class(myVPop.expData))) < 1
34 | warning(['Wrong input arguments for ',mfilename,'. Should provide: myVPop (or mapelOptions) with a populated expData property.'])
35 | continueFlag = false;
36 | end
37 | end
38 |
39 | if continueFlag
40 | commonNames = loadCommonNames();
41 | [nRows, ~] = size(myVPop.expData);
42 | if isa(myVPop,'VPop') || isa(myVPop,'mapelOptions')
43 | tableVariableNames = commonNames.VPOPTABLEVARNAMESFIXED;
44 | nDataHeaderCols = length(commonNames.VPOPTABLEVARNAMESFIXED);
45 | else
46 | tableVariableNames = commonNames.VPOPRECISTTABLEVARNAMESFIXED;
47 | nDataHeaderCols = length(commonNames.VPOPRECISTTABLEVARNAMESFIXED);
48 | end
49 | for rowCounter = 1 : nRows
50 | if rowCounter == 1
51 | tableVariableNames = [tableVariableNames,{'weight','expN', 'expSample', 'predN', 'predIndices','predSample', 'predProbs','expCombinedIndices','simCombinedIndices','combinedPoints'}];
52 | myDistTable = cell2table(cell(0,length(tableVariableNames)));
53 | myDistTable.Properties.VariableNames = tableVariableNames;
54 | end
55 | curData = myVPop.expData{rowCounter,nDataHeaderCols+1:end};
56 | curData = curData(~isnan(curData));
57 | curRow = table2cell(myVPop.expData(rowCounter,1:nDataHeaderCols));
58 | curRow = [curRow,{1, length(curData), {sort(curData,'ascend')}, nan, {nan}, {nan}, {nan},{nan},{nan},{nan}}];
59 | curRow = cell2table(curRow);
60 | curRow.Properties.VariableNames = myDistTable.Properties.VariableNames;
61 | myDistTable = [myDistTable; curRow];
62 | end
63 | else
64 | warning(['Unable to complete ',mfilename,', exiting.'])
65 | myDistTable = [];
66 | end
67 |
68 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/dataImport/convertExpDataToMnSDTable.m:
--------------------------------------------------------------------------------
1 | function myMnSDTable = convertExpDataToMnSDTable(myVPop)
2 | % This function takes experimental data and
3 | % converts it to a mean/sd table format for use in MAPEL
4 | %
5 | % ARGUMENTS:
6 | % myVPop: A VPop object with a populated expData field. A
7 | % mapelOptions structure is also OK.
8 | %
9 | % RETURNS
10 | % myMnSDTable
11 | %
12 |
13 | continueFlag = true;
14 | if nargin > 1
15 | continueFlag = false;
16 | warning(['Too many input arguments for ',mfilename,'. Should provide: myVPop.'])
17 | continueFlag = false;
18 | elseif nargin > 0
19 | continueFlag = true;
20 | else
21 | warning(['Insufficient input arguments for ',mfilename,'. Should provide: myVPop.'])
22 | continueFlag = false;
23 | end
24 |
25 | if continueFlag
26 | if sum(ismember({'VPop','VPopRECIST','VPopRECISTnoBin','mapelOptions','mapelOptionsRECIST','mapelOptionsRECISTnoBin'},class(myVPop))) < 1
27 | warning(['Wrong input arguments for ',mfilename,'. Should provide: myVPop (or mapelOptions).'])
28 | continueFlag = false;
29 | end
30 | end
31 |
32 | if continueFlag
33 | if sum(ismember({'table'},class(myVPop.expData))) < 1
34 | warning(['Wrong input arguments for ',mfilename,'. Should provide: myVPop (or mapelOptions) with a populated expData property.'])
35 | continueFlag = false;
36 | end
37 | end
38 |
39 | if continueFlag
40 | commonNames = loadCommonNames();
41 | [nRows, ~] = size(myVPop.expData);
42 | if isa(myVPop,'VPop') || isa(myVPop,'mapelOptions')
43 | tableVariableNames = commonNames.VPOPTABLEVARNAMESFIXED;
44 | nDataHeaderCols = length(commonNames.VPOPTABLEVARNAMESFIXED);
45 | else
46 | tableVariableNames = commonNames.VPOPRECISTTABLEVARNAMESFIXED;
47 | nDataHeaderCols = length(commonNames.VPOPRECISTTABLEVARNAMESFIXED);
48 | end
49 | for rowCounter = 1 : nRows
50 | if rowCounter == 1
51 | tableVariableNames = [tableVariableNames,{'logN','weightMean', 'weightSD', 'expN', 'expMean', 'expSD', 'predN', 'predIndices', 'predMean', 'predSD'}];
52 | myMnSDTable = cell2table(cell(0,length(tableVariableNames)));
53 | myMnSDTable.Properties.VariableNames = tableVariableNames;
54 | end
55 | curData = myVPop.expData{rowCounter,nDataHeaderCols+1:end};
56 | curData = curData(~isnan(curData));
57 | curRow = table2cell(myVPop.expData(rowCounter,1:nDataHeaderCols));
58 | curRow = [curRow,{false, 1, 1, length(curData), mean(curData), std(curData), nan, {nan}, nan, nan}];
59 | curRow = cell2table(curRow);
60 | curRow.Properties.VariableNames = myMnSDTable.Properties.VariableNames;
61 | myMnSDTable = [myMnSDTable; curRow];
62 | end
63 | else
64 | warning(['Unable to complete ',mfilename,', exiting.'])
65 | myMnSDTable = [];
66 | end
67 |
68 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/evaluateMSE.m:
--------------------------------------------------------------------------------
1 | function myVPop = evaluateMSE(myVPop)
2 | % count the subpopulation and dropouts in:
3 | vpPrevalenceWeights=myVPop.pws';
4 | if isempty(myVPop.LinearProblemMatrices)
5 | myOptimOptions = LinearCalibrationOptions();
6 | myOptimOptions.cdfProbsToFit = 0.05:0.05:0.95;
7 | myOptimOptions.pdf2DProbsToFitN = 5;
8 | myOptimOptions.responseValTransformation='none';
9 | myOptimOptions.optimizationAlgorithm = "quadprogEffN";
10 | myOptimOptions.priorPrevalenceWeightAssumption = 'specified';
11 | myOptimOptions.oldVPop = myVPop;
12 | % myOptimOptions = LinearCalibrationOptions();
13 | % myOptimOptions.cdfProbsToFit = 0.05:0.05:0.95;
14 | % myOptimOptions.pdf2DProbsToFitN = 5;
15 | % myOptimOptions.responseValTransformation='none';
16 | % myOptimOptions.optimizationAlgorithm = "fmincon";
17 | % myOptimOptions.priorPrevalenceWeightAssumption = 'specified';
18 | % myOptimOptions.targetEffNConstraint = 1; % just put any non-zero effN constraint to get the matrix
19 | % myOptimOptions.minSubWeightConstraint = 0;
20 |
21 | Objlinear = LinearCalibration(myVPop,myVPop,'optimOptions',myOptimOptions);
22 | Objlinear = Objlinear.constructLinearProblemMatrices();
23 | myVPop.LinearProblemMatrices = Objlinear.LinearProblemMatrices;
24 | end
25 | C = myVPop.LinearProblemMatrices.independentVarValsWeighted;
26 | d = myVPop.LinearProblemMatrices.observationValsWeighted;
27 | SubgroupSumWeights = myVPop.LinearProblemMatrices.vpIsInSubgroup*vpPrevalenceWeights;
28 | % myVPop.LinearProblemMatricesSubgroupSumWeights = SubgroupSumWeights; % don't recalculate the subgroupweight from the rescaled weights. keep it the same as oldVPop
29 | Cactual = (1./SubgroupSumWeights).*(C.*myVPop.LinearProblemMatrices.vpIsInSubgroup);
30 | residuals = Cactual*vpPrevalenceWeights-d;
31 | residuals(isnan(residuals)) = 0; % added this in case there are one or less VPs in the row, mn and std will be NaNs
32 | N = length(d); % just fix it as the number of rows, so it is comparable between iterations
33 | myVPop.MSE = sum(residuals.^2)/N;
34 | end
35 |
36 |
--------------------------------------------------------------------------------
/QSPToolbox/population/linearCalibration/increaseEffNWithLinearCalibrate.m:
--------------------------------------------------------------------------------
1 | function myVPop = increaseEffNWithLinearCalibrate(myVPop)
2 | % Uses least-squares optimization and bagging to increase EffN, likely
3 | % sacrificing goodness-of-fit p-value.
4 |
5 | tictoc = tic();
6 |
7 | disp('Increasing EffN by using linear calibration with bagging...');
8 |
9 | % Set up the optimization options, which will automatically spit back a set
10 | % of default values
11 | optimOptions = LinearCalibrationOptions();
12 |
13 | % Define the probabilities of the cumulative
14 | % distribution functions (CDF) to fit. The default is to fit all points on
15 | % the CDF. We will only fit certain probabilities
16 | % along the CDF in order to make the fit faster. These probabilities are
17 | % defined here:
18 | optimOptions.cdfProbsToFit = 0.05:0.05:0.95;
19 |
20 | % Other options:
21 | optimOptions.optimizationAlgorithm = "nnls";
22 | optimOptions.optimizationAlgorithmOptions.Accy = 0;
23 | optimOptions.method = "bagging";
24 | optimOptions.fractionVPsPerBaggingIteration = 0.05;
25 |
26 | % Initialize a 'LinearCalibration' object:
27 | linearCalibrationObject = LinearCalibration(myVPop,'optimOptions',optimOptions);
28 |
29 | % Run the optimization:
30 | linearCalibrationObject = linearCalibrationObject.run();
31 |
32 | % Update VPop:
33 | myVPop = linearCalibrationObject.OptimizedVPop;
34 |
35 | timeElapsedSec = toc(tictoc);
36 | disp(['Finished increasing EffN. Time elapsed [minutes]: ' num2str(timeElapsedSec/60)]);
37 |
38 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/alignCDFs.m:
--------------------------------------------------------------------------------
1 | function [CDF1, CDF2] = alignCDFs(sample1, sample2, W1, W2)
2 | % This function takes two samples and weights, and returns
3 | % adjusted sample and CDF vectors that can be compared element-wise
4 | %
5 | % ARGUMENTS
6 | % sample1 observed values for sample1. These are assumed to be sorted
7 | % in ascending order
8 | % sample2 observed values for sample2. These are assumed to be sorted
9 | % in ascending order
10 | % W1 a 1xlength(sample1) vector of weights for sample 1
11 | % W2 a 1xlength(sample2) vector of weights for sample 2
12 | %
13 | % RETURNS
14 | % CDF1 a 1xlength unique sample values of increasing cumulative
15 | % probabilities in sample 1 corresponding to the unique
16 | % combined sample values
17 | % CDF2 a 1xlength unique sample values of increasing cumulative
18 | % probabilities in sample 1 corresponding to the unique
19 | % combined sample values
20 | % First we need to interpolate the two samples so we can directly
21 | % take the supremum function.
22 | W1 = W1 / sum(W1);
23 | W2 = W2 / sum(W2);
24 | W1 = cumsum(W1);
25 | W2 = cumsum(W2);
26 | % We need to re-calculate the cdf for sample1 and sample2
27 | % at all x-values in either
28 | % sample 1 and sample2 so we can directly calculate
29 | % the differences in the cdf at each point
30 | [sample1ind, sample2ind, SC] = alignSamples(sample1, sample2);
31 | CDF1 = zeros(1, length(SC));
32 | CDF2 = zeros(1, length(SC));
33 | CDF1Indices = find(~isnan(sample1ind));
34 | CDF2Indices = find(~isnan(sample2ind));
35 | CDF1(CDF1Indices) = W1(sample1ind(CDF1Indices));
36 | CDF2(CDF2Indices) = W2(sample2ind(CDF2Indices));
37 |
38 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/alignCDFsPreGrid.m:
--------------------------------------------------------------------------------
1 | function [CDF1, CDF2] = alignCDFsPreGrid(SC, sample1ind, sample2ind, W1, W2)
2 | % This function returns
3 | % adjusted CDF vectors that can be compared element-wise
4 | %
5 | % ARGUMENTS
6 | % SC the combined unique, sorted sample values
7 | % sample1ind indices mapping values for sample1 to SC.
8 | % Indices are assumed to point to the each unique, last value
9 | % following sorting.
10 | % sample2ind indices mapping values for sample1 to SC.
11 | % Indices are assumed to point to the each unique, last value
12 | % following sorting.
13 | % W1 a 1xlength(sample1) vector of weights for sample 1
14 | % W2 a 1xlength(sample2) vector of weights for sample 2
15 | %
16 | % RETURNS
17 | % CDF1 a 1xlength unique sample values of increasing cumulative
18 | % probabilities in sample 1 corresponding to the unique
19 | % combined sample values
20 | % CDF2 a 1xlength unique sample values of increasing cumulative
21 | % probabilities in sample 1 corresponding to the unique
22 | % combined sample values
23 | %
24 | % First we need to interpolate the two samples so we can directly
25 | % take the supremum function.
26 | W1 = W1 / sum(W1);
27 | W2 = W2 / sum(W2);
28 | W1 = cumsum(W1);
29 | W2 = cumsum(W2);
30 | % We need to re-calculate the cdf for sample1 and sample2
31 | % at all x-values in either
32 | % sample 1 and sample2 so we can directly calculate
33 | % the differences in the cdf at each point
34 | CDF1 = zeros(1, length(SC));
35 | CDF2 = zeros(1, length(SC));
36 | CDF1Indices = find(~isnan(sample1ind));
37 | CDF2Indices = find(~isnan(sample2ind));
38 | CDF1(CDF1Indices) = W1(sample1ind(CDF1Indices));
39 | CDF2(CDF2Indices) = W2(sample2ind(CDF2Indices));
40 |
41 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/alignSamples.m:
--------------------------------------------------------------------------------
1 | function [sample1Ind, sample2Ind, SC] = alignSamples(sample1, sample2)
2 | % This function takes two samples, combines them, and returns
3 | % indices vectors that can be used to map the
4 | % original values in each sample onto the combined vector, prioritizing
5 | % the last observation to facilitate generating empirical CDFs.
6 | %
7 | % ARGUMENTS
8 | % sample1 observed values for sample1. These are assumed to be sorted
9 | % in ascending order
10 | % sample2 observed values for sample2. These are assumed to be sorted
11 | % in ascending order
12 | %
13 | % RETURNS
14 | % sample1Ind a 1xlength unique sample indices that map elements in sample
15 | % 1 to SC.
16 | % sample2Ind a 1xlength unique sample indices that map elements in sample
17 | % 2 to SC.
18 | % SC combined sample values
19 | %
20 | % We need to re-calculate the cdf for sample1 and sample2
21 | % at all x-values in either
22 | % sample 1 and sample2 so we can directly calculate
23 | % the differences in the cdf at each point
24 | [sample1,Inu1,~]=unique(sample1,'last');
25 | [sample2,Inu2,~]=unique(sample2,'last');
26 | SC = unique([sample1,sample2]);
27 | SC = sort(SC, 'ascend');
28 | % Get the indices of length SC where every entry in SC is found to be
29 | % >= the indicated index in sample1
30 | if length(sample1) > 1
31 | sample1Ind = interp1(sample1,[1:length(sample1)],SC,'previous');
32 | else
33 | % If there is just one unique value in sample1
34 | sample1Ind = ones(1,length(SC));
35 | sample1Ind(sample1= the indicated index in sample2
39 | if length(sample2) > 1
40 | sample2Ind = interp1(sample2,[1:length(sample2)],SC,'previous');
41 | else
42 | sample2Ind = ones(1,length(SC));
43 | sample2Ind(sample2 0
47 | t = 1:numel(sample1Ind);
48 | sample1Ind = interp1(t(~isnan(sample1Ind)),sample1Ind(~isnan(sample1Ind)),t,'previous','extrap');
49 | end
50 | if sum(isnan(sample2Ind)) > 0 && sum(~isnan(sample2Ind)) > 1 %need > 2 points for interpolating
51 | t = 1:numel(sample2Ind);
52 | sample2Ind = interp1(t(~isnan(sample2Ind)),sample2Ind(~isnan(sample2Ind)),t,'previous','extrap');
53 | end
54 | % To update CDFs, we will need to map back to the non-unique but sorted
55 | % samples
56 | curInd = find(~isnan(sample1Ind));
57 | sample1Ind(curInd) = Inu1(sample1Ind(curInd));
58 | curInd = find(~isnan(sample2Ind));
59 | sample2Ind(curInd) = Inu2(sample2Ind(curInd));
60 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/contingency2N.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BMSQSP/QSPToolbox/42cb4425292c5ecdf4954b6251346503746671d0/QSPToolbox/population/statistics/contingency2N.m
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/hbe.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BMSQSP/QSPToolbox/42cb4425292c5ecdf4954b6251346503746671d0/QSPToolbox/population/statistics/hbe.m
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/predNPDTFLS.m:
--------------------------------------------------------------------------------
1 | function myVPop = predNPDTFLS(myVPop)
2 | % This function takes a VPop object and updates with
3 | % predictions for number of PD patients.
4 | %
5 | % ARGUMENTS
6 | % myVPop: (Required) a mapelOptionsRECIST or VPopRECIST
7 | % instance.
8 | %
9 | % Returns
10 | % myVPop: VPopRECIST with updated brTableRECIST. This
11 | % gives predNPD21LS values.
12 | %
13 | %
14 |
15 |
16 | continueFlag = true;
17 | if nargin > 1
18 | warning(['Too many input arguments provided to ',mfilename,'. Requires: VPopRECIST object.'])
19 | continueFlag = false;
20 | elseif nargin < 1
21 | continueFlag = false;
22 | warning(['Insufficient input arguments provided to ',mfilename,'. Requires: VPopRECIST object.'])
23 | end
24 |
25 | if continueFlag
26 | if ~ismember(class(myVPop),{'VPopRECIST'})
27 | continueFlag = false;
28 | warning(['Input myVPop not recognized in call to ',mfilename,'. Requires: VPopRECIST object.'])
29 | end
30 | end
31 |
32 |
33 | if continueFlag
34 | lmResults = regressPD2ScaleFactor(myVPop); % updated: use PD, SD as dependent variable, intercept=0
35 | % Update the values for the
36 | % First find the blocks by the PD2 measures
37 | predRows = find(sum(isnan(myVPop.brTableRECIST{:,{'predN','predCR','predPR','predSD','predPD'}}),2)==0);
38 | predN = myVPop.brTableRECIST{predRows,{'predN'}};
39 | predPD = myVPop.brTableRECIST{predRows,{'predPD'}}.*predN;
40 | predSD = myVPop.brTableRECIST{predRows,{'predSD'}}.*predN;
41 |
42 | res = predPD.*lmResults.Coefficients{1,'Estimate'} + predSD.*lmResults.Coefficients{2,'Estimate'};
43 | myVPop.brTableRECIST{predRows,'predNPD21LS'}=res;
44 | else
45 | lmResults = {};
46 | warning(['Unable to run ',mfilename,'.'])
47 | end
48 | end
49 |
50 |
51 |
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/regressPD2ScaleFactor.m:
--------------------------------------------------------------------------------
1 | function lmResults = regressPD2ScaleFactor(myMapelOptions)
2 | % This function takes a mapelOptions or VPop object and returns
3 | % coefficients for a predicted PD2 scaling rate.
4 | %
5 | % ARGUMENTS
6 | % myMapelOptions: (Required) a mapelOptionsRECIST or VPopRECIST
7 | % instance.
8 | %
9 | % Returns
10 | % lmResults: Output of the regression. This gives the
11 | % a regression model for the observed PD normalized
12 | % to the number of patients recorded as nonPD2
13 | % (expN) at the first lesion scan. Multiply by
14 | % expN to get the predicted expNPD21LS. To
15 | % given an expNPD21LS, one could use the
16 | % predSD, predPD with the regression coefficients
17 | % and scale by the the predN.
18 | %
19 | %
20 |
21 |
22 | continueFlag = true;
23 | if nargin > 1
24 | warning(['Too many input arguments provided to ',mfilename,'. Requires: mapelOptionsRECIST or VPopRECIST object.'])
25 | continueFlag = false;
26 | elseif nargin < 1
27 | continueFlag = false;
28 | warning(['Insufficient input arguments provided to ',mfilename,'. Requires: mapelOptionsRECIST or VPopRECIST object.'])
29 | end
30 |
31 | if continueFlag
32 | if ~ismember(class(myMapelOptions),{'mapelOptionsRECIST','VPopRECIST'})
33 | continueFlag = false;
34 | warning(['Input not recognized in call to ',mfilename,'. Requires: mapelOptionsRECIST or VPopRECIST object.'])
35 | end
36 | end
37 |
38 |
39 | if continueFlag
40 | % First find the blocks by the PD2 measures
41 | % Only keep the last time point from each inidividual intervention (BOR), then train the regression model
42 | testData = myMapelOptions.brTableRECIST(:,{'subpopNo','expDataID','interventionID'});
43 | [C,IA,IC] = unique(testData,'rows','stable'); % unique(testData,'last','rows','stable');
44 | LastRowindex=IA;
45 | for j=1:length(IA)
46 | indices=find(IC==j);
47 | LastRowindex(j)=indices(end);
48 | end
49 | testRows = find(~isnan(myMapelOptions.brTableRECIST{:,{'expNPD21LS'}}));
50 | regRows = intersect(testRows, LastRowindex);
51 | expN = table2array(myMapelOptions.brTableRECIST(regRows,'expN'));
52 | expPD=table2array(myMapelOptions.brTableRECIST(regRows,'expPD')).*expN;
53 | expSD=table2array(myMapelOptions.brTableRECIST(regRows,'expSD')).*expN;
54 | resp=table2array(myMapelOptions.brTableRECIST(regRows,'expNPD21LS'));
55 | fitTable = table(expPD,expSD,resp);
56 | lmResults = fitlm(fitTable,'resp ~ expPD + expSD','Intercept',false);
57 | else
58 | lmResults = {};
59 | warning(['Unable to run ',mfilename,'. Returning an empty object.'])
60 | end
61 | end
62 |
63 |
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/weightedKS.m:
--------------------------------------------------------------------------------
1 | function myPVal = weightedKS(sample1, sample2, W1, W2, N1, N2)
2 | % This function performs a KS test. Rather than assuming the
3 | % percentiles are computed from the rank-order it
4 | % adjusts the percentiles for observations according to the
5 | % provided weights.
6 | %
7 | % References:
8 | % Press et al, Numerical Recipes - The Art of Scientific Computing
9 | % (2007) P 736-740
10 | % Stevens MA. Use of the Kolmogorov-Smirnov, Cramer-Von Mises and
11 | % Related Statistics Without Extensive Tables.
12 | % Journal of the Royal Statistical Society Series B (Methodological).
13 | % 1970;32(1):115-122.
14 | %
15 | %
16 | % ARGUMENTS
17 | % sample1 observed values for sample1. These are assumed to be sorted
18 | % in ascending order
19 | % sample2 observed values for sample2. These are assumed to be sorted
20 | % in ascending order
21 | % W1 a 1xlength(sample1) vector of weights for sample 1
22 | % W2 a 1xlength(sample2) vector of weights for sample 2
23 | % N1 number of observations underlying sample1
24 | % N2 number of observations underlying sample2
25 | %
26 | % RETURNS
27 | % myPVal the p-value resulting from the two-tailed test
28 |
29 | % First calculate CDF along the sample sample axis
30 | [CDF1, CDF2, SC] = alignCDFs(sample1, sample2, W1, W2);
31 | % See Press et al, Numerical Recipes - The Art of Scientific Computing
32 | % (2007) P 736-740
33 | D = max(abs(CDF2-CDF1));
34 | nPool = N1 * N2 /(N1 + N2);
35 | zVal = max((sqrt(nPool) + 0.12 + 0.11/sqrt(nPool)) * D , 0);
36 | % See page 334, special functions, in Numerical Recipes
37 | % This is an infinite series. Here we assume 100 terms is enough
38 | % TODO: may want to add a check to validate desired precision
39 | % for the series
40 | iVals = (1:100)';
41 | myPVal = 2 * sum((-1).^(iVals-1).*exp(-2*zVal^2*iVals.^2));
42 | myPVal = min(max(myPVal, 0), 1);
43 | end
44 |
45 |
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/weightedKSPreGrid.m:
--------------------------------------------------------------------------------
1 | function myPVal = weightedKSPreGrid(SC, sample1Ind, sample2Ind, W1, W2, N1, N2)
2 | % This function performs a KS test. Rather than assuming the
3 | % percentiles are computed from the rank-order it
4 | % adjusts the percentiles for observations according to the
5 | % provided weights.
6 | %
7 | % This version assumes you will provide the 1-D mesh and indices to
8 | % map weights onto that mesh from combined, sorted, unique sample points.
9 | %
10 | % References:
11 | % Press et al, Numerical Recipes - The Art of Scientific Computing
12 | % (2007) P 736-740
13 | % Stevens MA. Use of the Kolmogorov-Smirnov, Cramer-Von Mises and
14 | % Related Statistics Without Extensive Tables.
15 | % Journal of the Royal Statistical Society Series B (Methodological).
16 | % 1970;32(1):115-122.
17 | %
18 | % ARGUMENTS
19 | % SC the vector of unique, sorted combined sample points
20 | % sample1Ind indices to map observations in sorted sample1 to SC
21 | % sample2Ind indices to map observations in sorted sample2 to SC
22 | % W1 a 1xlength(sample1) vector of weights for sample 1.
23 | % Is it assumed the W1s are based on sorted observations.
24 | % W2 a 1xlength(sample2) vector of weights for sample 2
25 | % Is it assumed the W2s are based on sorted observations.
26 | % N1 number of observations underlying sample1
27 | % N2 number of observations underlying sample2
28 | %
29 | % RETURNS
30 | % myPVal the p-value resulting from the two-tailed test
31 | %
32 |
33 | % First calculate CDF along the sample sample axis
34 | [CDF1, CDF2] = alignCDFsPreGrid(SC, sample1Ind, sample2Ind, W1, W2);
35 | % See Press et al, Numerical Recipes - The Art of Scientific Computing
36 | % (2007) P 736-740
37 | D = max(abs(CDF2-CDF1));
38 | nPool = N1 * N2 /(N1 + N2);
39 | zVal = max((sqrt(nPool) + 0.12 + 0.11/sqrt(nPool)) * D , 0);
40 | % See page 334, special functions, in Numerical Recipes
41 | % This is an infinite series. Here we assume 100 terms is enough
42 | % TODO: may want to add a check to validate desired precision
43 | % for the series
44 | iVals = (1:100)';
45 | myPVal = 2 * sum((-1).^(iVals-1).*exp(-2*zVal^2*iVals.^2));
46 | myPVal = min(max(myPVal, 0), 1);
47 | end
48 |
49 |
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/woodF.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BMSQSP/QSPToolbox/42cb4425292c5ecdf4954b6251346503746671d0/QSPToolbox/population/statistics/woodF.m
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/wtdBinProb.m:
--------------------------------------------------------------------------------
1 | function wpp = wtdBinProb(measVals, pws, binEdgeValues)
2 | % This function calculates a discrete/binned pdf based on observations and
3 | % weights. Here, we strictly enforce the first dimension is 1
4 | % so there are no errors.
5 | %
6 | % ARGUMENTS
7 | % measVals: A 1 X nVP vector of measurement values
8 | % pws: A 1 X nVP vector of prevalence weights
9 | % binEdgeValues: A 1 X Nbin-1 vector of bin dividing edge values. Note
10 | % that values smaller than the first bin edge are counted
11 | % in the first bin and values >= than the upper bin edge
12 | % are counted in the last returned bin.
13 | %
14 | % RETURNS
15 | % wpp: A 1 X Nbin vector of weighted pdf in each bin
16 | %
17 | continueFlag = true;
18 | wpp = nan;
19 | numericTolerance = max(eps(1) * length(pws) * 10,1E-14);
20 | % We just check if matrix/vector dimensions are OK here.
21 | if nargin > 3
22 | continueFlag = false;
23 | warning(['A 1 x nVP vector of values and weights, and vector of inner bin edges, are all required for ',mfilename,'. Too many input arguments. Returning NaN.'])
24 | elseif nargin > 2
25 | continueFlag = true;
26 | else
27 | continueFlag = false;
28 | warning(['A 1 x nVP vector of values and weights, and vector of inner bin edges, are all required for ',mfilename,'. Insufficient input arguments. Returning NaN.'])
29 | end
30 |
31 | if continueFlag
32 | [size1r, size1c] = size(measVals);
33 | [size2r, size2c] = size(pws);
34 | [size3r, size3c] = size(binEdgeValues);
35 | if (size1c~= size2c)
36 | continueFlag = false;
37 | end
38 | if ((size1r ~= 1) || (size2r ~= 1) || (size3r ~= 1))
39 | continueFlag = false;
40 | end
41 | if (size3c < 1)
42 | continueFlag = false;
43 | end
44 | if ~continueFlag
45 | warning(['A 1 x nVP vector of values and weights, and 1 X (nBin-1) vector of inner bin edges, are all required for ',mfilename,'. Returning NaN.'])
46 | end
47 | end
48 |
49 | if continueFlag
50 | if ((sum(pws) > (1 + numericTolerance)) || (sum(pws) < (1 - numericTolerance)))
51 | warning(['Supplied pws to ',mfilename,' should sum to 1. Returning NaN.'])
52 | continueFlag = false;
53 | end
54 | end
55 |
56 | if continueFlag
57 | catMat = cat(1, measVals, pws);
58 | [sortVal, Indices] = sort(measVals);
59 | catMat = catMat(:,Indices);
60 | nBins = length(binEdgeValues) + 1;
61 | wpp = zeros(1,length(nBins));
62 | curIndices = catMat(1,:) < binEdgeValues(1);
63 | wpp(1,1) = sum(curIndices .* catMat(2,:));
64 | for binCounter = 2 : (nBins-1)
65 | curIndices = catMat(1,:) < binEdgeValues(binCounter);
66 | wpp(1,binCounter) = sum(curIndices .* catMat(2,:)) - sum(wpp(1:(binCounter-1)));
67 | end
68 | curIndices = catMat(1,:) >= binEdgeValues(nBins-1);
69 | wpp(1,nBins) = sum(curIndices .* catMat(2,:));
70 | end
71 |
72 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/wtdMean.m:
--------------------------------------------------------------------------------
1 | function wmn = wtdMean(measVals,pws)
2 | % Calculation of the weighted mean.
3 | %
4 | % ARGUMENTS
5 | % measVals: A 1 X nVP vector of measurement values
6 | % pws: A 1 X nVP vector of prevalence weights
7 | %
8 | % RETURNS
9 | % wmn: weighted mean
10 | %
11 |
12 | continueFlag = true;
13 | wmn = nan;
14 | % We just check if matrix/vector dimensions are OK here.
15 | if nargin > 2
16 | continueFlag = false;
17 | warning(['A 1 x nVP (or nVP X 1) vector of values and weights are both required for ',mfilename,'. Too many input arguments. Returning NaN.'])
18 | elseif nargin > 1
19 | continueFlag = true;
20 | else
21 | continueFlag = false;
22 | warning(['A 1 x nVP (or nVP X 1) vector of values and weights are both required for ',mfilename,'. Insufficient input arguments. Returning NaN.'])
23 | end
24 |
25 | if continueFlag
26 | [size1r, size1c] = size(measVals);
27 | [size2r, size2c] = size(pws);
28 | if ((size1r~= size2r) || (size1c~= size2c))
29 | continueFlag = false;
30 | end
31 | if (min(size1r, size1c) ~= 1) || (min(size2r, size2c) ~= 1)
32 | continueFlag = false;
33 | end
34 | if ~continueFlag
35 | warning(['A 1 x nVP (or nVP X 1) vector of values and weights are both required for ',mfilename,'. Returning NaN.'])
36 | end
37 | end
38 |
39 | if continueFlag
40 | % We allow an error of eps * the number of VPs * 10
41 | % We could in strictly enforce eps * the number of VPs but
42 | % this criterion is relaxed a little.
43 | % 10^-14 was used as a minimum in the bin probabilities. The
44 | % bin probabilities should all be fixed and
45 | % PWs should all be corrected to sum to 1, but
46 | % here 10^-14 is set as a minimum allowed error in the check
47 | numericTolerance = max(eps(1) * length(pws) * 10,1E-14);
48 | if ((sum(pws) > (1 + numericTolerance)) || (sum(pws) < (1 - numericTolerance)))
49 | warning(['Supplied pws to ',mfilename,' should sum to 1. Returning NaN.'])
50 | continueFlag = false;
51 | end
52 | end
53 |
54 | if continueFlag
55 | wmn = sum(pws .* measVals);
56 | end
57 |
58 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/statistics/wtdStd.m:
--------------------------------------------------------------------------------
1 | function wsd = wtdStd(measVals,pws)
2 | % Calculates a weighted standard deviation. Note this is a quantity
3 | % without universal agreement on a definition from statisticians.
4 | % So here, we adopt the definition used in NIST software. See:
5 | % http://www.itl.nist.gov/div898/software/dataplot/refman2/ch2/weightsd.pdf
6 | %
7 | % ARGUMENTS
8 | % measVals: A 1 X nVP (or nVP X 1) vector of measurement values
9 | % pws: A 1 X nVP (or nVP X 1) vector of prevalence weights
10 | %
11 | % RETURNS
12 | % wsd: weighted standard deviation
13 | %
14 |
15 | continueFlag = true;
16 | wsd = nan;
17 | % We just check if matrix/vector dimensions are OK here.
18 | if nargin > 2
19 | continueFlag = false;
20 | warning(['A 1 x nVP (or nVP X 1) vector of values and weights are both required for ',mfilename,'. Too many input arguments. Returning NaN.'])
21 | elseif nargin > 1
22 | continueFlag = true;
23 | else
24 | continueFlag = false;
25 | warning(['A 1 x nVP (or nVP X 1) vector of values and weights are both required for ',mfilename,'. Insufficient input arguments. Returning NaN.'])
26 | end
27 |
28 | if continueFlag
29 | [size1r, size1c] = size(measVals);
30 | [size2r, size2c] = size(pws);
31 | if ((size1r~= size2r) || (size1c~= size2c))
32 | continueFlag = false;
33 | end
34 | if (min(size1r, size1c) ~= 1) || (min(size2r, size2c) ~= 1)
35 | continueFlag = false;
36 | end
37 | if ~continueFlag
38 | warning(['A 1 x nVP (or nVP X 1) vector of values and weights are both required for ',mfilename,'. Returning NaN.'])
39 | end
40 | end
41 |
42 | if continueFlag
43 | % We allow an error of eps * the number of VPs * 10
44 | % We could in strictly enforce eps * the number of VPs but
45 | % this criterion is relaxed a little.
46 | % 10^-14 was used as a minimum in the bin probabilities. The
47 | % bin probabilities should all be fixed and
48 | % PWs should all be corrected to sum to 1, but
49 | % here 10^-14 is set as a minimum allowed error in the check
50 | numericTolerance = max(eps(1) * length(pws) * 10,1E-14);
51 | if ((sum(pws) > (1 + numericTolerance)) || (sum(pws) < (1 - numericTolerance)))
52 | warning(['Supplied pws to ',mfilename,' should sum to 1. Returning NaN.'])
53 | continueFlag = false;
54 | end
55 | end
56 |
57 | if continueFlag
58 | wMean = wtdMean(measVals,pws);
59 | wVar = sum(pws.*((measVals - wMean).^2));
60 | % Note that for n in the wsd, we use the number of pws above a numeric
61 | % threshold (here, 1 E -16 as was done in the MAPEL paper).
62 | % If an effective N is used for statistical comparisons, the effective
63 | % N is implemented at the time of the statistical testing (e.g. F-test,
64 | % t-test, ...)
65 | n = sum(pws > numericTolerance);
66 | % Use the unbiased correction so it gives the
67 | % same answer as R's SD function
68 | wVar = wVar*n/(n-1);
69 | wsd = sqrt(wVar);
70 | % infinity can be returned
71 | % with a PW of ~1 coupled with
72 | % very small PWs. The std
73 | % of 1 value should be 0.
74 | if isinf(wsd)
75 | wsd = 0;
76 | end
77 | end
78 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/align2DPDFs.m:
--------------------------------------------------------------------------------
1 | function [data1pdf, data2pdf, combinedPoints] = align2DPDFs(data1, data2, data2PWs)
2 | % This function takes two samples and weights, and returns
3 | % adjusted sample and CDF vectors that can be compared element-wise
4 | %
5 | % ARGUMENTS
6 | % data1 observed values for sample1. These need not be sorted,
7 | % but should be provided as a 2xN1 matrix
8 | % data2 observed values for sample2. These need not be sorted,
9 | % but should be provided as a 2xN2 matrix.
10 | % data2PWs a 1xN2 vector of weights for sample 2. It is assumed
11 | % all observations in sample1 are weighted equally.
12 | %
13 | % RETURNS
14 | % data1pdf: a pdf for data in sample1 mapped onto the combinedPoints
15 | % data2pdf: a pdf for data in sample2 mapped onto the combinedPoints
16 | % combinedPoints: a set of points that the pdfs in data1 and data2 are mapped onto.
17 |
18 | % First combine points, to get ranges
19 | combinedPoints = [(unique(data1','rows'))',(unique(data2','rows'))'];
20 |
21 | % We will apply smoothing to the PDFs. Calculate a bandwidth to use
22 | % base on the range in the data
23 | bw1 = (max(combinedPoints(1,:),[],2)-min(combinedPoints(1,:),[],2))/10;
24 | bw2 = (max(combinedPoints(2,:),[],2)-min(combinedPoints(2,:),[],2))/10;
25 |
26 | % Get the experimental density onto the model sampled points, with
27 | % smoothing
28 | data1pdf = ksdensity(data1',combinedPoints','Bandwidth',[bw1;bw2]);
29 | f = scatteredInterpolant(combinedPoints(1,:)', combinedPoints(2,:)', data1pdf, 'nearest');
30 |
31 | % Unfortunately, we have to integrate over discontinuous surfaces (see
32 | % below)
33 | % and it's very likely there will be some residual error. We may want
34 | % to revisit this in future MATLAB releases.
35 | warning('off','MATLAB:integral2:maxFunEvalsPass');
36 | % We may want to turn this back on with improved performance of
37 | % the 2D integration
38 | warning('off','MATLAB:integral2:maxFunEvalsFail');
39 | % We use large tolerances. int does not have to be very precise,
40 | % and MATLAB's integral2 function can use much overhead if
41 | % we require a small tolerance.
42 | int = integral2(@(x,y) f(x,y), min(combinedPoints(1,:)), max(combinedPoints(1,:)), min(combinedPoints(2,:)), max(combinedPoints(2,:)),'method','tiled','AbsTol',1e-2,'RelTol',1e-1);
43 |
44 | % Normalize the 2D PDF
45 | data1pdf = data1pdf/int;
46 |
47 | % We will resample from data2 before smoothing. We can't apply
48 | % PWs in the smoothing function directly
49 | % Note: we may want to adjust the rng seed as an additional
50 | % input to make this reproducible
51 | % rng(0);
52 | data2pdf = datasample(data2', 1E3, 'Weights',data2PWs');
53 | data2pdf = ksdensity(data2pdf,combinedPoints','Bandwidth',[bw1;bw2]);
54 | % We have to use 'nearest', which is discontinuous but
55 | % the only practical option. Otherwise, MATLAB may calculate a
56 | % negative interpolant with the available options, which does not
57 | % make sense for a pdf surface
58 | f = scatteredInterpolant(combinedPoints(1,:)', combinedPoints(2,:)', data2pdf, 'nearest');
59 | int = integral2(@(x,y) f(x,y), min(combinedPoints(1,:)), max(combinedPoints(1,:)), min(combinedPoints(2,:)), max(combinedPoints(2,:)),'method','tiled','AbsTol',1e-2,'RelTol',1e-1);
60 | data2pdf = data2pdf/int;
61 | warning('on','MATLAB:integral2:maxFunEvalsPass');
62 | warning('on','MATLAB:integral2:maxFunEvalsFail');
63 |
64 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/calculateExpWeight.m:
--------------------------------------------------------------------------------
1 | function w = calculateExpWeight(expN, expSTD, dataGroupDescription, simN)
2 | % This is a utility function to find calculation of
3 | % different weights for the different data group types
4 | % in linear calibrate.
5 | %
6 | % ARGUMENTS
7 | % expN: An experimental N
8 | % expSTD: An experimental standard deviation
9 | % dataGroupDescription: Data group description. Should be one of:
10 | % binTable
11 | % distTable
12 | % brTableRECIST
13 | % rTableRECIST
14 | % mnSDTablemean
15 | % mnSDTablevariance
16 | % simN: Assumed N for weighting for the simulation results
17 | % RETURNS
18 | % w: A weighting factor.
19 | %
20 |
21 | if strcmp(dataGroupDescription(1:length('binTable')), 'binTable')
22 | w = sqrt((expN*simN)/(expN+simN));
23 |
24 | elseif strcmp(dataGroupDescription(1:length('distTable')), 'distTable')
25 | w = sqrt((expN*simN)/(expN+simN));
26 |
27 | elseif strcmp(dataGroupDescription(1:length('distTable2D')), 'distTable2D')
28 | w = sqrt((expN*simN)/(expN+simN));
29 |
30 | elseif strcmp(dataGroupDescription(1:length('brTableRECIST')), 'brTableRECIST')
31 | w = sqrt((expN*simN)/(expN+simN));
32 |
33 | elseif strcmp(dataGroupDescription(1:length('rTableRECIST')), 'rTableRECIST')
34 | w = sqrt((expN*simN)/(expN+simN));
35 |
36 | elseif strcmp(dataGroupDescription(1:length('mnSDTable')), 'mnSDTable') && strcmp(dataGroupDescription(end-length('mean')+1:end), 'mean')
37 | w = 1/(expSTD*sqrt(1/expN+1/simN));
38 |
39 | elseif strcmp(dataGroupDescription(1:length('mnSDTable')), 'mnSDTable') && strcmp(dataGroupDescription(end-length('variance')+1:end), 'variance')
40 | w = 1/(expSTD*sqrt(1/expN+1/simN));
41 | elseif strcmp(dataGroupDescription(1:length('corTable')), 'corTable')
42 | if expN>3 && simN>3
43 | w = 1/sqrt(1/(expN-3)+1/(simN-3));
44 | else
45 | warning(['Either expN or simN is less than or equal to 3, modify weight calculation in ' mfilename ' to avoid NaN'])
46 | w = 1/sqrt(1/(expN)+1/(simN));
47 | end
48 | else
49 | error('data group not supported');
50 | end
51 |
52 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/calculateExpWeightFix.m:
--------------------------------------------------------------------------------
1 | function w = calculateExpWeightFix(expN, expSTD, dataGroupDescription, simN)
2 | % This is a utility function to fix the experimental
3 | % weight to 1 for the different data group types
4 | % in linear calibrate.
5 | %
6 | % ARGUMENTS
7 | % expN: An experimental N, these are ignored here
8 | % expSTD: An experimental standard deviation
9 | % dataGroupDescription: Data group description. Should be one of:
10 | % binTable
11 | % distTable
12 | % brTableRECIST
13 | % rTableRECIST
14 | % mnSDTablemean
15 | % mnSDTablevariance
16 | % corTable
17 | % simN: Assumed N for weighting for the simulation results
18 | % RETURNS
19 | % w: A weighting factor.
20 | %
21 |
22 | % We will also try supplementing the VP scores scaled into PWs. This
23 | % likely won't be very effective at finding optimal solutions but will add
24 | % points where VPs in sparser regions of the distributions relative to the data
25 | % are more highly weighted which could help to weight to where it is needed
26 | % without overly focusing on a few VPs
27 | if strcmp(dataGroupDescription(1:length('binTable')), 'binTable')
28 | w = 1;
29 |
30 | elseif strcmp(dataGroupDescription(1:length('distTable')), 'distTable')
31 | w = 1;
32 |
33 | elseif strcmp(dataGroupDescription(1:length('distTable2D')), 'distTable2D')
34 | w = 1;
35 |
36 | elseif strcmp(dataGroupDescription(1:length('brTableRECIST')), 'brTableRECIST')
37 | w = 1;
38 |
39 | elseif strcmp(dataGroupDescription(1:length('rTableRECIST')), 'rTableRECIST')
40 | w = 1;
41 |
42 | elseif strcmp(dataGroupDescription(1:length('mnSDTable')), 'mnSDTable') && strcmp(dataGroupDescription(end-length('mean')+1:end), 'mean')
43 | w = 1;
44 |
45 | elseif strcmp(dataGroupDescription(1:length('mnSDTable')), 'mnSDTable') && strcmp(dataGroupDescription(end-length('variance')+1:end), 'variance')
46 | w = 1;
47 | elseif strcmp(dataGroupDescription(1:length('corTable')), 'corTable')
48 | w = 1;
49 | else
50 | error('data group not supported');
51 | end
52 |
53 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/calculateExpWeightFixSingle.m:
--------------------------------------------------------------------------------
1 | function w = calculateExpWeightFixSingle(expN, expSTD, dataGroupDescription, simN, keepType)
2 | % This is a utility function to fix the experimental
3 | % weight to 1 for a single data group type
4 | % in linear calibrate.
5 | %
6 | % ARGUMENTS
7 | % expN: An experimental N, these are ignored here
8 | % expSTD: An experimental standard deviation
9 | % dataGroupDescription: Data group description. Should be one of:
10 | % binTable
11 | % distTable
12 | % brTableRECIST
13 | % rTableRECIST
14 | % mnSDTablemean
15 | % mnSDTablevariance
16 | % corTable
17 | % simN: Assumed N for weighting for the simulation results
18 | % keepType: data group description to keep
19 | % nonzero. Note: use mnSDTable rather than
20 | % mnSDTablemean, mnSDTablevariance
21 | % RETURNS
22 | % w: A weighting factor.
23 | %
24 |
25 | if strcmp(dataGroupDescription(1:length('binTable')), 'binTable')
26 | if strcmp(keepType,'binTable')
27 | w = 1;
28 | else
29 | w = 0;
30 | end
31 |
32 | elseif strcmp(dataGroupDescription(1:length('distTable')), 'distTable')
33 | if strcmp(keepType,'distTable')
34 | w = 1;
35 | else
36 | w = 0;
37 | end
38 |
39 | elseif strcmp(dataGroupDescription(1:length('distTable2D')), 'distTable2D')
40 | if strcmp(keepType,'distTable')
41 | w = 1;
42 | else
43 | w = 0;
44 | end
45 |
46 | elseif strcmp(dataGroupDescription(1:length('brTableRECIST')), 'brTableRECIST')
47 | if strcmp(keepType,'distTable')
48 | w = 1;
49 | else
50 | w = 0;
51 | end
52 |
53 | elseif strcmp(dataGroupDescription(1:length('rTableRECIST')), 'rTableRECIST')
54 | if strcmp(keepType,'rTableRECIST')
55 | w = 1;
56 | else
57 | w = 0;
58 | end
59 |
60 | elseif strcmp(dataGroupDescription(1:length('mnSDTable')), 'mnSDTable') && strcmp(dataGroupDescription(end-length('mean')+1:end), 'mean')
61 | if strcmp(keepType,'mnSDTable')
62 | w = 1;
63 | else
64 | w = 0;
65 | end
66 |
67 |
68 | elseif strcmp(dataGroupDescription(1:length('mnSDTable')), 'mnSDTable') && strcmp(dataGroupDescription(end-length('variance')+1:end), 'variance')
69 | if strcmp(keepType,'mnSDTable')
70 | w = 1;
71 | else
72 | w = 0;
73 | end
74 | elseif strcmp(dataGroupDescription(1:length('corTable')), 'corTable')
75 | if strcmp(keepType,'corTable')
76 | w = 1;
77 | else
78 | w = 0;
79 | end
80 | else
81 | error('data group not supported');
82 | end
83 |
84 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/combineBins.m:
--------------------------------------------------------------------------------
1 | function myVPop = combineBins(myVPop)
2 | % Take an existing population and combine the axis bins, such that N bins
3 | % becomes N/2 bins. This is an auxiliary function that may be helpful
4 | % if testing using different numbers of axis bins for the VPop.
5 | % Note that you need to start with an even number of bins per axis
6 | % for this function.
7 | %
8 | % ARGUMENTS
9 | % myVPop: An instance of a VPop object. Properties should be
10 | % populated:
11 | % binEdges
12 | % indexTable
13 | % mnSDTable
14 | % binTable
15 | % simData
16 | %
17 | % RETURNS
18 | % myVpop: VPop with updated properties:
19 | % binEdges
20 | % binMidPoints
21 | % binProbs
22 | % gofMn
23 | % gofSD
24 | % gofBin
25 | % gof
26 | %
27 |
28 | continueFlag = false;
29 | if nargin > 1
30 | warning([mfilename,' requires input argument: myVPop. Too many arguments provided.']);
31 | elseif nargin >0
32 | continueFlag = true;
33 | else
34 | warning([mfilename,' requires input argument: myVPop. Insufficient arguments provided.'])
35 | end
36 |
37 | if continueFlag
38 | if class(myVPop) ~= 'VPop'
39 | warning(['An argument of class VPop is required in ',mfilename,'. Exiting.'])
40 | continueFlag = false;
41 | end
42 | end
43 |
44 | if continueFlag
45 | [myNAxis, myNBins] = size(myVPop.binMidPoints);
46 | if mod(myNBins,2) > 0
47 | warning(['Unable to combine bins in ',mfilename,'. An even number of bins is required. Exiting'])
48 | continueFlag = false;
49 | end
50 | end
51 |
52 | if continueFlag
53 | for axisCounter = 1 : myNAxis
54 | for binCounter = 1 : (myNBins/2)
55 | downAdjustBin = 2 * binCounter;
56 | myIndices = find(myVPop.indexTable(axisCounter,:) == downAdjustBin);
57 | indexTable(axisCounter,myIndices) = binCounter;
58 | end
59 | end
60 | myVPop.binEdges = myVPop.binEdges(:,[1:2:length(myVPop.binEdges(axisCounter,:))]);
61 | newMidPoints = nan(myNAxis,myNBins/2);
62 | newBinProbs = nan(myNAxis,myNBins/2);
63 | for binCounter = 1 : (myNBins/2)
64 | newMidPoints(:,binCounter) = 0.5*myVPop.binEdges(:,binCounter)+0.5*myVPop.binEdges(:,binCounter+1);
65 | newBinProbs(:,binCounter) = myVPop.binProbs(:,2*(binCounter-1)+1)+myVPop.binProbs(:,2*(binCounter));
66 | end
67 | myVPop.binMidPoints = newMidPoints;
68 | myVPop.binProbs = newBinProbs;
69 | myVPop = evaluateGOF(myVPop);
70 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/hyperTransform.m:
--------------------------------------------------------------------------------
1 | function probVectTrans = hyperTransform(probVect)
2 | % Hyperspherical coordinate transform
3 | %
4 | % ARGUMENTS
5 | % probVect: a vector of probabilities (0-1, sum to 1)
6 | %
7 | % RETURNS
8 | % probVectTrans: the transformed probability vector
9 | %
10 |
11 | % We need to do this because for hyperspherical
12 | % coords sum(x**2) = 1, for us sum(x) = 1 (probability)
13 | probVect = (probVect).^.5;
14 | nProbs = length(probVect);
15 | % We likely want a row vector out of the function
16 | probVectTrans = nan(1, nProbs-1);
17 |
18 | for pCounter = 1 : (nProbs-2)
19 | probVectTrans(pCounter) = atan2( sqrt(sum((probVect((pCounter+1):nProbs)).^2)),probVect(pCounter) );
20 | end
21 |
22 |
23 | probVectTrans(nProbs-1) = atan2(probVect(nProbs),probVect(nProbs-1));
24 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/initializeOptionPropertiesToVPop.m:
--------------------------------------------------------------------------------
1 | function myVPop = initializeOptionPropertiesToVPop(myMapelOptions)
2 | % This is a simple utility function to copy all of the properties from
3 | % an options object to a VPop. Note Copying over myMapelOptions.initialPWs
4 | % is not done here. It is assumed appropriate treatment of these
5 | % is done in a calling script.
6 | % Also can't be set up here:
7 | % indexTable
8 | % binEdges
9 | % binMidPoints
10 | % binProbs
11 | % simData
12 | % recistSimFilter
13 | %
14 | % ARGUMENTS
15 | % myMapelOptions: (Required) an instance of a mapelOptions object.
16 | %
17 | % RETURNS
18 | % VPop: an instance of a VPop
19 | %
20 |
21 | if isa(myMapelOptions, 'mapelOptions')
22 | myVPop = VPop;
23 | elseif isa(myMapelOptions, 'mapelOptionsRECIST')
24 | myVPop = VPopRECIST;
25 | end
26 | % First, get the properties from myMapelOptions
27 |
28 |
29 | myVPop.pwStrategy = myMapelOptions.pwStrategy;
30 | myVPop.mnSDTable = myMapelOptions.mnSDTable;
31 | myVPop.binTable = myMapelOptions.binTable;
32 | myVPop.distTable = myMapelOptions.distTable;
33 | myVPop.distTable2D = myMapelOptions.distTable2D;
34 | myVPop.corTable = myMapelOptions.corTable;
35 | myVPop.subpopTable = myMapelOptions.subpopTable;
36 | myVPop.expData = myMapelOptions.expData;
37 | myVPop.spreadOut = myMapelOptions.spreadOut;
38 | myVPop.minIndPVal = myMapelOptions.minIndPVal;
39 | myVPop.useEffN = myMapelOptions.useEffN;
40 | myVPop.exactFlag = myMapelOptions.exactFlag;
41 | myVPop.optimizeTimeLimit = myMapelOptions.optimizeTimeLimit;
42 | myVPop.optimizeType = myMapelOptions.optimizeType;
43 | myVPop.optimizePopSize = myMapelOptions.optimizePopSize;
44 | myVPop.objectiveLimit = myMapelOptions.objectiveLimit;
45 | myVPop.poolClose = myMapelOptions.poolClose;
46 | myVPop.poolRestart = myMapelOptions.poolRestart;
47 | myVPop.intSeed = myMapelOptions.intSeed;
48 | myVPop.tol = myMapelOptions.tol;
49 | myVPop.nIters = myMapelOptions.nIters;
50 | myVPop.minEffN = myMapelOptions.minEffN;
51 |
52 | if isa(myVPop,'VPopRECIST')
53 | myVPop.brTableRECIST = myMapelOptions.brTableRECIST;
54 | myVPop.rTableRECIST = myMapelOptions.rTableRECIST;
55 | myVPop.relSLDvar = myMapelOptions.relSLDvar;
56 | myVPop.absALDVar = myMapelOptions.absALDVar;
57 | myVPop.crCutoff = myMapelOptions.crCutoff;
58 | end
59 |
60 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/initializeVPopPropertiesToOption.m:
--------------------------------------------------------------------------------
1 | function myMapelOptions = initializeVPopPropertiesToOption(myVPop)
2 | % This is a simple utility function to copy all of the properties from
3 | % a VPop back to a MapelOptions.
4 | %
5 | % ARGUMENTS
6 | % myVPop: (Required) an instance of a VPop
7 | %
8 | % RETURNS
9 | % myMapelOptions: an instance of a mapelOptions object
10 | %
11 |
12 | if isa(myVPop, 'VPop')
13 | myMapelOptions = mapelOptions;
14 | elseif isa(myVPop, 'VPopRECIST')
15 | myMapelOptions = mapelOptionsRECIST;
16 | end
17 | % First, get the properties from myVPop
18 | % Also, note these are lost here:
19 | % indexTable
20 | % binEdges
21 | % binMidPoints
22 | % binProbs
23 | % simData
24 | % recistSimFilter
25 |
26 | myMapelOptions.pwStrategy = myVPop.pwStrategy;
27 | myMapelOptions.mnSDTable = myVPop.mnSDTable;
28 | myMapelOptions.binTable = myVPop.binTable;
29 | myMapelOptions.distTable = myVPop.distTable;
30 | myMapelOptions.distTable2D = myVPop.distTable2D;
31 | myMapelOptions.corTable = myVPop.corTable;
32 | myMapelOptions.subpopTable = myVPop.subpopTable;
33 | myMapelOptions.expData = myVPop.expData;
34 | myMapelOptions.spreadOut = myVPop.spreadOut;
35 | myMapelOptions.minIndPVal = myVPop.minIndPVal;
36 | myMapelOptions.useEffN = myVPop.useEffN;
37 | myMapelOptions.exactFlag = myVPop.exactFlag;
38 | myMapelOptions.optimizeTimeLimit = myVPop.optimizeTimeLimit;
39 | myMapelOptions.optimizeType = myVPop.optimizeType;
40 | myMapelOptions.optimizePopSize = myVPop.optimizePopSize;
41 | myMapelOptions.objectiveLimit = myVPop.objectiveLimit;
42 | myMapelOptions.poolClose = myVPop.poolClose;
43 | myMapelOptions.poolRestart = myVPop.poolRestart;
44 | myMapelOptions.intSeed = myVPop.intSeed;
45 | myMapelOptions.tol = myVPop.tol;
46 | myMapelOptions.nIters = myVPop.nIters;
47 | myMapelOptions.minEffN = myVPop.minEffN;
48 |
49 | if ~isempty(myVPop.binMidPoints)
50 | [~,myMapelOptions.nBins] = size(myVPop.binMidPoints);
51 | else
52 | myMapelOptions.nBins = 2;
53 | end
54 | myMapelOptions.initialProbs = myVPop.binProbs;
55 | myMapelOptions.initialPWs = myVPop.pws;
56 | % randomStart not on VPop
57 |
58 | if isa(myVPop,'VPopRECIST')
59 | myMapelOptions.brTableRECIST = myVPop.brTableRECIST;
60 | myMapelOptions.rTableRECIST = myVPop.rTableRECIST;
61 | myMapelOptions.relSLDvar = myVPop.relSLDvar;
62 | myMapelOptions.absALDVar = myVPop.absALDVar;
63 | myMapelOptions.crCutoff = myVPop.crCutoff;
64 | end
65 |
66 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/invHyperTransform.m:
--------------------------------------------------------------------------------
1 | function probVect = invHyperTransform(probVectTrans)
2 | % Recover probabilities from hyperspherical coordinate transform
3 | %
4 | % ARGUMENTS
5 | % probVectTrans: the transformed probability vector
6 | %
7 | % RETURNS
8 | % probVect: a vector of probabilities (0-1, sum to 1)
9 | %
10 |
11 | probVect = [cos(probVectTrans) 1] .* [1 cumprod(sin(probVectTrans))];
12 | probVect = probVect.^2;
13 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/loadCommonNames.m:
--------------------------------------------------------------------------------
1 | function commonNames = loadCommonNames()
2 | % This is a simple function that returns a struct with useful
3 | % information for names for items such as table headers.
4 | % This is intended to ensure consistency in table
5 | % formatting and references.
6 | %
7 | % ARGUMENTS:
8 | % none
9 | %
10 | % RETURNS
11 | % commonNames: A structure with useful names
12 | %
13 |
14 | commonNames = struct;
15 | % Add table header variables.
16 | commonNames.RESPONSETABLEVARNAMESFIXED = {'subpopNo','time', 'expVarID', 'interventionID','elementID','elementType', 'expDataID', 'expTimeVarID','PatientIDVar','TRTVar','BRSCOREVar','RSCOREVar'};
17 | commonNames.VPOPRECISTTABLEVARNAMESFIXED = {'subpopNo','time', 'interventionID', 'elementID', 'elementType', 'expDataID', 'expTimeVarID', 'expVarID','PatientIDVar','TRTVar','BRSCOREVar','RSCOREVar'};
18 | commonNames.VPOPTABLEVARNAMESFIXED = {'subpopNo','time', 'interventionID', 'elementID', 'elementType', 'expDataID', 'expTimeVarID', 'expVarID','PatientIDVar'};
19 | commonNames.VPOPEXPTABLEVARNAMESFIXED = commonNames.VPOPTABLEVARNAMESFIXED;
20 | commonNames.VPOPRECISTEXPTABLEVARNAMESFIXED = commonNames.VPOPRECISTTABLEVARNAMESFIXED;
21 | commonNames.VPOPRECISTRESPONSETABLEVARNAMESFIXED = {'subpopNo','time', 'expVarID', 'interventionID', 'elementID', 'elementType', 'expDataID', 'expTimeVarID', 'PatientIDVar','TRTVar','BRSCOREVar','RSCOREVar'};
22 | commonNames.VPOP2DTABLEVARNAMESFIXED = {'subpopNo','time1','time2','interventionID1','interventionID2','elementID1','elementID2','elementType1','elementType2','expDataID1','expDataID2','expTimeVarID1','expTimeVarID2','expVarID1','expVarID2','PatientIDVar1','PatientIDVar2'}; % Lu edited: added 'PatientIDVar1','PatientIDVar2'
23 | commonNames.VPOPRECIST2DTABLEVARNAMESFIXED = {'subpopNo','time1','time2','interventionID1','interventionID2','elementID1','elementID2','elementType1','elementType2','expDataID1','expDataID2','expTimeVarID1','expTimeVarID2','expVarID1','expVarID2','PatientIDVar1','PatientIDVar2','TRTVar1','TRTVar2','BRSCOREVar1','BRSCOREVar2','RSCOREVar1','RSCOREVar2'};
24 | commonNames.SUBPOPTABLEVARNAMESFIXED = {'subpopID','time','interventionID', 'elementID', 'elementType','comparator','value'};
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/probsToProbVect.m:
--------------------------------------------------------------------------------
1 | function myProbVect = probsToProbVect(myProbs)
2 | % Reshape a mxn table of axis probilities (m axis, n bins in each axis)
3 | % to a 1 X m*n vector.
4 | % This is needed in order to feed the vector to the optimization
5 | % algorithms
6 | %
7 | % ARGUMENTS
8 | % myProbs: an array of axis probabilities, preferentially already
9 | % transformed.
10 | %
11 | myProbVect = reshape(transpose(myProbs),[],1);
12 | myProbVect = transpose(myProbVect);
13 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/spreadPWsToNeighbors.m:
--------------------------------------------------------------------------------
1 | function myNewPWs = spreadPWsToNeighbors(myPWs,myCoefficients,nNew)
2 | % This is a "utility function" that should be called directly.
3 | % This function will generate new PW guesses spread
4 | % around an initial guess, with weights given
5 | % preferentially to nearer neighbors.
6 | %
7 | % ARGUMENTS
8 | % myPWs: a 1 x nVPs vector of prevalence weights
9 | % myCoefficients an nAxis x nVP matrix of coefficients
10 | % nNew number of new PW solutions to add
11 | %
12 | % RETURNS
13 | % myNewPWs: original PWs appended with additional
14 | % (nNew + 1) x nVP matrix
15 | %
16 |
17 | [nDim,nVPs] = size(myCoefficients);
18 | % To speed up, we will focus on shifting weight
19 | % for up to the top 200 PWs
20 | nParents = min(nVPs,200);
21 | [~,parentIndices] = sort(myPWs,'descend');
22 | parentIndices = parentIndices(1:nParents);
23 | vpDistance = pdist2(myCoefficients',myCoefficients');
24 | % Maximim allowed my. i.e. mu of 4
25 | % will leave 25% of weight on the parent
26 | spreadMuMax = min(4,nParents/2);
27 |
28 | % We will generate new guesses that follow exponential
29 | % distributions around the initial point
30 | myNewPWs = myPWs;
31 | myNewPWs(parentIndices) = 0;
32 | myNewPWs = repmat(myNewPWs,nNew,1);
33 | % mu is the mu parameter from the exponential distribution
34 | mu = rand([nNew,1,nParents])*spreadMuMax;
35 | % Each parent VP from the original solution (outer loop)
36 | % will have some of his mass shifted onto neighbors according
37 | % to the exponential spread.
38 | spreadVals = exppdf(repmat([0:1:(nVPs-1)],nNew,1,nParents),mu);
39 | % loop over VPs in the outer loop so we only have to sort distances
40 | % for each VP once
41 | for parentCounter = 1 : nParents
42 | parentIndex = parentIndices(parentCounter);
43 | [~, sortIndex] = sort(vpDistance(parentIndex,:),'ascend');
44 | % Normalize the spreadvals to make sure each row sums to 1
45 | spreadValsCur = spreadVals(:,:,parentCounter)./sum(spreadVals(:,:,parentCounter),2);
46 | %for distCounter = 1 : nNew
47 | %myNewPWs(distCounter, sortIndex) = myPWs(parentCounter)*spreadVals(distCounter,:)+myNewPWs(distCounter, sortIndex);
48 | myNewPWs(:, sortIndex) = myPWs(parentIndex)*spreadValsCur+myNewPWs(:, sortIndex);
49 | %end
50 | end
51 | myNewPWs = [myPWs;myNewPWs];
52 | end
--------------------------------------------------------------------------------
/QSPToolbox/population/utility/subsetWorksheetVPop.m:
--------------------------------------------------------------------------------
1 | function [myWorksheet, myVPop] = subsetWorksheetVPop(myWorksheet, myVPop, myVPIDs, equalizePWflag)
2 | % This function will take an input paired worksheet and VPop
3 | % and return a subsetted worksheet/VPop combination
4 | %
5 | % ARGUMENTS
6 | % myWorksheet: A worksheet structure
7 | % myVPop: A VPop object
8 | % myVPIDs: A 1xN set of VPIDs to selected
9 | % equalizePWflag: (optional, default FALSE) A boolean indicating
10 | % whether to reset all of the PWs to 1/N.
11 | % Default behavior is to re-normalize to 1
12 | % but not reset to be equal. If pwStrategy is
13 | % 'bin', the same bin probabilities are kept
14 | % and equalize will set the bin probabilities
15 | % to be the same.
16 | % RETURNS
17 | % myWorksheet
18 | % myVPop
19 |
20 | % Perform initial checks on the provided arguments
21 | flagContinue = true;
22 |
23 | if nargin > 4
24 | warning([mfilename,' requires input argument: myWorksheet, myVPop, myVPIDs, and optionally equalizePWflag. Too many arguments provided.'])
25 | flagContinue = false;
26 | elseif nargin > 3
27 | flagContinue = true;
28 | elseif nargin > 2
29 | equalizePWflag = false;
30 | flagContinue = true;
31 | elseif nargin < 1
32 | warning([mfilename,' requires input argument: myWorksheet, myVPop, myVPIDs, and optionally equalizePWflag. Insufficient arguments provided.'])
33 | flagContinue = true;
34 | end
35 |
36 |
37 |
38 | if flagContinue
39 | vpIDsAll = getVPIDs(myWorksheet);
40 | iMaskVPIDsKeep = ismember(vpIDsAll,myVPIDs);
41 | if (~isempty(myVPop.LinearProblemMatrices))
42 | myVPop.LinearProblemMatrices.vpIsInSubgroup = myVPop.LinearProblemMatrices.vpIsInSubgroup(:,iMaskVPIDsKeep);
43 | myVPop.LinearProblemMatrices.independentVarValsWeighted = myVPop.LinearProblemMatrices.independentVarValsWeighted(:,iMaskVPIDsKeep);
44 | myVPop.LinearProblemMatrices.independentVarVals = myVPop.LinearProblemMatrices.independentVarVals(:,iMaskVPIDsKeep);
45 | end
46 | vpIDsKeep = vpIDsAll(iMaskVPIDsKeep);
47 | myWorksheet = copyWorksheet(myWorksheet,vpIDsKeep);
48 | if isa(myVPop,'VPopRECIST')
49 | myVPop.recistSimFilter = createRECISTSimFilter(myWorksheet, myVPop, false);
50 | end
51 | myVPop = myVPop.getSimData(myWorksheet);
52 |
53 | if isequal(myVPop.pwStrategy,'direct')
54 | if ~equalizePWflag
55 | prevalenceWeightsRenormalized = myVPop.pws(iMaskVPIDsKeep);
56 | prevalenceWeightsRenormalized = prevalenceWeightsRenormalized/sum(prevalenceWeightsRenormalized);
57 | else
58 | prevalenceWeightsRenormalized = 1/sum(iMaskVPIDsKeep) * ones(1,sum(iMaskVPIDsKeep));
59 | end
60 | myVPop.pws = prevalenceWeightsRenormalized;
61 | else
62 | myVPop.indexTable = myVPop.indexTable(:,iMaskVPIDsKeep);
63 | if equalizePWflag
64 | myVPop = myVPop.startProbs(false);
65 | end
66 | myVPop = myVPop.assignPWs();
67 | end
68 |
69 | myVPop = myVPop.assignCoeffs(myWorksheet);
70 | myVPop.subpopTable = updateSubpopTableVPs(myVPop.subpopTable, myWorksheet);
71 | myVPop = myVPop.addTableSimVals();
72 | myVPop = myVPop.addPredTableVals();
73 | myVPop = evaluateGOF(myVPop);
74 | myVPop = evaluateMSE(myVPop);
75 | else
76 | warning(['Could not complete ',mfilename,'. Returning original worksheet, VPop.'])
77 | end
78 | end
--------------------------------------------------------------------------------
/QSPToolbox/visp/createViSPInput.m:
--------------------------------------------------------------------------------
1 | function createViSPInput(myWorksheet, myFileName)
2 | % Transform a worksheet into an input file for ViSP.
3 | % Note this should be run on the target simulation
4 | % architecture.
5 | %
6 | % ARGUMENTS
7 | % myWorksheet: A worksheet.
8 | % myFileName: The file to save to. ".mat" will be appended.
9 | %
10 | % RETURNS
11 | % nothing
12 | %
13 |
14 | flagContinue = false;
15 | if nargin > 2
16 | warning([mfilename,' requires input arguments: myWorksheet, myFileName. Too many arguments provided.'])
17 | elseif nargin < 2
18 | warning([mfilename,' requires input argument: myWorksheet, myFileName. Insufficient arguments provided.'])
19 | else
20 | flagContinue = true;
21 | end
22 |
23 | if flagContinue
24 |
25 | simBioModel = copyobj(myWorksheet.model);
26 |
27 | [modelValues,modelIndices, dosesArray,~,modelNames,~]...
28 | = getSimulateValuesDosesSep(myWorksheet);
29 | indices = GetIndices(modelValues,modelIndices);
30 | [paramValues,paramNames] = GetParamNamesAndValuesToStoreInDB(modelValues,modelNames,indices);
31 |
32 | simBioModel = UpdateSimBioModel(myWorksheet.compiled.elements, simBioModel, modelValues,indices);
33 | exportedModel = CreateExportedModel(simBioModel);
34 | exportedModel = SetSimulationOptionsInExportedModel(exportedModel,'myWorksheet',myWorksheet);
35 |
36 | vispSimBioInput.paramValues = paramValues;
37 | vispSimBioInput.paramNames = paramNames;
38 | vispSimBioInput.dosesArray = dosesArray;
39 | vispSimBioInput.exportedModel = exportedModel;
40 | vispSimBioInput.mySaveElementResultIDs = myWorksheet.simProps.saveElementResultIDs;
41 | save(myFileName,'-struct','vispSimBioInput');
42 | disp('Saved Visp SimBio Input')
43 | end
44 | end
45 |
46 | function config = GetConfigForInput(fname)
47 | config_data = readtable(fname, 'Delimiter', '|');
48 | config = containers.Map(config_data{:,1}, config_data{:,2});
49 | end
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/QSPToolbox/visp/utility/CreateExportedModel.m:
--------------------------------------------------------------------------------
1 | function exportedModel = CreateExportedModel(simBioModel)
2 |
3 | %simBioModel = copyobj(myWorksheet.model);
4 | allModelParameters = get(simBioModel, 'Parameters');
5 | allModelSpecies = get(simBioModel, 'Species');
6 | allModelCompartments = get(simBioModel, 'Compartments');
7 | exportElements = [allModelParameters;allModelSpecies;allModelCompartments];
8 | allModelDoses = get(simBioModel, 'Doses');
9 |
10 | simBioModel.ConfigSet.CompileOptions.UnitConversion = false;
11 | simBioModel.ConfigSet.CompileOptions.DimensionalAnalysis = false;
12 |
13 | exportedModel = export(simBioModel, exportElements, allModelDoses);
14 |
15 | end
--------------------------------------------------------------------------------
/QSPToolbox/visp/utility/GetDoseNames.m:
--------------------------------------------------------------------------------
1 | function doseNames = GetDoseNames(doseArray)
2 | doseNames = cell(1,length(doseArray));
3 | for theIndex = 1: length(doseArray)
4 | doseNames{counter} = get(doseArray{theIndex},'Name');
5 | end
6 | for theIndex = 1: length(theDoseIndices)
7 | counter = counter + 1;
8 | theDoseArray = [theDoseArray, myModelDoseObjects(theDoseIndices(theIndex))];
9 | intervention(counter) = interventionCounter;
10 | names{counter} = get(myModelDoseObjects(theDoseIndices(theIndex)),'Name');
11 | end
12 | end
--------------------------------------------------------------------------------
/QSPToolbox/visp/utility/GetIndices.m:
--------------------------------------------------------------------------------
1 | function indices = GetIndices(modelValues,modelIndices)
2 |
3 | numSim = size(modelValues,1)*size(modelValues,2);
4 | numParam = size(modelValues,3);
5 | reshapedModelValues = reshape(modelValues,numSim,numParam);
6 |
7 | filter = max(reshapedModelValues,[],1)- min(reshapedModelValues,[],1)==0;
8 | indices.constantParam = find(filter)';
9 | indices.modelElemToSet = modelIndices(indices.constantParam);
10 |
11 | filter = max(reshapedModelValues,[],1)- min(reshapedModelValues,[],1)~=0;
12 | indices.varyingParam = find(filter)';
13 |
14 |
15 | end
16 |
--------------------------------------------------------------------------------
/QSPToolbox/visp/utility/GetParamNamesAndValuesToStoreInDB.m:
--------------------------------------------------------------------------------
1 | function [paramValues,paramNames] = GetParamNamesAndValuesToStoreInDB(modelValues,modelNames,indices)
2 |
3 | paramValues = modelValues(:,:,indices.varyingParam);
4 | paramNames = modelNames(indices.varyingParam);
5 |
6 | end
7 |
8 |
9 |
--------------------------------------------------------------------------------
/QSPToolbox/visp/utility/UpdateSimBioModel.m:
--------------------------------------------------------------------------------
1 | function simBioModel = UpdateSimBioModel(modelElements,simBioModel,modelValues,indices)
2 | for counter = 1:length(indices.modelElemToSet)
3 | paramName = modelElements{indices.modelElemToSet(counter),1};
4 | paramType = modelElements{indices.modelElemToSet(counter),2};
5 | paramValue = modelValues(1,1,indices.constantParam(counter));
6 | myObject = sbioselect(simBioModel,'Type',paramType,'Name',paramName);
7 | set(myObject,'Value',paramValue);
8 | end
9 | end
10 |
11 |
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/axis/getAxisDef.m:
--------------------------------------------------------------------------------
1 | function myAxisDef = getAxisDef(myWorksheet, myAxisDefID)
2 | % Get axisDef from a worksheet
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet, required
5 | % myAxisDefID: String identifier for the axis
6 | %
7 | % RETURNS
8 | % myAxisDef: the desired axis definition
9 |
10 | axisDefIDs = getAxisDefIDs(myWorksheet);
11 | theMemberTrue = ismember(axisDefIDs, myAxisDefID);
12 | if sum(theMemberTrue) < 1
13 | error('Specified axis ID not in model')
14 | elseif sum(theMemberTrue) > 1
15 | error('Specified axis ID degenerate in model')
16 | else
17 | axisIndex = find(theMemberTrue);
18 | myAxisDef = myWorksheet.axisProps.axisDef{axisIndex};
19 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/axis/getAxisDefBounds.m:
--------------------------------------------------------------------------------
1 | function axisDefElementBounds = getAxisDefBounds(myWorksheet, myAxisID)
2 | % Get mechanistic axes bounds from a worksheet
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet, required
5 | % myAxisID: axis to get the bounds for
6 | %
7 | % RETURNS
8 | % axisDefElementBounds: a nAxisElements X 2 matrix with axis bounds
9 | %
10 |
11 | previousAxesDef = getAxisDef(myWorksheet,myAxisID);
12 | axisDefElementBounds = zeros(0,2);
13 | for axesCounter = 1 : length(previousAxesDef)
14 | curAxisDefElementBounds = previousAxesDef.bounds{axesCounter};
15 | axisDefElementBounds = cat(1, axisDefElementBounds, curAxisDefElementBounds);
16 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/axis/getAxisDefIDs.m:
--------------------------------------------------------------------------------
1 | function axisDefIDs = getAxisDefIDs(myWorksheet)
2 | % Get mechanistic axes IDs from a worksheet
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet, required
5 | %
6 | % RETURNS
7 | % axisDefIDs: a 1 X nAxes cell array with axes IDs
8 | %
9 | previousAxisDef = myWorksheet.axisProps.axisDef;
10 | axisDefIDs = cell(1,0);
11 | for axesCounter = 1 : length(previousAxisDef)
12 | testAxesDef = previousAxisDef{axesCounter};
13 | axisDefIDs = [axisDefIDs, testAxesDef.id];
14 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/axis/getVPCoeffs.m:
--------------------------------------------------------------------------------
1 | function myVPCoeffs = getVPCoeffs(myWorksheet)
2 | % Get VP axes coefficient values from a worksheet
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet, required
5 | %
6 | % RETURNS
7 | % myVPCoefs: an nCoeffs x nVP numeric matrix of coefficient values
8 | %
9 | myVPCoeffs = myWorksheet.axisProps.axisVP.coefficients;
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/axis/getVPValues.m:
--------------------------------------------------------------------------------
1 | function myVPValues = getVPValues(myWorksheet)
2 | % Get VP element values that are defined by axes in a worksheet
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet, required
5 | %
6 | % RETURNS
7 | % myVPValues: a cell array, each element is a matrix of element (parameter) values
8 | %
9 | myCoeffs = getVPCoeffs(myWorksheet);
10 | [nAxes, nVPs] = size(myCoeffs);
11 | myVPValues = cell(nAxes, nVPs);
12 | axesVP = myWorksheet.axisProps.axisVP;
13 | for vpCounter = 1 : nVPs
14 | for axesCounter = 1: nAxes
15 | myVPValues{axesCounter, vpCounter} = axesVP.calculateElementValues([axesCounter, vpCounter], myWorksheet);
16 | end
17 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/axis/utility/setAxisDefBounds.m:
--------------------------------------------------------------------------------
1 | function myWorksheet = setAxisDefBounds(myWorksheet, myAxisID, myBoundsMatrix)
2 | % Set mechanistic axes bounds from a worksheet
3 | % This is just added so we can work with axes bounds as matrices
4 | % rather than a cell array of 1X2 matrices
5 | %
6 | % NOTE: THIS FUNCTION DOES NOT RESET VP COEFFICIENTS! CALL RESETAXISBOUNDS
7 | % TO INCLUDE A VP COEFFICIENT UPDATE!
8 | %
9 | % ARGUMENTS
10 | % myWorksheet: a worksheet, required
11 | % myAxisID: axis to set the bounds for
12 | % myBoundsMatrix
13 | %
14 | % RETURNS
15 | % myWorksheet: worksheet with updated bounds for the indicates axes
16 | %
17 | allAxisIDs = getAxisDefIDs(myWorksheet);
18 | axisIndex = find(ismember(allAxisIDs, myAxisID));
19 | [nElements, dummy] = size(myBoundsMatrix);
20 | myBoundsAsCellArray = cell(1,0);
21 |
22 | for elementCounter = 1 : nElements
23 | myBoundsAsCellArray = [myBoundsAsCellArray, myBoundsMatrix(elementCounter, :)];
24 | end
25 | myWorksheet.axisProps.axisDef{axisIndex}.bounds = myBoundsAsCellArray;
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/convertVPCoefficientsToVariants.m:
--------------------------------------------------------------------------------
1 | function myVariants = convertVPCoefficientsToVariants(myWorksheet, myVPIDs)
2 | % Here, we convert VP Coefficients defined from the axes to a variant.
3 | % This can potentially help in developing virtual populations.
4 | %
5 | % ARGUMENTS:
6 | % myWorksheet A worksheet data structure with VPs and coefficients
7 | % myVPIDs An optional 1xnVP cell array of virtual patient IDs to gather.
8 | % If none are given, all worksheet VP IDs will be used.
9 | %
10 | % RETURNS:
11 | % myVariants A 1xnVP cell array of variants
12 | %
13 |
14 | continueFlag = true;
15 | if nargin > 2
16 | warning(['Too many input arguments provided to ',mfilename,'. Expecting myWorksheet, myVPIDs. Exiting.'])
17 | continueFlag = false;
18 | elseif nargin > 1
19 | continueFlag = true;
20 | elseif nargin > 0
21 | continueFlag = true;
22 | myVPIDs = getVPIDs(myWorksheet);
23 | else
24 | warning(['Too few input arguments provided to ',mfilename,'. Expecting myWorksheet, myVPIDs. Exiting.'])
25 | continueFlag = false;
26 | end
27 |
28 | if continueFlag
29 | allVPIDs = getVPIDs(myWorksheet);
30 | if sum(ismember(myVPIDs,allVPIDs)) < length(myVPIDs)
31 | warning(['Worksheet is missing desired VPIDs in ',mfilename,'. Exiting'])
32 | continueFlag = false;
33 | end
34 | end
35 |
36 | if continueFlag
37 | nVPs = length(myVPIDs);
38 | myVariants = cell(1,nVPs);
39 | myAxisIDs = getAxisDefIDs(myWorksheet);
40 | nAxis = length(myAxisIDs)
41 | myTemplate = cell(1,0);
42 | templateCounter = 0;
43 | for axisCounter = 1:nAxis
44 | myAxisDef = myWorksheet.axisProps.axisDef{axisCounter};
45 | for elementCounter = 1:length(myAxisDef.elementNames)
46 | %curTemplate = cell(1,4);
47 | elementType = myAxisDef.elementTypes{elementCounter};
48 | elementName = myAxisDef.elementNames{elementCounter};
49 | elementValue = NaN;
50 | if strcmp('parameter',elementType)
51 | elementValueType = 'Value';
52 | elseif strcmp('species',elementType)
53 | elementValueType = 'InitialAmount';
54 | else
55 | elementValueType = 'Capacity';
56 | end
57 | myTemplate = [myTemplate,{{elementType,elementName,elementValueType,elementValue}}];
58 | end
59 | end
60 | for vpCounter = 1 : nVPs
61 | curVPValues = myTemplate;
62 | vpIndex = find(ismember(allVPIDs,myVPIDs{vpCounter}));
63 | elementIndex = 0;
64 | for axisCounter = 1 :nAxis
65 | myValues = myWorksheet.axisProps.axisVP.calculateElementValues([axisCounter,vpIndex],myWorksheet);
66 | for memberCounter = 1 : length(myValues)
67 | elementIndex = elementIndex +1;
68 | curVPValues{elementIndex}{4} = myValues(memberCounter);
69 | end
70 | end
71 | myVariants{vpCounter}=sbiovariant(myVPIDs{vpCounter});
72 | myVariants{vpCounter}.Content = curVPValues;
73 | end
74 | else
75 | warning(['Exiting ',mfilename,'.'])
76 | end
77 |
78 |
79 |
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/createWorksheet.m:
--------------------------------------------------------------------------------
1 | function myWorksheet = createWorksheet()
2 | % A simple function to initialize a new blank worksheet.
3 | % This function
4 | % ARGUMENTS
5 | % none
6 | %
7 | % RETURNS
8 | % myWorksheet
9 |
10 | % Worksheets are structures. At some point in the future, we may want to
11 | % re-code them as objects.
12 | myWorksheet = struct();
13 |
14 | % No null value in MATLAB, just use an empty string
15 | myWorksheet.model = '';
16 |
17 | myWorksheet.project = struct();
18 | myWorksheet.project.filePath = '';
19 | myWorksheet.project.fileName = '';
20 |
21 | myWorksheet.compiled = struct();
22 | myWorksheet.compiled.elements = '';
23 | myWorksheet.compiled.doses = '';
24 | myWorksheet.compiled.model = '';
25 |
26 |
27 | % VP definitions will be an 1XnVP array of cells, each cell consiting of
28 | % and appropriate VP
29 | myWorksheet.vpDef = cell(1,0);
30 |
31 | myWorksheet.axisProps = struct();
32 | % axesDef will be an LX1 array of axisDef objects,
33 | myWorksheet.axisProps.axisDef = cell(0,1);
34 | % VP axes will be an 1 vpAxis object,
35 | myWorksheet.axisProps.axisVP = axisVP();
36 | % interventions will be an MX1 array of
37 | % cells, then within each cell we will
38 | % have an intervention structure
39 | myWorksheet.interventions = cell(0,1);
40 | % expData will contain misc. datasets for plotting and optimization
41 | myWorksheet.expData = cell(0,1);
42 | % Response types will include groups of response type elements
43 | % which will be mappings from the responses to intervention
44 | % for certain variables to datasets or specified bounds.
45 | myWorksheet.responseTypes = cell(0,1);
46 |
47 | % simProps will include specifications for the simulation run
48 | myWorksheet.simProps = struct();
49 | myWorksheet.simProps.sampleTimes = [0:0.25:100]';
50 | myWorksheet.simProps.absoluteTolerance = 1e-8;
51 | myWorksheet.simProps.absoluteToleranceStepSize = [];%myWorksheet.simProps.absoluteTolerance * myWorksheet.simProps.simTime * 0.1;
52 | myWorksheet.simProps.relativeTolerance = 1e-3;
53 | myWorksheet.simProps.absoluteToleranceScaling = true;
54 | myWorksheet.simProps.maximumWallClock = 5*60;
55 | myWorksheet.simProps.maxStep = [];
56 | myWorksheet.simProps.solverType = 'sundials';
57 | myWorksheet.simProps.saveElementResultIDs = {};
58 |
59 | % We will initialize results to an empty cell
60 | myWorksheet.results = cell(0,0);
61 |
62 | % Variantprops will keep track of the variants to apply to define the
63 | % base VP's, before axes or the effects of interventions are applied.
64 | myWorksheet.variantProps = struct();
65 | % Variant types define the grouping of parameters
66 | myWorksheet.variantProps.variantTypes = cell(0,1);
67 | % Variant type value sets are the types plus specific parameter values
68 | myWorksheet.variantProps.typeValueSets = cell(0,1);
69 |
70 | % Reserved string for splitting variant type and variant description
71 | % in variant names
72 | myWorksheet.variantProps.delimiter = '___';
73 |
74 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/data/getExpData.m:
--------------------------------------------------------------------------------
1 | function myExpData = getExpData(expDataID, myWorksheet)
2 | % Get experimental data from a worksheet
3 | % ARGUMENTS
4 | % expDataID: String identifier for the expData
5 | % myWorksheet: a worksheet, required
6 | %
7 | % RETURNS
8 | % myExpData: the experimental data
9 |
10 | expDataIDs = getExpDataIDs(myWorksheet);
11 | if sum(ismember(expDataIDs, expDataID)) < 1
12 | warning(['Specified data set ID, ',expDataID,', not loaded into worksheet.'])
13 | myExpData = table();
14 | elseif sum(ismember(expDataIDs, expDataID)) > 1
15 | warning(['Specified data set ID, ',expDataID,', degenerate in worksheet.'])
16 | myExpData = table();
17 | else
18 | dataIndex = find(ismember(expDataIDs, expDataID));
19 | myExpData = myWorksheet.expData{dataIndex,1}.('data');
20 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/data/getExpDataIDs.m:
--------------------------------------------------------------------------------
1 | function expDataIDs = getExpDataIDs(myWorksheet)
2 | % Get experiment data IDs from a model
3 | % ARGUMENTS
4 | % worksheet: a worksheet object, required
5 | %
6 | % RETURNS
7 | % expDataIDs: an array of cells with the variant names
8 | %
9 | expDataSets = myWorksheet.expData;
10 | [nDataSets, dummy] = size(expDataSets);
11 | expDataIDs = cell(1, nDataSets);
12 | for dataCounter = 1 : nDataSets
13 | curDataSet = expDataSets{dataCounter};
14 | expDataIDs{dataCounter} = curDataSet.('ID');
15 | end
16 |
17 |
18 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/intervention/createIntervention.m:
--------------------------------------------------------------------------------
1 | function myWorksheet = createIntervention(myWorksheet, interventionID, arrangedIntervention)
2 | % Create an intervention and add it to the worksheet
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet structure, required
5 | % interventionID: a simple text identifier for the intervention
6 | % arrangedIntervention: an (N+M)x2 cell of N Variants and M doses
7 | %
8 | % RETURNS
9 | % worksheet: an updated worksheet with the intervention.
10 | %
11 | % TODO: 1st iteration, might want to add checks on
12 | % the VP variants. This is done before calling createVP() now.
13 | % Also might want to update this to add a set of VPs at once.
14 | newIntervention = struct();
15 | newIntervention.ID = interventionID;
16 | newIntervention.definition = arrangedIntervention;
17 |
18 | % Don't duplicate intervention ID's
19 | % But we will allow multiple base interventions with identical
20 | % variants/doses, since we may alter these
21 | % later
22 | existingInterventionIDs = getInterventionIDs(myWorksheet);
23 | if length(find(ismember(existingInterventionIDs, newIntervention.ID))) == 0
24 | [dummyVar, nExistingInterventions] = size(existingInterventionIDs);
25 | myWorksheet.interventions{nExistingInterventions + 1, 1} = newIntervention;
26 | else
27 | warning(['Input argument interventionID in ',mfilename,' should not already be present in worksheet. Returning input worksheet.'])
28 | end
29 |
30 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/intervention/extractInterventionTypeElements.m:
--------------------------------------------------------------------------------
1 | function interventionSubElements = extractInterventionTypeElements(intervention, type)
2 | % Get the identities of model VARIANTs or DOSEs used by an intervention.
3 | %
4 | % ARGUMENTS
5 | % intervention: an intervention structure
6 | % type: a string indicating the type of model components
7 | % to return from the intervention definition:
8 | % i.e. 'VARIANT' or 'DOSE'
9 | %
10 | % RETURNS
11 | % interventionSubElements: a cell array of strings containing the names
12 | % of the indicated model components.
13 | % Order is maintained.
14 | %
15 | interventionSubElements = cell(0,1);
16 | [nModifiers, nCols] = size(intervention.('definition'));
17 | for modifierCounter = 1 : nModifiers
18 | specType = intervention.('definition'){modifierCounter,1};
19 | specName = intervention.('definition'){modifierCounter,2};
20 | if strcmp(specType, type)
21 | interventionSubElements{length(interventionSubElements) + 1} = specName;
22 | end
23 | end
24 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/intervention/getDoseNames.m:
--------------------------------------------------------------------------------
1 | function doseNames = getDoseNames(worksheet)
2 | % Get dose names from a model
3 | % ARGUMENTS
4 | % worksheet: a worksheet object, required
5 | %
6 | % RETURNS
7 | % doseNames: an array of cells with the dose names
8 | %
9 |
10 | allDoses = getdose(worksheet.model);
11 | nDoses = length(allDoses);
12 | doseNames = cell(nDoses,1);
13 |
14 | for doseCounter = 1 : length(doseNames)
15 | doseNames{doseCounter} = allDoses(doseCounter).('Name');
16 | end
17 |
18 |
19 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/intervention/getInterventionIDs.m:
--------------------------------------------------------------------------------
1 | function interventionIDs = getInterventionIDs(myWorksheet)
2 | % Get VP IDs from a model
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet
5 | %
6 | % RETURNS
7 | % interventionIDs: an array of cells with the intervention names
8 |
9 | interventions = myWorksheet.interventions;
10 | [nInterventions, dummy] = size(interventions);
11 | interventionIDs = cell(1,nInterventions);
12 | for theInterventionCounter = 1 : nInterventions
13 | curIntervention = interventions{theInterventionCounter};
14 | interventionIDs{theInterventionCounter} = curIntervention.('ID');
15 | end
16 |
17 |
18 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/intervention/removeInterventions.m:
--------------------------------------------------------------------------------
1 | function myWorksheet = removeInterventions(myWorksheet, myInterventionIDs)
2 | % Remove Interventions from a worksheet based on ID. Also remove any
3 | % results for that intervention and responseType elements that reference
4 | % it.
5 | %
6 | % ARGUMENTS
7 | % myWorksheet: a worksheet
8 | % interventionIDs: IDs of interventions to remove from worksheet
9 | %
10 | % RETURNS
11 | % myWorksheet: an updated worksheet without the interventions
12 | %
13 | continueFlag = true;
14 | allInterventionIDs = getInterventionIDs(myWorksheet);
15 | nInterventionsToRemove = length(unique(myInterventionIDs));
16 | if sum(ismember(myInterventionIDs,allInterventionIDs)) < nInterventionsToRemove
17 | warning(['Require a list of unique intervention IDs all contained in worksheet in call to ',mfilesname,'. Returning input worksheet'.'])
18 | continueFlag = false;
19 | end
20 |
21 | if continueFlag
22 | interventionIndicestoRemove = nan(nInterventionsToRemove,1);
23 | responseTypeIDs = getResponseTypeIDs(myWorksheet);
24 | nResponseTypes = length(responseTypeIDs);
25 | responseTypeElementIndicesToRemove = cell(nResponseTypes,1);
26 |
27 | resultIndicestoRemove = find(ismember(allInterventionIDs,myInterventionIDs));
28 | nWorksheetInterventions = length(allInterventionIDs);
29 | myWorksheet.interventions(resultIndicestoRemove) = [];
30 | [size1, ~] = size(myWorksheet.results);
31 | if size1 == nWorksheetInterventions
32 | myWorksheet.results(resultIndicestoRemove,:) = [];
33 | end
34 | responseTypeIndicesToRemove = [];
35 | for responseTypeCounter = 1 : nResponseTypes
36 | responseTypeElementIndicesToRemove = [];
37 | responseTypeID = responseTypeIDs{responseTypeCounter};
38 | curResponseType = getResponseType(myWorksheet, responseTypeID);
39 | responseTypeElementIDs = getResponseTypeElementIDs(myWorksheet, responseTypeID);
40 | nResponseTypeElements = length(responseTypeElementIDs);
41 | for responseTypeElementCounter = 1: nResponseTypeElements
42 | curResponseTypeElement = curResponseType.elements{responseTypeElementCounter};
43 | if sum(ismember(properties(curResponseTypeElement),'interventionID')) > 0
44 | if sum(ismember(myInterventionIDs,curResponseTypeElement.interventionID)) > 0
45 | responseTypeElementIndicesToRemove = [responseTypeElementIndicesToRemove,responseTypeElementCounter];
46 | end
47 | end
48 | end
49 | if length(responseTypeElementIndicesToRemove) == nResponseTypeElements
50 | responseTypeIndicesToRemove = [responseTypeIndicesToRemove,responseTypeCounter];
51 | elseif length(responseTypeElementIndicesToRemove) > 0
52 | myWorksheet.responseTypes{responseTypeCounter}.elements(responseTypeElementIndicesToRemove) = [];
53 | end
54 | end
55 | if length(responseTypeIndicesToRemove) > 0
56 | if length(responseTypeIndicesToRemove) < nResponseTypes
57 | myWorksheet.responseTypes(responseTypeIndicesToRemove) = [];
58 | else
59 | myWorksheet.responseTypes = cell(0,1);
60 | end
61 | end
62 | [size1, ~] = size(myWorksheet.results);
63 | if size1 == 0
64 | myWorksheet.results = {};
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/model/getModelCompartmentIDs.m:
--------------------------------------------------------------------------------
1 | function compartmentNames = getModelCompartmentIDs(myWorksheet)
2 | % A simple function to get the compartments IDs from a model included in a
3 | % worksheet.
4 | %
5 | % ARGUMENTS
6 | % myWorksheet
7 | %
8 | % RETURNS
9 | % compartmentNames
10 | %
11 |
12 | myCompartments = get(myWorksheet.model, 'Compartments');
13 | [nCompartments, ~] = size(myCompartments);
14 | compartmentNames = cell(1,nCompartments);
15 | for cCounter = 1 : nCompartments
16 | compartmentNames{1,cCounter} = myCompartments(cCounter).Name;
17 | end
18 |
19 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/model/getModelObservableIDs.m:
--------------------------------------------------------------------------------
1 | function observableNames = getModelObservableIDs(myWorksheet)
2 | % A simple function to get the parameter ID's from a model included in a
3 | % worksheet.
4 | % ARGUMENTS
5 | % myWorksheet
6 | %
7 | % RETURNS
8 | % parameterNames
9 |
10 | myObservables = get(myWorksheet.model, 'Observables');
11 | [nObservables, ~] = size(myObservables);
12 | observableNames = cell(1,nObservables);
13 | for pCounter = 1 : nObservables
14 | observableNames{1,pCounter} = myObservables(pCounter).Name;
15 | end
16 |
17 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/model/getModelParameterIDs.m:
--------------------------------------------------------------------------------
1 | function parameterNames = getModelParameterIDs(myWorksheet)
2 | % A simple function to get the parameter ID's from a model included in a
3 | % worksheet.
4 | % ARGUMENTS
5 | % myWorksheet
6 | %
7 | % RETURNS
8 | % parameterNames
9 |
10 | myParameters = get(myWorksheet.model, 'Parameters');
11 | [nParameters, ~] = size(myParameters);
12 | parameterNames = cell(1,nParameters);
13 | for pCounter = 1 : nParameters
14 | parameterNames{1,pCounter} = myParameters(pCounter).Name;
15 | end
16 |
17 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/model/getModelSpeciesIDs.m:
--------------------------------------------------------------------------------
1 | function speciesNames = getModelSpeciesIDs(myWorksheet)
2 | % A simple function to get the species ID's from a model included in a
3 | % worksheet.
4 | %
5 | % ARGUMENTS
6 | % myWorksheet
7 | %
8 | % RETURNS
9 | % speciesNames
10 | %
11 | mySpecies = get(myWorksheet.model, 'Species');
12 | [nSpecies, ~] = size(mySpecies);
13 | speciesNames = cell(1,nSpecies);
14 | for sCounter = 1 : nSpecies
15 | speciesNames{1,sCounter} = mySpecies(sCounter).Name;
16 | end
17 |
18 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/removeDuplicateVPs.m:
--------------------------------------------------------------------------------
1 | function myWorksheet = removeDuplicateVPs(myWorksheet)
2 | % Remove VPs with duplicate base definitions and axis values.
3 | %
4 | % ARGUMENTS
5 | % myWorksheet: a worksheet
6 | %
7 | % RETURNS
8 | % copiedWorksheet
9 | %
10 |
11 | % Perform initial checks on the provided arguments
12 | flagContinue = false;
13 |
14 | if nargin > 1
15 | warning([mfilename,' requires input argument: myWorksheet. Too many arguments provided.'])
16 | elseif nargin == 0
17 | warning([mfilename,' requires input argument: myWorksheet. Insufficient arguments provided.'])
18 | else
19 | flagContinue = true;
20 | end
21 |
22 | if flagContinue
23 | allVPIDs = getVPIDs(myWorksheet);
24 | nVPs = length(allVPIDs);
25 | if length(unique(allVPIDs)) < nVPs
26 | warning(['Degenerate VP IDs in worksheet provided to ',mfilename,'.']);
27 | flagContinue = false;
28 | end
29 | end
30 |
31 | if flagContinue
32 | pointBaseVPIndices = nan(2, nVPs);
33 | baseVPVariantSets = cell(1,0);
34 | baseVPVariantSetIndices = nan(1,0);
35 | iseqarray = @(x,y) isequal(x,y);
36 | nUniqueVarSets = 0;
37 | for vpCounter = 1 : nVPs
38 | curVariants = myWorksheet.vpDef{vpCounter}.('variants');
39 | if nUniqueVarSets > 0
40 | baseVariantsCheck = cell2mat(arrayfun(@(i) iseqarray(baseVPVariantSets{i},curVariants), 1:nUniqueVarSets,'UniformOutput',false)');
41 | if sum(baseVariantsCheck) > 0
42 | baseVariantIndex = find(baseVariantsCheck);
43 | baseVariantIndex = baseVPVariantSetIndices(baseVariantIndex);
44 | pointBaseVPIndices(:, vpCounter) = [baseVariantIndex;vpCounter];
45 | else
46 | pointBaseVPIndices(:, vpCounter) = [vpCounter;vpCounter];
47 | nUniqueVarSets = nUniqueVarSets + 1;
48 | baseVPVariantSets = cat(2,baseVPVariantSets,{curVariants});
49 | baseVPVariantSetIndices = cat(2,baseVPVariantSetIndices,vpCounter);
50 | end
51 | else
52 | pointBaseVPIndices(:, vpCounter) = [vpCounter;vpCounter];
53 | baseVPVariantSets = cat(2,baseVPVariantSets,{curVariants});
54 | baseVPVariantSetIndices = cat(2,baseVPVariantSetIndices,vpCounter);
55 | nUniqueVarSets = nUniqueVarSets + 1;
56 | end
57 | end
58 | allVPCoefficients = getVPCoeffs(myWorksheet);
59 | keepVPIndices = nan(1,0);
60 | for baseVPCounter = 1 : nUniqueVarSets
61 | curOriginalIndices = find(pointBaseVPIndices(1,:) == baseVPCounter);
62 | curOriginalIndices = pointBaseVPIndices(2,curOriginalIndices);
63 | vpCoeffsToTest = allVPCoefficients(:,curOriginalIndices);
64 | vpCoeffsToTest = transpose(vpCoeffsToTest);
65 | [C,IA,IC] = unique(vpCoeffsToTest,'rows');
66 | keepVPIndices = [keepVPIndices, curOriginalIndices(IA)];
67 | end
68 | keepVPIndices = sort(keepVPIndices,'ascend');
69 | vpsToCopy = allVPIDs(keepVPIndices);
70 | myWorksheet = copyWorksheet(myWorksheet,vpsToCopy,true);
71 | else
72 | warning(['Could not complete ',mfilename,'. Returning original worksheet.'])
73 | copiedWorksheet = myWorksheet;
74 | end
75 |
76 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/createResponseType.m:
--------------------------------------------------------------------------------
1 | function myWorksheet = createResponseType(myWorksheet, responseTypeID)
2 | % Create a response type and add it to the worksheet
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet structure, required
5 | % responseTypeID: a simple text identifier for the response type
6 | %
7 | % RETURNS
8 | % myWorksheet: an updated worksheet with the empty response type.
9 | %
10 | newResponseType = struct();
11 | newResponseType.ID = responseTypeID;
12 | newResponseType.elements = cell(0,1);
13 |
14 | % Don't duplicate RT ID's
15 | existingResponseTypeIDs = getResponseTypeIDs(myWorksheet);
16 | if length(find(ismember(existingResponseTypeIDs, newResponseType.ID))) == 0
17 | [dummyVar, nExistingResponseTypes] = size(existingResponseTypeIDs);
18 | myWorksheet.responseTypes{nExistingResponseTypes + 1, 1} = newResponseType;
19 | else
20 | warning('Response type with specified ID already exists, not creating a new one')
21 | end
22 |
23 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/getResponseType.m:
--------------------------------------------------------------------------------
1 | function myResponseType = getResponseType(myWorksheet, responseTypeID)
2 | % Get response types from a model
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet, required
5 | % responseTypeID
6 | %
7 | % RETURNS
8 | % responseType: the requested response type
9 | % note this is a memory copy and not an actual object
10 |
11 | responseTypes = myWorksheet.responseTypes;
12 | responseTypeIDs = getResponseTypeIDs(myWorksheet);
13 | if sum(ismember(responseTypeIDs, responseTypeID)) > 1
14 | error('Requested response type ID is degenerate')
15 | elseif sum(ismember(responseTypeIDs, responseTypeID)) < 1
16 | error('Requested response type ID is not present')
17 | else
18 | myIndex = find(ismember(responseTypeIDs, responseTypeID));
19 | myResponseType = responseTypes{myIndex};
20 | end
21 |
22 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/getResponseTypeElementIDs.m:
--------------------------------------------------------------------------------
1 | function responseTypeElementIDs = getResponseTypeElementIDs(myWorksheet, responseTypeID)
2 | % Get Response Type Element IDs from a model
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet object, required
5 | % responseTypeID
6 | %
7 | % RETURNS
8 | % responseTypeElementIDs: an array of cells with the response type element
9 | % names for the specified response type
10 | continueFlag = true;
11 | responseTypeElementIDs = cell(1,0);
12 |
13 | if nargin > 2
14 | warning(['Too many input arguments to ',mfilename,'. Require: myWorksheet, responseTypeID.'])
15 | continueFlag = false;
16 | elseif nargin < 2
17 | warning(['Insufficient input arguments to ',mfilename,'. myWorksheet, responseTypeID.'])
18 | continueFlag = false;
19 | end
20 |
21 | if continueFlag
22 | responseTypeIDs = getResponseTypeIDs(myWorksheet);
23 | if sum(ismember(responseTypeIDs, responseTypeID)) < 1
24 | warning('Cannot identify specified response type ID, ',responseTypeID,', in the worksheet')
25 | elseif sum(ismember(responseTypeIDs, responseTypeID)) > 1
26 | warning('Specified response type ID, ',responseTypeID,', is degenerate in the worksheet')
27 | else
28 | responseTypeIndex = find(ismember(responseTypeIDs, responseTypeID));
29 | responseType = myWorksheet.responseTypes{responseTypeIndex};
30 | [nResponseTypeElements, dummyVar] = size(responseType.elements);
31 | responseTypeElementIDs = cell(1,nResponseTypeElements);
32 | for rteCounter = 1 : nResponseTypeElements
33 | currte = responseType.elements{rteCounter};
34 | responseTypeElementIDs{1,rteCounter} = currte.id;
35 | end
36 | end
37 | end
38 |
39 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/getResponseTypeIDs.m:
--------------------------------------------------------------------------------
1 | function responseTypeIDs = getResponseTypeIDs(myWorksheet)
2 | % Get response type IDs from a model
3 | % ARGUMENTS
4 | % worksheet: a worksheet object, required
5 | %
6 | % RETURNS
7 | % responseTypeIDs: an array of cells with the response type names
8 |
9 | responseTypes = myWorksheet.responseTypes;
10 | [nResponseTypes, dummyVar] = size(responseTypes);
11 | responseTypeIDs = cell(1, nResponseTypes);
12 | for theRTcounter = 1 : length(responseTypes)
13 | curRT = responseTypes{theRTcounter,1};
14 | responseTypeIDs{1,theRTcounter} = curRT.('ID');
15 | end
16 |
17 |
18 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/utility/evaluateAxisObjective.m:
--------------------------------------------------------------------------------
1 | function objectiveValue = evaluateAxisObjective(myCoefficient, targetValue)
2 | % Objective function type of evaluation for axis coefficients
3 | %
4 | % ARGUMENTS
5 | % myCoefficient: coefficient for the mechanistic axis
6 | % targetValue: target value for the axis coefficient
7 | %
8 | % RETURNS
9 | % objectiveValue:
10 | %
11 |
12 | % A small local gradient might be preferable, but then we run into
13 | % issues such as with how to best shape the well. So it's just
14 | % absolute value for now. The axes are already inherently scaled.
15 | objectiveValue = abs(myCoefficient-targetValue);
16 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/utility/evaluateBoundsObjectiveWtIntRangeCE.m:
--------------------------------------------------------------------------------
1 | function objectiveValue = evaluateBoundsObjectiveWtIntRangeCE(myTimeVals, myYVals, myBounds)
2 | % Objective function for bounds response type elements
3 | % WtIntRange - values being included in the objective are weighted by how
4 | % far they fall outside the allowed range and
5 | % also take into consideration the interval over which they
6 | % are out-of-bounds.
7 | % CE - the penalty for out-of-bounds terms is normalized by an error term
8 | % that is constant across time points
9 | %
10 | % ARGUMENTS
11 | % myTimeVals: a vector of time values from the simulation
12 | % myYVals: a vector of simulation output values
13 | %
14 | % RETURNS
15 | % objectiveValue: a single value
16 | %
17 |
18 | epsilon = 1E-4;
19 | if isequal(isinf(myBounds),[1, 1])
20 | % If our bounds are just infinite then there won't be a penalty,
21 | % this just passes through the VP without penalizing
22 | % them on this RTE
23 | objectiveValue = 0;
24 | else
25 | % We assume these have already been ordered
26 | lowerBound = myBounds(1);
27 | upperBound = myBounds(2);
28 | lowerBound2 = lowerBound;
29 | upperBound2 = upperBound;
30 | if isequal(isinf(myBounds),[1, 0])
31 | % If this is one-sided, we will normalize by the larger of epsilon
32 | % or magnitude of the non-infinite bound
33 | rangeNorm = min(myBounds(1), epsilon);
34 | lowerBound2 = 0;
35 | elseif isequal(isinf(myBounds),[0, 1])
36 | rangeNorm = min(myBounds(2), epsilon);
37 | upperBound2 = 0;
38 | else
39 | % Otherwise, we assume the upper/lower bounds are finite and
40 | % nonequal, which should be true based on the definition of the
41 | % RTE
42 | rangeNorm = max(myBounds) - min(myBounds);
43 | end
44 | % We also normalize by the time interval
45 | myTimeInterval = max(myTimeVals) - min(myTimeVals);
46 | myPenaltyValues = (myYVals > upperBound) .* (myYVals-upperBound2) + (myYVals < lowerBound) .* (lowerBound2-myYVals);
47 | if myTimeInterval > 0
48 | objectiveValue = trapz(myTimeVals,myPenaltyValues)/myTimeInterval/rangeNorm;
49 | else
50 | objectiveValue = myPenaltyValues/rangeNorm;
51 | end
52 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/utility/evaluatePointObjectiveCV.m:
--------------------------------------------------------------------------------
1 | function objectiveValue = evaluatePointObjectiveCV(uniqueSimTime, simY, expTime, expY)
2 | % Objective function for point response type elements
3 | % CV - A "coefficeint of variation" type of objective is implemented.
4 | % We evaluate the variation in the data about the simulation at each
5 | % time point, normalized by the magnitude of the mean of the data at
6 | % the current time point
7 | %
8 | %
9 | % ARGUMENTS
10 | % uniqueSimTime: filtered to match unique values in expTime
11 | % simY: interpolated simulation values at each uniqueSimTime
12 | % expTime: experiment times for samples
13 | % expY: experimental Y values
14 | %
15 | % RETURNS
16 | % objectiveValue: a single value
17 | %
18 | nExpPoints = length(expY);
19 | objectiveValue = 0;
20 | for timeCounter = 1 : length(uniqueSimTime)
21 | curTime = uniqueSimTime(timeCounter);
22 | curY = simY(timeCounter);
23 | expIndices = find(expTime == curTime);
24 | nCurPoints = length(expIndices);
25 | % Could try different objectives, but start with the sample size
26 | % weighted coefficient of variation
27 | curVal = sqrt((sum((expY(expIndices) - curY).^2))/nCurPoints) / abs(mean(expY(expIndices)));
28 | objectiveValue = objectiveValue + curVal*nCurPoints/nExpPoints;
29 | end
30 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/utility/evaluatePointObjectiveRange.m:
--------------------------------------------------------------------------------
1 | function objectiveValue = evaluatePointObjectiveRange(uniqueSimTime, simY, expTime, expY)
2 | % Objective function for point response type elements
3 | % Range - Whether the simulation falls within the experimental data range
4 | % at each data point is evaluated. The objective value is also
5 | % normalized by the number of time points for which we have data
6 | %
7 | %
8 | % ARGUMENTS
9 | % uniqueSimTime: filtered to match unique values in expTime
10 | % simY: interpolated simulation values at each uniqueSimTime
11 | % expTime: experiment times for samples
12 | % expY: experimental Y values
13 | %
14 | % RETURNS
15 | % objectiveValue: a single value
16 | %
17 | nExpPoints = length(expY);
18 | objectiveValue = 0;
19 | nTpoints = length(uniqueSimTime);
20 | for timeCounter = 1 : nTpoints
21 | curTime = uniqueSimTime(timeCounter);
22 | curY = simY(timeCounter);
23 | expIndices = find(expTime == curTime);
24 | nCurPoints = length(expIndices);
25 | maxval = max(expY(expIndices));
26 | minval = min(expY(expIndices));
27 | curVal = ((curY>maxval)+(curY 1
31 | if timeCounter < nTimePoints
32 | deltaT = (uniqueSimTime(timeCounter+1) - uniqueSimTime(timeCounter-1))/2;
33 | else
34 | deltaT = (uniqueSimTime(timeCounter) - uniqueSimTime(timeCounter-1))/2;
35 | end
36 | elseif nTimePoints > 1
37 | deltaT = (uniqueSimTime(timeCounter+1) - uniqueSimTime(timeCounter))/2;
38 | else
39 | deltaT = 1;
40 | totalTimeInterval = 1;
41 | end
42 | curTime = uniqueSimTime(timeCounter);
43 | curY = simY(timeCounter);
44 | expIndices = find(expTime == curTime);
45 | nCurPoints = length(expIndices);
46 | medVal = median(expY(expIndices));
47 | curVal = abs(curY-medVal);
48 | objectiveValue = objectiveValue + curVal*deltaT/totalTimeInterval;
49 | rangeNorm = rangeNorm + std(expY(expIndices));
50 | end
51 | rangeNorm = rangeNorm / nTimePoints;
52 | objectiveValue = objectiveValue / rangeNorm;
53 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/utility/evaluatePointObjectiveWtIntRangeCE.m:
--------------------------------------------------------------------------------
1 | function objectiveValue = evaluatePointObjectiveWtIntRangeCE(uniqueSimTime, simY, expTime, expY)
2 | % Objective function for point response type elements
3 | % WtIntRange - values being included in the objective are weighted by how
4 | % far they fall outside the observed range in the data and
5 | % also take into consideration the interval between the
6 | % data time points. So data from periods of time
7 | % that are more sparsely sampled can receive more weight
8 | % CE - The penalty for simulated values falling outside the observed range
9 | % is normalized by an error term that is constant across time points,
10 | % the average standard deviation in the data
11 | %
12 | %
13 | % ARGUMENTS
14 | % uniqueSimTime: filtered to match unique values in expTime
15 | % simY: interpolated simulation values at each uniqueSimTime
16 | % expTime: experiment times for samples
17 | % expY: experimental Y values
18 | %
19 | % RETURNS
20 | % objectiveValue: a single value
21 | %
22 | nExpPoints = length(expY);
23 | objectiveValue = 0;
24 | nTimePoints = length(uniqueSimTime);
25 | rangeNorm = 0;
26 | totalTimeInterval = max(uniqueSimTime) - min(uniqueSimTime);
27 | for timeCounter = 1 : nTimePoints
28 | % It would be computationally slightly more efficient to use
29 | % convolution, but then we would also have to write up the matrix to
30 | % Take the edges into consideration. Implement this this way for now.
31 | if timeCounter > 1
32 | if timeCounter < nTimePoints
33 | deltaT = (uniqueSimTime(timeCounter+1) - uniqueSimTime(timeCounter-1))/2;
34 | else
35 | deltaT = (uniqueSimTime(timeCounter) - uniqueSimTime(timeCounter-1))/2;
36 | end
37 | elseif nTimePoints > 1
38 | deltaT = (uniqueSimTime(timeCounter+1) - uniqueSimTime(timeCounter))/2;
39 | else
40 | deltaT = 1;
41 | totalTimeInterval = 1;
42 | end
43 | curTime = uniqueSimTime(timeCounter);
44 | curY = simY(timeCounter);
45 | expIndices = find(expTime == curTime);
46 | nCurPoints = length(expIndices);
47 | maxval = max(expY(expIndices));
48 | minval = min(expY(expIndices));
49 | % We could normalize out of bounds
50 | % simulation points by stdev, range, etc...
51 | % just to provide a gentle push to bring these in
52 | % spec
53 | rangeNorm = rangeNorm + std(expY(expIndices));
54 | flagTop = curY > maxval;
55 | flagBottom = curY < minval;
56 | % This was set to 0.99 prior to 12/26/15, then tried adjusting
57 | % to see if I could get more agreeable results from the optimizers.
58 | % inRangeWeight = 0.0 seems to give better results for many
59 | % scenarios
60 | inRangeWeight = 0.0;
61 | curVal = inRangeWeight*((flagTop)+(flagBottom))+(1-inRangeWeight)*(flagBottom*(minval-curY)+flagTop*(curY-maxval));
62 | objectiveValue = objectiveValue + curVal*deltaT/totalTimeInterval;
63 | end
64 | rangeNorm = rangeNorm / nTimePoints;
65 | objectiveValue = objectiveValue / rangeNorm;
66 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/utility/evaluatePointObjectiveWtRange.m:
--------------------------------------------------------------------------------
1 | function objectiveValue = evaluatePointObjectiveWtRange(uniqueSimTime, simY, expTime, expY)
2 | % Objective function for point response type elements
3 | % WtRange - values being included in the objective are weighted by how far
4 | % they fall outside the observed range in the data
5 | % Note "CE" is not specified. Objective values are also
6 | % normalized by an error term that is varied across time
7 | % points, the current standard deviation in the data
8 | %
9 | % ARGUMENTS
10 | % uniqueSimTime: filtered to match unique values in expTime
11 | % simY: interpolated simulation values at each uniqueSimTime
12 | % expTime: experiment times for samples
13 | % expY: experimental Y values
14 | %
15 | % RETURNS
16 | % objectiveValue: a single value
17 | %
18 | nExpPoints = length(expY);
19 | objectiveValue = 0;
20 | nTpoints = length(uniqueSimTime);
21 | for timeCounter = 1 : nTpoints
22 | curTime = uniqueSimTime(timeCounter);
23 | curY = simY(timeCounter);
24 | expIndices = find(expTime == curTime);
25 | nCurPoints = length(expIndices);
26 | maxval = max(expY(expIndices));
27 | minval = min(expY(expIndices));
28 | % We could normalize out of bounds
29 | % simulation points by stdev, range, etc...
30 | % just to provide a gentle push to bring these in
31 | % spec
32 | % rangeNorm = (maxval - minval);
33 | rangeNorm = std(expY(expIndices));
34 | flagTop = curY > maxval;
35 | flagBottom = curY < minval;
36 | % This was set to 0.99 prior to 12/26, then tried adjusting
37 | % to see if I could get more agreeable results from the optimizers.
38 | inRangeWeight = 0.0;
39 | curVal = inRangeWeight*((flagTop)+(flagBottom))+(1-inRangeWeight)*(flagBottom*(minval-curY)+flagTop*(curY-maxval))/rangeNorm;
40 | %curVal = sqrt((sum((expY(expIndices) - curY).^2))/nCurPoints) / abs(mean(expY(expIndices)));
41 | objectiveValue = objectiveValue + curVal*1/nTpoints;
42 | end
43 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/utility/evaluatePointObjectiveWtRangeCE.m:
--------------------------------------------------------------------------------
1 | function objectiveValue = evaluatePointObjectiveWtRangeCE(uniqueSimTime, simY, expTime, expY)
2 | % Objective function for point response type elements
3 | % WtRange - values being included in the objective are weighted by how far
4 | % they fall outside the observed range in the data
5 | % CE - Objective values are also normalized by an error term that is
6 | % constant across time points, the average standard deviation in the
7 | % data
8 | %
9 | % ARGUMENTS
10 | % uniqueSimTime: filtered to match unique values in expTime
11 | % simY: interpolated simulation values at each uniqueSimTime
12 | % expTime: experiment times for samples
13 | % expY: experimental Y values
14 | %
15 | % RETURNS
16 | % objectiveValue: a single value
17 | %
18 | nExpPoints = length(expY);
19 | objectiveValue = 0;
20 | nTpoints = length(uniqueSimTime);
21 | rangeNorm = 0;
22 | for timeCounter = 1 : nTpoints
23 | curTime = uniqueSimTime(timeCounter);
24 | curY = simY(timeCounter);
25 | expIndices = find(expTime == curTime);
26 | nCurPoints = length(expIndices);
27 | maxval = max(expY(expIndices));
28 | minval = min(expY(expIndices));
29 | % We could normalize out of bounds
30 | % simulation points by stdev, range, etc...
31 | % just to provide a gentle push to bring these in
32 | % spec
33 | % rangeNorm = (maxval - minval);
34 | rangeNorm = rangeNorm + std(expY(expIndices));
35 | flagTop = curY > maxval;
36 | flagBottom = curY < minval;
37 | % This was set to 0.99 prior to 12/26/15, then tried adjusting
38 | % to see if I could get more agreeable results from the optimizers.
39 | % inRangeWeight = 0.0 seems to give better results for many
40 | % scenarios
41 | inRangeWeight = 0.0;
42 | curVal = inRangeWeight*((flagTop)+(flagBottom))+(1-inRangeWeight)*(flagBottom*(minval-curY)+flagTop*(curY-maxval));
43 | %curVal = sqrt((sum((expY(expIndices) - curY).^2))/nCurPoints) / abs(mean(expY(expIndices)));
44 | objectiveValue = objectiveValue + curVal*1/nTpoints;
45 | end
46 | rangeNorm = rangeNorm / nTpoints;
47 | objectiveValue = objectiveValue / rangeNorm;
48 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/utility/evaluateResponseType.m:
--------------------------------------------------------------------------------
1 | function myRTresult = evaluateResponseType(myWorksheet, responseTypeID, verifyFlag)
2 | % This function evaluates a response type, returning a responseTypeResult
3 | % object.
4 | %
5 | % ARGUMENTS
6 | % myWorksheet: a worksheet
7 | % responseTypeID: ID of the response type to evaluate
8 | % verifyFlag: (optional) Whether to verify the responseType: boolean
9 | % (true/false, default is false). This is an optional
10 | % step as re-verification during iterative processes
11 | % like optimization should not be necessary and could slow
12 | % optimization.
13 | %
14 | % RETURNS
15 | % myRTresult: a response type result object
16 | %
17 |
18 | flagContinue = true;
19 | if nargin > 3
20 | warning(['Too many input arguments to ',mfilename,'. Require: myWorksheet, responseTypeID.'])
21 | flagContinue = false;
22 | elseif nargin > 2
23 | flagContinue = true;
24 | elseif nargin > 1
25 | verifyFlag = false;
26 | flagContinue = true;
27 | else
28 | warning(['Insufficient input arguments to ',mfilename,'. myWorksheet, responseTypeID.'])
29 | flagContinue = false;
30 | end
31 |
32 | if flagContinue
33 | if ~islogical(verifyFlag)
34 | warning(['Invalid verifyFlag specified for ',mfilename,', a boolean (true/false) should be specified.'])
35 | end
36 | end
37 |
38 | if flagContinue
39 | if verifyFlag
40 | flagContinue = verifyResponseType(myWorksheet, responseTypeID);
41 | if ~flagContinue
42 | warning(['Verification failed for ',responseTypeID,' in ',mfilename,'.'])
43 | end
44 | end
45 | end
46 |
47 | if flagContinue
48 | myRTresult = responseTypeResult({[responseTypeID,'_result'], responseTypeID});
49 | myRTresult = myRTresult.evaluateResponseTypeResults(myWorksheet);
50 | % myWorksheet,
51 | else
52 | warning(['Unable to run ',mfilename,'.'])
53 | myRTresult = responseTypeResult({});
54 | end
55 |
56 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/responseType/verifyResponseType.m:
--------------------------------------------------------------------------------
1 | function passCheck = verifyResponseType(myWorksheet, responseTypeID)
2 | % Perform a series of checks on a response type and the constituent
3 | % response type elements to make sure it is valid.
4 | %
5 | % ARGUMENTS
6 | % myWorksheet: a worksheet, required
7 | % responseTypeID
8 | %
9 | % RETURNS
10 | % passCheck: a boolean
11 | passCheck = true;
12 |
13 | if nargin > 2
14 | warning(['Too many input arguments to ',mfilename,'. Require: myWorksheet, responseTypeID.'])
15 | passCheck = false;
16 | elseif nargin < 2
17 | warning(['Insufficient input arguments to ',mfilename,'. myWorksheet, responseTypeID.'])
18 | passCheck = false;
19 | end
20 |
21 | if passCheck
22 | responseTypeIDs = getResponseTypeIDs(myWorksheet);
23 | if sum(ismember(responseTypeIDs, responseTypeID)) > 1
24 | warning(['Requested response type ID ',responseTypeID,' is degenerate. Check failed.'])
25 | passCheck = false;
26 | elseif sum(ismember(responseTypeIDs, responseTypeID)) < 1
27 | warning(['Requested response type ID ',responseTypeID,' is not present. Check failed.'])
28 | passCheck = false;
29 | end
30 | end
31 |
32 | if passCheck
33 | failedRTEs = cell(1,0);
34 | responseTypes = myWorksheet.responseTypes;
35 | myIndex = find(ismember(responseTypeIDs, responseTypeID));
36 | myResponseType = responseTypes{myIndex};
37 | myResponseTypeElementIDs = getResponseTypeElementIDs(myWorksheet, responseTypeID);
38 | nResponseTypeElementIDs = length(myResponseTypeElementIDs);
39 | for rteCounter = 1 : length(myResponseTypeElementIDs)
40 | myRTE = myResponseType.elements{rteCounter};
41 | curPassCheck = myRTE.verify(myWorksheet);
42 | if ~curPassCheck
43 | passCheck = false;
44 | failedRTEs = [failedRTEs, myRTE.id];
45 | end
46 | end
47 | if ~passCheck
48 | warning(['Verification failed for RTEs: ',strjoin(failedRTEs,', '),'.'])
49 | end
50 | end
51 |
52 |
53 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/results/convertSimData.m:
--------------------------------------------------------------------------------
1 | function simStruct = convertSimData(simData)
2 | % Take a simResult and convert it to a format just with 2 fields:
3 | % Name and Data. Originally, I was going to use tables but ran into
4 | % maximum name length issue.
5 | %
6 | % ARGUMENTS
7 | % simData
8 | %
9 | % RETURNS
10 | % simStruct
11 | %
12 | colnames = ['time';simData.DataNames];
13 | datavalues = [simData.Time,simData.Data];
14 | simStruct.Data = datavalues;
15 | simStruct.Names = transpose(colnames);
16 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/utility/calculateIndividualElementValues.m:
--------------------------------------------------------------------------------
1 | function elementValues = calculateIndividualElementValues(axisVPCoeffs,curBounds,myScale)
2 | % This function calculates values for individual elements
3 | % (parameter/initial species/compartment) values within an axis.
4 | % It is vectorized to work across all VPs in a worksheet to run
5 | % large worksheets more quickly.
6 | % Note there is no input argument proofing, this is essentially a
7 | % utility function we anticipate will be called often.
8 | %
9 | % ARGUMENTS
10 | % axisVPCoeffs: a 1xnVP vector of axis coefficients
11 | % curBounds: a 1x2 vector of lower, upper bound for the current axis
12 | % scale: axis string to indicate type of scale. Currently
13 | % anticipated are 'linear' and 'log'. Will default to
14 | % log calculation if specification is not recognized.
15 | %
16 | % RETURNS
17 | % elementValues: an 1xnVP vector of each element
18 | % (parameter/initial species/compartment) value
19 | %
20 | if strcmp(myScale,'linear')
21 | elementValues = axisVPCoeffs*(curBounds(2) - curBounds(1)) + curBounds(1);
22 | else
23 | elementValues = 10.^(axisVPCoeffs*(curBounds(2) - curBounds(1)) + curBounds(1));
24 | end
25 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/utility/checkNWorkers.m:
--------------------------------------------------------------------------------
1 | function mySimulateOptions = checkNWorkers(mySimulateOptions)
2 | % This is a "utility function" that should not be called directly.
3 | % This is used to check the number of workers specified
4 | % and if not, check how many are available.
5 | %
6 | % ARGUMENTS
7 | % mySimulateOptions: a simulateOptions object
8 | %
9 | % RETURNS
10 | % mySimulateOptions: a simulateOptions object with the
11 | % number of workers checked
12 | %
13 |
14 | mySettings = parallel.Settings;
15 | clusterCheck = parcluster(mySimulateOptions.clusterID);
16 | if isnan(mySimulateOptions.nWorkers)
17 | if isnumeric(mySettings.Pool.PreferredNumWorkers)
18 | % First try getting the value from parallel.settings, but cap in
19 | % case a silly value was entered.
20 | if isa(clusterCheck, 'parallel.cluster.Local')
21 | mySimulateOptions.nWorkers = min(clusterCheck.NumWorkers, ...
22 | mySettings.Pool.PreferredNumWorkers);
23 | else
24 | mySimulateOptions.nWorkers = min(clusterCheck.MaxNumWorkers, ...
25 | mySettings.Pool.PreferredNumWorkers);
26 | end
27 | else
28 | mySimulateOptions.nWorkers = clusterCheck.NumWorkers;
29 | end
30 | % The local scheduler tends to be listed this way, but this is not
31 | % guaranteed. This code is no longer needed but is
32 | % kept for reference.
33 | % mySchedulerComponent = [mySimulateOptions.clusterID,'SchedulerComponent'];
34 |
35 | else
36 | % Otherwise, check that the number of workers specified
37 | % doesn't exceed any pre-set maximums.
38 | if isnumeric(mySettings.Pool.PreferredNumWorkers)
39 | % First try getting the value from parallel.settings, but cap in
40 | % case a silly value was entered.
41 | if isa(clusterCheck, 'parallel.cluster.Local')
42 | mySimulateOptions.nWorkers = min(mySimulateOptions.nWorkers, min(clusterCheck.NumWorkers, mySettings.Pool.PreferredNumWorkers));
43 | else
44 | mySimulateOptions.nWorkers = min(mySimulateOptions.nWorkers, min(clusterCheck.MaxNumWorkers, mySettings.Pool.PreferredNumWorkers));
45 | end
46 | else
47 | if isa(clusterCheck, 'parallel.cluster.Local')
48 | mySimulateOptions.nWorkers = min(mySimulateOptions.nWorkers, clusterCheck.NumWorkers);
49 | else
50 | mySimulateOptions.nWorkers = min(mySimulateOptions.nWorkers, clusterCheck.MaxNumWorkers);
51 | end
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/utility/getOptimizationAxes.m:
--------------------------------------------------------------------------------
1 | function [indicesForVaried, boundsForVaried, axisScale] = getOptimizationAxes(myWorksheet, mySimulateOptions)
2 |
3 | optimizeAxisIDs = mySimulateOptions.optimizeAxisIDs;
4 | allInterventionIDs = getInterventionIDs(myWorksheet);
5 | nInterventions = length(allInterventionIDs);
6 | allAxisIDs = getAxisDefIDs(myWorksheet);
7 | nOptimizeAxes = length(optimizeAxisIDs);
8 | % indicesForVaried will be N axes X M interventions
9 | % as interventions may
10 | % may overwrite some of the parameters included in the axes, which
11 | % we will need to account for in the optimization process
12 | indicesForVaried = cell(nOptimizeAxes, nInterventions);
13 | % We make an additional cell for bounds
14 | boundsForVaried = cell(nOptimizeAxes, nInterventions);
15 | axisScale = cell(nOptimizeAxes, 1);
16 | for axisCounter = 1 : nOptimizeAxes
17 | myAxisDefID = optimizeAxisIDs{axisCounter};
18 | curAxisDef = getAxisDef(myWorksheet, myAxisDefID);
19 | axisIndices = nan(1,0);
20 | axisBounds = cell(1,0);
21 | axisScale{axisCounter} = curAxisDef.scale;
22 | for eCounter = 1 : length(curAxisDef.elementNames)
23 | curElementName = curAxisDef.elementNames{eCounter};
24 | curElementType = curAxisDef.elementTypes{eCounter};
25 | axisBounds = [axisBounds,curAxisDef.bounds{eCounter}];
26 | theIndices = find(ismember(myWorksheet.compiled.elements(:,1), curElementName) & ismember(myWorksheet.compiled.elements(:,2), curElementType));
27 | if length(theIndices) > 0
28 | axisIndices = cat(2,axisIndices,theIndices);
29 | % It should not be possible not to find the axis index
30 | end
31 | end
32 | for interventionCounter = 1 : nInterventions
33 | curIntervention = myWorksheet.interventions{interventionCounter};
34 | [nrows, ncols] = size(curIntervention);
35 | interventionVariants = extractInterventionTypeElements(curIntervention, 'VARIANT');
36 | interventionElementValues = flattenVariantstoElements(myWorksheet, interventionVariants);
37 | checkedAxisIndices = nan(1,0);
38 | checkedAxisBounds = cell(1,0);
39 | for eCounter = 1 : length(axisIndices)
40 | indexToCheck = axisIndices(eCounter);
41 | nameToCheck = myWorksheet.compiled.elements{indexToCheck, 1};
42 | typeToCheck = myWorksheet.compiled.elements{indexToCheck, 2};
43 | nOverwriteIndices = sum(ismember(interventionElementValues(:,1),nameToCheck) & ismember(interventionElementValues(:,2),typeToCheck));
44 | if nOverwriteIndices < 1
45 | checkedAxisIndices = cat(2, checkedAxisIndices, indexToCheck);
46 | checkedAxisBounds = [checkedAxisBounds, axisBounds{eCounter}];
47 | % else
48 | % If we don't pass the check, the intervention will
49 | % overwrite the axis element, so we don't add this
50 | % element as a variable
51 | % 1;
52 | end
53 | end
54 | indicesForVaried{axisCounter,interventionCounter} = checkedAxisIndices;
55 | boundsForVaried{axisCounter,interventionCounter} = checkedAxisBounds;
56 | end
57 | end
58 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/utility/getUniqueBaseVPVariantSets.m:
--------------------------------------------------------------------------------
1 | function [pointBaseVPIndices, baseVPVariantSets] = getUniqueBaseVPVariantSets(myWorksheet, flagKeepVP)
2 | % This utility function is helpful for collapsing down a set of VP
3 | % variant sets which may be repeated in the VP definitions.
4 | %
5 | % NOTE THIS IS A UTILITY FUNCTION AND NOT INTENDED TO BE CALLED DIRECTLY
6 | % BY TOOLBOX USERS
7 | %
8 | % ARGUMENTS
9 | % myWorksheet: a worksheet
10 | % flagKeepVP: a 1xnVP matrix of 1/0 indicating whether to keep a VP.
11 | %
12 | % RETURNS
13 | % pointBaseVPIndices: a 2xnVP matrix pointing to the each first unique
14 | % base VP and subsequent VPs with identical variants
15 | % sets
16 | % row 1: base VP index
17 | % row 2: VP index
18 | % baseVPVariantSets: base VP variant sets; that is, variant sets for
19 | % those unique VP indices on row 1
20 | %
21 | %
22 |
23 | vpIDs = getVPIDs(myWorksheet);
24 | nVPs = length(vpIDs);
25 |
26 | pointBaseVPIndices = nan(2, nVPs);
27 | baseVPVariantSets = cell(1,0);
28 | baseVPVariantSetIndices = nan(1,0);
29 | iseqarray = @(x,y) isequal(x,y);
30 | nUniqueVarSets = 0;
31 | for vpCounter = 1 : nVPs
32 | % If we are just running a subset of a large worksheet we
33 | % don't want to spend time here.
34 | if flagKeepVP(vpCounter)
35 | curVariants = myWorksheet.vpDef{vpCounter}.('variants');
36 | if nUniqueVarSets > 0
37 | baseVariantsCheck = cell2mat(arrayfun(@(i) iseqarray(baseVPVariantSets{i},curVariants), 1:nUniqueVarSets,'UniformOutput',false)');
38 | if sum(baseVariantsCheck) > 0
39 | baseVariantIndex = find(baseVariantsCheck);
40 | baseVariantIndex = baseVPVariantSetIndices(baseVariantIndex);
41 | pointBaseVPIndices(:, vpCounter) = [baseVariantIndex;vpCounter];
42 | else
43 | pointBaseVPIndices(:, vpCounter) = [vpCounter;vpCounter];
44 | nUniqueVarSets = nUniqueVarSets + 1;
45 | baseVPVariantSets = cat(2,baseVPVariantSets,{curVariants});
46 | baseVPVariantSetIndices = cat(2,baseVPVariantSetIndices,vpCounter);
47 | end
48 | else
49 | pointBaseVPIndices(:, vpCounter) = [vpCounter;vpCounter];
50 | baseVPVariantSets = cat(2,baseVPVariantSets,{curVariants});
51 | baseVPVariantSetIndices = cat(2,baseVPVariantSetIndices,vpCounter);
52 | nUniqueVarSets = nUniqueVarSets + 1;
53 | end
54 | end
55 | end
56 | % We could still have nan's, for example if we didn't want to keep/simulate
57 | % a VP.
58 | keepCols = find((~isnan(pointBaseVPIndices(1,:)) & ~isnan(pointBaseVPIndices(2,:))));
59 | pointBaseVPIndices = pointBaseVPIndices(:,keepCols);
60 |
61 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/utility/particleSwarmCohortWrapper.m:
--------------------------------------------------------------------------------
1 | function [x,fval,exitFlag,swarm] = particleSwarmCohortWrapper(fun, nvars, lb, ub, userOptions)
2 | % This is a wrapper to call particle swarm and keep the last returned
3 | % swarm, which isn't available in the userOptions.
4 |
5 | swarm = [];
6 | userOptions.OutputFcn = @outputFunction;
7 | [x,fval,exitFlag,output] = particleswarm(fun, nvars, lb, ub, userOptions);
8 |
9 | function stop = outputFunction(optimValues, state)
10 | stop = false;
11 | swarm = optimValues.swarm;
12 | end
13 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/utility/runSingleSimulation.m:
--------------------------------------------------------------------------------
1 | function simResult = runSingleSimulation(exportedModel, currentModelValues, curDoses, mySaveElementResultIDs)
2 | % This is a "utility function" that should be called directly.
3 | % This is called following preprocessing to run a single simulation
4 | %
5 | % ARGUMENTS
6 | % exportedModel: an exported (accelerated) simbiology model object
7 | % currentModelValues: a nModelElements matrix of values
8 | % curDoses: a dose array
9 | % mySaveElementResultIDs a cell array of variable names
10 | %
11 | %
12 | % RETURNS
13 | % simResult: a simulation result structure
14 | %
15 |
16 | try
17 | simData = simulate(exportedModel, currentModelValues, curDoses);
18 | simData = convertSimData(simData);
19 | % Reformat results into the desired data format
20 | if ~isempty(mySaveElementResultIDs)
21 | [~, keepIndices] = ismember(['time',mySaveElementResultIDs], simData.Names);
22 | simData.Names = simData.Names(keepIndices);
23 | simData.Data = simData.Data(:,keepIndices);
24 | end
25 | flagSimData = verifySimData(simData, exportedModel.SimulationOptions.StopTime);
26 | % If the simulation doesn't complete the entire
27 | % specified length of simulated time, then we need to
28 | % flag this. For now, we only keep results
29 | % for simulations that can complete.
30 | if ~flagSimData
31 | simResult = [];
32 | else
33 | simResult = simData;
34 | end
35 | catch
36 | % If the simulation fails, we need to move on
37 | simResult = [];
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/utility/verifyFullResults.m:
--------------------------------------------------------------------------------
1 | function fullResultsFlag = verifyFullResults(myWorksheet)
2 | % Check whether a worksheet has a fully populated results field.
3 | %
4 | % ARGUMENTS
5 | % myWorksheet: a worksheet
6 | %
7 | % RETURNS
8 | % fullResultsFlag: a (true/false) value indicating whether the results
9 | % are fully populated.
10 | %
11 |
12 | fullResultsFlag = false;
13 | vpIDs = getVPIDs(myWorksheet);
14 | interventionDefinitions = myWorksheet.interventions;
15 | nVPs = length(vpIDs);
16 | nInterventions = length(interventionDefinitions);
17 | %[nInterventionResults, nVPResults] = size(myWorksheet.results);
18 | myResultClasses = cellfun(@class,myWorksheet.results, 'UniformOutput', false);
19 | flagVPcheck = sum(strcmp(myResultClasses,'struct'),1);
20 | flagVPcheck = (flagVPcheck == nInterventions);
21 | if sum(flagVPcheck) == nVPs
22 | fullResultsFlag = true;
23 | end
24 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/utility/verifySimData.m:
--------------------------------------------------------------------------------
1 | function flagPass = verifySimData(simData, stopTime)
2 | % A simple function to verify simData, indicates complete simulation
3 | % results are available.
4 |
5 | timeIndex = find(ismember(simData.Names,'time'));
6 |
7 | if max(simData.Data(:,timeIndex)) < stopTime
8 | flagPass = false;
9 | elseif length(simData.Data(:,timeIndex)) < 1
10 | flagPass = false;
11 | else
12 | flagPass = true;
13 | end
14 |
15 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/variant/getVariantNames.m:
--------------------------------------------------------------------------------
1 | function variantNames = getVariantNames(worksheet, variantType)
2 | % Get variant names from a model, subject to the constraint
3 | % to select variants that start with "prefix"
4 | % ARGUMENTS
5 | % worksheet: a worksheet object, required
6 | % variantType: optional string. If provided, variants with that prefix
7 | % will be returned. Otherwise, if the prefix does not
8 | % match available prefixes or if prefix is not provided
9 | % all model variants will be matched
10 | %
11 | % RETURNS
12 | % variantNames: an array of cells with the variant names; aka typeValueSets
13 |
14 | variant_delimiter = worksheet.variantProps.delimiter;
15 | %
16 | if nargin < 2
17 | variantType = '';
18 | end
19 |
20 | variantNames = cell(0,1);
21 |
22 | variants = worksheet.model.variants;
23 | [n_variants, dummy] = size(variants);
24 | allvariantNames = cell(n_variants,1);
25 |
26 | variantTypes = worksheet.variantProps.variantTypes;
27 |
28 | for i = 1 : n_variants
29 | current_variant_name = variants(i).Name;
30 | allvariantNames{i} = current_variant_name;
31 | end
32 |
33 | if length(variantType) > 0;
34 | if length(find(ismember(variantTypes, variantType))) > 0
35 | the_prefixes = cell(n_variants, 1);
36 | for i = 1 : n_variants
37 | split_values = strsplit(allvariantNames{i}, variant_delimiter);
38 | the_prefixes(i) = split_values(1);
39 | end
40 | the_indices = find(ismember(the_prefixes, variantType));
41 | variantNames = allvariantNames(the_indices);
42 | else
43 | variantNames = allvariantNames;
44 | end
45 |
46 | else
47 | variantNames = allvariantNames;
48 | end
49 |
50 |
51 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/variant/getVariantTypeElements.m:
--------------------------------------------------------------------------------
1 | function variantTypeElements = getVariantTypeElements(myWorksheet, variantTypeName)
2 | % This function is developed to look up a variant type and get all of the
3 | % associated parameters, species, compartments, generally referred to as
4 | % elements. We also check that the included
5 | % elements are consistent across the value sets of a variant type.
6 | %
7 | % ARGUMENTS
8 | % myWorksheet: a worksheet
9 | % variantTypeName: a variant type
10 | %
11 | % RETURNS
12 | % variantTypeElements: a cell array of strings with the components of the
13 | % variant type.
14 | %
15 |
16 |
17 | flagContinue = false;
18 |
19 | % First check input arguments
20 | if nargin > 2
21 | warning(['Too many input arguments to',mfilename,'. Require: myWorksheet, variantTypeName.'])
22 | elseif nargin > 1
23 | flagContinue = true;
24 | else
25 | warning(['Insufficient input arguments to',mfilename,'. Require: myWorksheet, variantTypeName.'])
26 | end
27 |
28 | variantTypeElements = cell(0,2);
29 |
30 | if flagContinue
31 | variantDelimiter = myWorksheet.variantProps.delimiter;
32 | variantNames = myWorksheet.variantProps.typeValueSets;
33 | variantTypes = cell(length(variantNames),1);
34 | for variantCounter = 1 : length(variantNames)
35 | % Scan through all of the model variants
36 | curVariantName = variantNames{variantCounter};
37 | curVariantSplit = strsplit(curVariantName, variantDelimiter);
38 | curVariantType = curVariantSplit{1};
39 | variantTypes{variantCounter} = curVariantType;
40 | % Check is the variant is of the right type
41 | if strcmp(curVariantType, variantTypeName)
42 | curVariantCell = myWorksheet.model.variants(variantCounter).('Content');
43 | curVariantElements = cell(length(curVariantCell),2);
44 | % Scan through all of the current variant's parameters
45 | for curVariantElementNumber = 1 : length(curVariantCell)
46 | curVariantRow = curVariantCell{curVariantElementNumber};
47 | % Get the name
48 | curVariantElements{curVariantElementNumber,1} = curVariantRow{2};
49 | % Get the type: parameter, species, compartment
50 | curVariantElements{curVariantElementNumber,1} = curVariantRow{2};
51 | curVariantElements{curVariantElementNumber,2} = curVariantRow{1};
52 | end
53 | [nrow, ncol] = size(variantTypeElements);
54 | if nrow == 0
55 | variantTypeElements = curVariantElements;
56 | % If the names match we are OK
57 | elseif length(intersect(variantTypeElements(:,1), curVariantElements(:,1))) ~= length(variantTypeElements(:,1))
58 | warning(['Inconsistency in variant elements noted for model variant: ',curVariantName,'.']);
59 | variantTypeElements = union(variantTypeElements, curVariantElements);
60 | end
61 | end
62 | end
63 | else
64 | warning([mfilename,' could not complete. Returning empty cell array.'])
65 | end
66 | end
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/variant/getVariantTypes.m:
--------------------------------------------------------------------------------
1 | function variantTypes = getVariantTypes(myWorksheet)
2 | % Scan a worksheet and return all of the variant types.
3 | % ARGUMENTS
4 | % myWorksheet
5 | %
6 | % RETURNS
7 | % variantTypes
8 | variant_delimiter = myWorksheet.variantProps.delimiter;
9 |
10 | variants = myWorksheet.model.variants;
11 | [n_variants, dummy] = size(variants);
12 | variant_names = cell(n_variants,1);
13 | variantTypes = cell(0,1);
14 | for i = 1 : n_variants
15 | current_variant_name = variants(i).Name;
16 | variant_names{i} = current_variant_name;
17 | variant_name_split = strsplit(current_variant_name, variant_delimiter);
18 | current_variant_prefix = variant_name_split{1};
19 | if length(find(ismember(variantTypes,current_variant_prefix))) < 1
20 | n_variant_types = length(variantTypes);
21 | variantTypes{n_variant_types + 1,1} = current_variant_prefix;
22 | end
23 | end
24 |
25 |
26 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/vp/getVP.m:
--------------------------------------------------------------------------------
1 | function myVP = getVP(myWorksheet, vpID)
2 | % Get VP from a model
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet, required
5 | % vpID: String identifier for the VP
6 | %
7 | % RETURNS
8 | % myVP: the indicated VP
9 |
10 | vpIDs = getVPIDs(myWorksheet);
11 | if sum(ismember(vpIDs, vpID)) < 1
12 | error('Specified VP ID not in model')
13 | elseif sum(ismember(vpIDs, vpID)) > 1
14 | error('Specified VP ID degenerate in model')
15 | else
16 | vpIndex = find(ismember(vpIDs, vpID));
17 | myVP = myWorksheet.vpDef{vpIndex};
18 | end
--------------------------------------------------------------------------------
/QSPToolbox/worksheet/vp/getVPIDs.m:
--------------------------------------------------------------------------------
1 | function vpIDs = getVPIDs(myWorksheet)
2 | % Get VP IDs from a model
3 | % ARGUMENTS
4 | % myWorksheet: a worksheet
5 | %
6 | % RETURNS
7 | % vpIDs: an array of cells with the vp names
8 |
9 | VPs = myWorksheet.vpDef;
10 | vpIDs = cell(1, length(VPs));
11 | for theVPcounter = 1 : length(VPs)
12 | curVP = VPs{theVPcounter};
13 | vpIDs{theVPcounter} = curVP.('ID');
14 | end
15 |
16 |
17 | end
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | QSP Toolbox
2 | =============
3 | Quantitative Systems Pharmacology Toolbox
4 | -------------
5 |
6 | This toolbox was developed to support Quantitative Systems Pharmacology work.
7 |
8 | ## Current system requirements:
9 | -MATLAB 2022a (other releases not fully supported, good compatibility back to 2018b)
10 | Required MATLAB toolboxes:
11 | -SimBiology
12 | -Optimization
13 | -Global Optimization
14 | -Parallel Computing
15 | -Statistics and Machine Learning
16 |
17 | ## Tutorials and documentation:
18 | -There are several tutorials located in the examples folder.
19 | -Currently, functions are primarily documented in-line in MATLAB (i.e. type "help myFunction" following initialization).
20 | -The below AAPs J publication is a helpful reference to get started. Note the repository code is updated since the paper.
21 |
22 | ## How to cite:
23 | If this is useful for you, and you publish resulting work, please cite your usage of this tool.
24 | The most relevant paper is currently:
25 |
26 | Cheng Y, et al. (2017) QSP Toolbox: Computational Implementation of Integrated
27 | Workflow Components for Deploying Multi-Scale Mechanistic Models. AAPS J 19(4), 1002-1016.
28 |
29 | ## How to contribute:
30 | -We are evaluating allowing others to contribute to the development on a case-by-case basis.
31 | -We will likely require a Contributor License Agreement with the intent all resulting work will be equally available for others.
32 | -Please contact us to contribute, or with related inquiries. The current contact is brian(dot)schmidt{at}bms{dot}com.
33 |
34 | ## Other notes for our development efforts:
35 | -The current fully public version corresponds to rev1368 from the in-house development repository.
36 |
37 | ## To install:
38 | -Once you download, add the root directory (QSPToolbox folder) to your MATLAB path.
39 | -Type "initQSPToolbox" in MATLAB to initialize the QSP Toolbox for use.
40 |
--------------------------------------------------------------------------------