|
| 1 | +diff --git a/run_mutsig_persample.m b/run_mutsig_persample.m |
| 2 | +new file mode 100644 |
| 3 | +index 0000000..49b1d48 |
| 4 | +--- /dev/null |
| 5 | ++++ b/run_mutsig_persample.m |
| 6 | +@@ -0,0 +1,26 @@ |
| 7 | ++function run_mutsig_persample(maf, outdir) |
| 8 | ++% Run the (DIALECT-patched) MutSig2CV v3.11 source on a MAF, dumping the |
| 9 | ++% per-(gene,patient,effect) expected background to <outdir>/persample_bmr.mat. |
| 10 | ++% Uses the reference files vendored with the compiled bundle. |
| 11 | ++% |
| 12 | ++% matlab -batch "run_mutsig_persample('/abs/cohort.maf','/abs/outdir')" |
| 13 | ++ |
| 14 | ++here = fileparts(mfilename('fullpath')); % .../external/MutSig2CV_src |
| 15 | ++repo = fileparts(fileparts(here)); % repo root |
| 16 | ++refdir = fullfile(repo, 'external', 'MutSig2CV', 'mutsig2cv', 'reference'); |
| 17 | ++ |
| 18 | ++addpath(genpath(fullfile(here, 'src'))); |
| 19 | ++javaaddpath(fullfile(refdir, 'FixedWidthBinary.jar')); |
| 20 | ++if exist('OCTAVE_VERSION', 'builtin') |
| 21 | ++ pkg load statistics % binofit, binopdf, hygepdf, ... used throughout MutSig |
| 22 | ++end |
| 23 | ++ |
| 24 | ++% the source's reference paths default to 'reference/...', resolved from the |
| 25 | ++% compiled bundle dir, so run with that as the working directory. |
| 26 | ++oldcd = cd(fullfile(repo, 'external', 'MutSig2CV', 'mutsig2cv')); |
| 27 | ++cleanupObj = onCleanup(@() cd(oldcd)); %#ok<NASGU> |
| 28 | ++ |
| 29 | ++if ~exist(outdir, 'dir'), mkdir(outdir); end |
| 30 | ++MutSig2CV(maf, outdir); % 2-arg: leave P unset so the wrapper uses its defaults |
| 31 | ++fprintf('DIALECT: wrote %s/persample_bmr.mat\n', outdir); |
| 32 | ++end |
| 33 | +diff --git a/src/MutSig_2CV_v3_11_core.m b/src/MutSig_2CV_v3_11_core.m |
| 34 | +index b4b4433..8fc8c94 100755 |
| 35 | +--- a/src/MutSig_2CV_v3_11_core.m |
| 36 | ++++ b/src/MutSig_2CV_v3_11_core.m |
| 37 | +@@ -23,8 +23,8 @@ demand_file(covariates_file); |
| 38 | + demand_file(conservation_fwb_file); |
| 39 | + demand_file(FixedWidthBinary_jar_file); |
| 40 | + |
| 41 | +-% add jar to java classpath |
| 42 | +-javaclasspath(FixedWidthBinary_jar_file); |
| 43 | ++% add jar to java classpath (javaaddpath works in both MATLAB and Octave) |
| 44 | ++javaaddpath(FixedWidthBinary_jar_file); |
| 45 | + |
| 46 | + % ensure output directory is ok |
| 47 | + ede(output_dir); |
| 48 | +@@ -60,7 +60,7 @@ if P.permutations_min_effect_size<1, error('permutations_min_effect_size must be |
| 49 | + P = impose_default_value(P,'max_coverage_bins',10); |
| 50 | + P = impose_default_value(P,'clustering_metric',204); |
| 51 | + P = impose_default_value(P,'randseed',6789); |
| 52 | +-P = impose_default_value(P,'skip_permutations',false); |
| 53 | ++P = impose_default_value(P,'skip_permutations',true); % [DIALECT] persample_lambda is computed pre-permutation; skip for speed |
| 54 | + P = impose_default_value(P,'maxperm',1e5); %to speedup initial screens; need to reset to 1e6 later. |
| 55 | + P = impose_default_value(P,'theta',1); |
| 56 | + P = impose_default_value(P,'keyboard_before_begin',false); |
| 57 | +@@ -81,13 +81,13 @@ M=[]; |
| 58 | + |
| 59 | + % open FWB tracks |
| 60 | + M.FWB = []; |
| 61 | +-M.FWB.conservation = org.broadinstitute.cga.tools.seq.FixedWidthBinary(conservation_fwb_file); |
| 62 | ++M.FWB.conservation = javaObject('org.broadinstitute.cga.tools.seq.FixedWidthBinary', conservation_fwb_file); |
| 63 | + M.FWB.conservation.setNullVal(200); |
| 64 | +-M.FWB.context_and_effect = org.broadinstitute.cga.tools.seq.FixedWidthBinary(context_and_effect_fwb_file); |
| 65 | ++M.FWB.context_and_effect = javaObject('org.broadinstitute.cga.tools.seq.FixedWidthBinary', context_and_effect_fwb_file); |
| 66 | + M.context_and_effect = load_struct(context_and_effect_categs_file); |
| 67 | + M.context_and_effect.context65 = map_categories_to_65(context_and_effect_categs_file); |
| 68 | + if ~strcmpi(basewise_coverage_fwb_file,'IMPUTE_FULL_COVERAGE') |
| 69 | +- M.FWB.basewise_coverage = org.broadinstitute.cga.tools.seq.FixedWidthBinary(basewise_coverage_fwb_file); |
| 70 | ++ M.FWB.basewise_coverage = javaObject('org.broadinstitute.cga.tools.seq.FixedWidthBinary', basewise_coverage_fwb_file); |
| 71 | + M.FWB.basewise_coverage.setNullVal(0); |
| 72 | + end |
| 73 | + |
| 74 | +@@ -195,7 +195,7 @@ end |
| 75 | + |
| 76 | + % remove duplicate patients |
| 77 | + fprintf('Scanning for duplicate patients...\n'); |
| 78 | +-X = new_find_duplicate_samples(M.mut); |
| 79 | ++X = []; X.drop = {}; % [DIALECT/Octave] skip MEX count_overlaps_fast2 (cohorts are pre-deduplicated) |
| 80 | + if ~isempty(X.drop) |
| 81 | + fprintf('Removing the following %d duplicate patients:\n',length(X.drop)); |
| 82 | + disp(X.drop); |
| 83 | +@@ -606,6 +606,9 @@ fprintf('now eta # gene nmut nperm CV CL |
| 84 | + |
| 85 | + if P.keyboard_before_begin, keyboard; end |
| 86 | + |
| 87 | ++% [DIALECT] per-(gene,patient,effect) expected background count (d=1 missense, d=2 nonsense) |
| 88 | ++persample_lambda = zeros(M.ng, M.np, 2, 'single'); |
| 89 | ++ |
| 90 | + for g=1:M.ng |
| 91 | + gene_status_reported=false; |
| 92 | + pCVmax = 1; pclust=1; pcons=1; nperm=0; nm=0; |
| 93 | +@@ -813,6 +816,10 @@ for g=1:M.ng |
| 94 | + p = my_hygepdf(0,N_total,n_total,N_signal); % (2D vectorization was being screwed up by all the error checking in hygepdf.m) |
| 95 | + P0(:,d) = prod(p,2); |
| 96 | + has_mutation(:,d) = sum(n_signal,2)>0; |
| 97 | ++ if d<=2 % [DIALECT] expected bg count = sum_c hypergeometric mean (sample- AND context-specific) |
| 98 | ++ Nt_safe = N_total; Nt_safe(Nt_safe<=0) = inf; |
| 99 | ++ persample_lambda(g,:,d) = single(sum(n_total .* N_signal ./ Nt_safe, 2))'; |
| 100 | ++ end |
| 101 | + end |
| 102 | + P0(isnan(P0))=1; |
| 103 | + P0(P0>1)=1; |
| 104 | +@@ -1107,6 +1114,24 @@ fprintf('%d genes with q<=0.1\n',sum(M.gene.q<=0.1)); |
| 105 | + |
| 106 | + fprintf('Saving results... '); |
| 107 | + |
| 108 | ++% [DIALECT] per-(gene,patient,effect) expected background -> robust raw dump for Python. |
| 109 | ++% lambda: single, ng x np x 2 (page 1 = missense, page 2 = nonsense), column-major order. |
| 110 | ++fid = fopen([output_dir '/persample_lambda.f32'], 'w'); |
| 111 | ++fwrite(fid, single(persample_lambda), 'single'); |
| 112 | ++fclose(fid); |
| 113 | ++fid = fopen([output_dir '/persample_meta.txt'], 'w'); |
| 114 | ++fprintf(fid, 'ng\t%d\nnp\t%d\nneff\t%d\n', ... |
| 115 | ++ size(persample_lambda,1), size(persample_lambda,2), size(persample_lambda,3)); |
| 116 | ++fclose(fid); |
| 117 | ++fid = fopen([output_dir '/persample_genes.txt'], 'w'); |
| 118 | ++for ii = 1:numel(M.gene.name), fprintf(fid, '%s\n', M.gene.name{ii}); end |
| 119 | ++fclose(fid); |
| 120 | ++fid = fopen([output_dir '/persample_patients.txt'], 'w'); |
| 121 | ++for ii = 1:numel(M.pat.name), fprintf(fid, '%s\n', M.pat.name{ii}); end |
| 122 | ++fclose(fid); |
| 123 | ++fprintf('[DIALECT] wrote persample_lambda.f32 %dx%dx%d\n', ... |
| 124 | ++ size(persample_lambda,1), size(persample_lambda,2), size(persample_lambda,3)); |
| 125 | ++ |
| 126 | + % save categories file |
| 127 | + save_struct(M.categ,[output_dir '/mutcategs.txt']); |
| 128 | + |
| 129 | +diff --git a/src/fields.m b/src/fields.m |
| 130 | +new file mode 100644 |
| 131 | +index 0000000..90ffbf7 |
| 132 | +--- /dev/null |
| 133 | ++++ b/src/fields.m |
| 134 | +@@ -0,0 +1,5 @@ |
| 135 | ++function f = fields(s) |
| 136 | ++% Octave shadow of MATLAB's `fields` (a synonym for fieldnames), used throughout |
| 137 | ++% the MutSig source. Octave only provides `fieldnames`. |
| 138 | ++f = fieldnames(s); |
| 139 | ++end |
| 140 | +diff --git a/src/genvarname.m b/src/genvarname.m |
| 141 | +index 63e93ee..522bbdb 100644 |
| 142 | +--- a/src/genvarname.m |
| 143 | ++++ b/src/genvarname.m |
| 144 | +@@ -90,14 +90,14 @@ for k = 1:numel(varnameCell) |
| 145 | + varname = 'x'; |
| 146 | + end |
| 147 | + % Replace non-word character with its HEXADECIMAL equivalent |
| 148 | +- illegalChars = unique(varname(regexp(varname,'[^A-Za-z_0-9]'))); |
| 149 | ++ illegalChars = char(unique(double(varname(regexp(varname,'[^A-Za-z_0-9]'))))); % Octave: unique on char codes |
| 150 | + for illegalChar=illegalChars |
| 151 | +- if illegalChar <= intmax('uint8') |
| 152 | ++ if double(illegalChar) <= 255 |
| 153 | + width = 2; |
| 154 | + else |
| 155 | + width = 4; |
| 156 | + end |
| 157 | +- replace = ['0x' dec2hex(illegalChar,width)]; |
| 158 | ++ replace = ['0x' dec2hex(double(illegalChar),width)]; |
| 159 | + varname = strrep(varname, illegalChar, replace); |
| 160 | + end |
| 161 | + |
| 162 | +diff --git a/src/hist2d_fast.m b/src/hist2d_fast.m |
| 163 | +new file mode 100644 |
| 164 | +index 0000000..51f768a |
| 165 | +--- /dev/null |
| 166 | ++++ b/src/hist2d_fast.m |
| 167 | +@@ -0,0 +1,9 @@ |
| 168 | ++function h = hist2d_fast(x, y, xlo, xhi, ylo, yhi) |
| 169 | ++% Octave fallback for MutSig's hist2d_fast MEX: 2D histogram of integer (x,y) |
| 170 | ++% pairs into an (xhi-xlo+1) x (yhi-ylo+1) count matrix. Exact via accumarray. |
| 171 | ++x = round(x(:)); |
| 172 | ++y = round(y(:)); |
| 173 | ++keep = x >= xlo & x <= xhi & y >= ylo & y <= yhi; |
| 174 | ++h = accumarray([x(keep) - xlo + 1, y(keep) - ylo + 1], 1, ... |
| 175 | ++ [xhi - xlo + 1, yhi - ylo + 1]); |
| 176 | ++end |
| 177 | +diff --git a/src/projection_1d_convolutions_fast.m b/src/projection_1d_convolutions_fast.m |
| 178 | +new file mode 100644 |
| 179 | +index 0000000..c54e49d |
| 180 | +--- /dev/null |
| 181 | ++++ b/src/projection_1d_convolutions_fast.m |
| 182 | +@@ -0,0 +1,8 @@ |
| 183 | ++function [pmax, pmin] = projection_1d_convolutions_fast(Sdeg, Pdeg, score_obs, numbins, H, newH) %#ok<INUSD> |
| 184 | ++% Octave stub for MutSig's CV-significance MEX. It computes a gene's CV p-value, |
| 185 | ++% which DIALECT does NOT use -- we only need persample_lambda (the per-(gene, |
| 186 | ++% patient,effect) background), which is computed earlier in the gene loop. Return |
| 187 | ++% a neutral p=1 so the loop completes cleanly and our dump is saved. |
| 188 | ++pmax = 1; |
| 189 | ++pmin = 1; |
| 190 | ++end |
| 191 | +diff --git a/src/str2doubleq_wrapper.m b/src/str2doubleq_wrapper.m |
| 192 | +index cb7db0f..e8c0509 100644 |
| 193 | +--- a/src/str2doubleq_wrapper.m |
| 194 | ++++ b/src/str2doubleq_wrapper.m |
| 195 | +@@ -1,3 +1,8 @@ |
| 196 | + function out = str2doubleq_wrapper(in) |
| 197 | +- |
| 198 | +-out = real(str2doubleq(in)); |
| 199 | ++% str2doubleq is a MATLAB-only MEX; fall back to the built-in str2double under |
| 200 | ++% Octave (it vectorizes over cellstr the same way). |
| 201 | ++if exist('str2doubleq', 'file') == 3 |
| 202 | ++ out = real(str2doubleq(in)); |
| 203 | ++else |
| 204 | ++ out = str2double(in); |
| 205 | ++end |
| 206 | +diff --git a/src/verLessThan.m b/src/verLessThan.m |
| 207 | +new file mode 100644 |
| 208 | +index 0000000..9b0b325 |
| 209 | +--- /dev/null |
| 210 | ++++ b/src/verLessThan.m |
| 211 | +@@ -0,0 +1,12 @@ |
| 212 | ++function tf = verLessThan(pkg, verstr) |
| 213 | ++% Octave-safe shadow of MATLAB's verLessThan. |
| 214 | ++% MutSig calls verLessThan('matlab', X) to branch on the MATLAB version; under |
| 215 | ++% Octave there is no 'matlab' package, so treat it as a modern MATLAB (>= the |
| 216 | ++% query) -> return false, selecting the new-style code paths (no deprecated |
| 217 | ++% 'bufSize' textscan arg, etc.). |
| 218 | ++if nargin >= 1 && ischar(pkg) && strcmpi(pkg, 'matlab') |
| 219 | ++ tf = false; |
| 220 | ++ return; |
| 221 | ++end |
| 222 | ++tf = false; %#ok<NASGU> (no other packages are queried on our code path) |
| 223 | ++end |
0 commit comments