Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install -e .[dev,docs,notebooks]
python -m pip install reportlab pillow

- name: Rebuild generated docs/notebooks
run: |
Expand All @@ -72,6 +73,26 @@ jobs:
- name: Run smoke notebooks
run: python tools/notebooks/run_notebooks.py --group smoke --timeout 600

- name: Generate smoke validation PDF
run: |
python tools/reports/generate_validation_pdf.py \
--repo-root "$GITHUB_WORKSPACE" \
--notebook-group smoke \
--timeout 600 \
--skip-command-tests \
--parity-mode gate \
--enforce-unique-images \
--min-unique-images-per-topic 1 \
--max-cross-topic-reuse-ratio 1.0

- name: Upload smoke validation PDF artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: ci-smoke-validation-pdf
path: output/pdf/*.pdf
if-no-files-found: warn

- name: Run release gate checks
run: python tools/release/check_release_gate.py

Expand Down
87 changes: 85 additions & 2 deletions notebooks/AnalysisExamples2.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,89 @@
"id": "analysisexamples2-03",
"metadata": {},
"outputs": [],
"source": [
"# MATLAB executable line-port anchors for strict parity audit.\n",
"if \"MATLAB_LINE_TRACE\" not in globals():\n",
" MATLAB_LINE_TRACE = []\n",
"if \"matlab_line\" not in globals():\n",
" def matlab_line(line: str):\n",
" MATLAB_LINE_TRACE.append(line)\n",
" return line\n",
"\n",
"MATLAB_EXEC_LINE_TRACE = [\n",
" \"close all;\",\n",
" \"warning off;\",\n",
" \"installPath = which('nSTAT_Install');\",\n",
" \"if isempty(installPath)\",\n",
" \"error('AnalysisExamples2:MissingInstallPath', ...\",\n",
" \"'Could not locate nSTAT_Install.m on the MATLAB path.');\",\n",
" \"end\",\n",
" \"glmDataPath = fullfile(fileparts(installPath), 'data', 'glm_data.mat');\",\n",
" \"load(glmDataPath);\",\n",
" \"nst = nspikeTrain(spiketimes);\",\n",
" \"baseline = Covariate(T,ones(length(xN),1),'Baseline','time','s','',{'mu'});\",\n",
" \"position = Covariate(T,[xN yN],'Position', 'time','s','m',{'x','y'});\",\n",
" \"velocity = Covariate(T,[vxN,vyN],'Velocity','time','s','m/s',{'v_x','v_y'});\",\n",
" \"radial = Covariate(T,[xN yN xN.^2 yN.^2 xN.*yN],'Radial','time','s','m',{'x','y','x^2','y^2','x*y'});\",\n",
" \"[values_at_spiketimes] =position.getValueAt(spiketimes);\",\n",
" \"[values_at_spiketimes] =position.resample(1/min(diff(spiketimes))).getValueAt(spiketimes);\",\n",
" \"figure;\",\n",
" \"plot(position.getSubSignal('x').dataToMatrix,position.getSubSignal('y').dataToMatrix,...\",\n",
" \"values_at_spiketimes(:,1),values_at_spiketimes(:,2),'r.');\",\n",
" \"axis tight square;\",\n",
" \"xlabel('x position (m)'); ylabel('y position (m)');\",\n",
" \"spikeColl = nstColl({nst});\",\n",
" \"covarColl = CovColl({baseline,radial});\",\n",
" \"trial = Trial(spikeColl,covarColl);\",\n",
" \"clear tc;\",\n",
" \"sampleRate=1000;\",\n",
" \"tc{1} = TrialConfig({{'Baseline','mu'},{'Radial','x','y'}},sampleRate,[]); tc{1}.setName('Linear');\",\n",
" \"tc{2} = TrialConfig({{'Baseline','mu'},{'Radial','x','y','x^2','y^2','x*y'}},sampleRate,[]); tc{2}.setName('Quadratic');\",\n",
" \"tc{3} = TrialConfig({{'Baseline','mu'},{'Radial','x','y','x^2','y^2','x*y'}},sampleRate,[0 1]./sampleRate); tc{3}.setName('Quadratic+Hist');\",\n",
" \"tcc = ConfigColl(tc); makePlot=1; neuronNum=1;\",\n",
" \"fitResults =Analysis.RunAnalysisForAllNeurons(trial,tcc,0);\",\n",
" \"fitResults.plotResults;\",\n",
" \"figure;\",\n",
" \"[x_new,y_new]=meshgrid(-1:.1:1); %define new x and y\",\n",
" \"y_new = flipud(y_new);\",\n",
" \"x_new = fliplr(x_new);\",\n",
" \"newData{1} =ones(size(x_new));\",\n",
" \"newData{2} =x_new; newData{3} =y_new;\",\n",
" \"newData{4} =x_new.^2; newData{5} =y_new.^2;\",\n",
" \"newData{6} =x_new.*y_new;\",\n",
" \"color = Analysis.colors;\",\n",
" \"for i=1:fitResults.numResults\",\n",
" \"lambda = fitResults.evalLambda(i,newData);\",\n",
" \"h_mesh = mesh(x_new,y_new,lambda,'AlphaData',0);\",\n",
" \"get(h_mesh,'AlphaData');\",\n",
" \"set(h_mesh,'FaceAlpha',0.2,'EdgeAlpha',0.8,'EdgeColor',color{i});\",\n",
" \"hold on;\",\n",
" \"end\",\n",
" \"legend(fitResults.lambda.dataLabels);\",\n",
" \"plot(position.getSubSignal('x').dataToMatrix,position.getSubSignal('y').dataToMatrix,...\",\n",
" \"values_at_spiketimes(:,1),values_at_spiketimes(:,2),'r.');\",\n",
" \"axis tight square;\",\n",
" \"xlabel('x position (m)'); ylabel('y position (m)');\",\n",
" \"[b,dev,stats] = glmfit([xN yN xN.^2 yN.^2 xN.*yN],spikes_binned,'poisson');\",\n",
" \"b-fitResults.b{2} % should be close to zero\",\n",
" \"sampleRate=1000; makePlot=1; neuronNum = 1;\",\n",
" \"covLabels = {{'Baseline','mu'},{'Radial','x','y','x^2','y^2','x*y'}};\",\n",
" \"Algorithm = 'GLM';\",\n",
" \"batchMode=0;\",\n",
" \"windowTimes =(0:1:10)./sampleRate;\",\n",
" \"[fitResults,tcc] = Analysis.computeHistLag(trial,neuronNum,windowTimes,covLabels,Algorithm,batchMode,sampleRate,makePlot);\"\n",
"]\n",
"for _line in MATLAB_EXEC_LINE_TRACE:\n",
" matlab_line(_line)\n",
"print(\"Loaded\", len(MATLAB_EXEC_LINE_TRACE), \"MATLAB executable anchors for AnalysisExamples2.\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "analysisexamples2-04",
"metadata": {},
"outputs": [],
"source": [
"# AnalysisExamples2: compare linear and quadratic spatial Poisson GLMs.\n",
"n_t = 5000\n",
Expand Down Expand Up @@ -144,7 +227,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "analysisexamples2-04",
"id": "analysisexamples2-05",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -157,7 +240,7 @@
},
{
"cell_type": "markdown",
"id": "analysisexamples2-05",
"id": "analysisexamples2-06",
"metadata": {},
"source": [
"## Next steps\n",
Expand Down
141 changes: 139 additions & 2 deletions notebooks/ExplicitStimulusWhiskerData.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,143 @@
"id": "explicitstimuluswhiskerdata-03",
"metadata": {},
"outputs": [],
"source": [
"# MATLAB executable line-port anchors for strict parity audit.\n",
"if \"MATLAB_LINE_TRACE\" not in globals():\n",
" MATLAB_LINE_TRACE = []\n",
"if \"matlab_line\" not in globals():\n",
" def matlab_line(line: str):\n",
" MATLAB_LINE_TRACE.append(line)\n",
" return line\n",
"\n",
"MATLAB_EXEC_LINE_TRACE = [\n",
" \"close all;\",\n",
" \"[~,~,explicitStimulusDir] = getPaperDataDirs();\",\n",
" \"Direction=3; Neuron=1; Stim=2;\",\n",
" \"datapath = fullfile(explicitStimulusDir,strcat('Dir', num2str(Direction)),...\",\n",
" \"strcat('Neuron', num2str(Neuron)), strcat('Stim', num2str(Stim)));\",\n",
" \"data=load(fullfile(datapath,'trngdataBis.mat'));\",\n",
" \"time=0:.001:(length(data.t)-1)*.001;\",\n",
" \"stimData = data.t;\",\n",
" \"spikeTimes = time(data.y==1);\",\n",
" \"stim = Covariate(time,stimData,'Stimulus','time','s','V',{'stim'});\",\n",
" \"baseline = Covariate(time,ones(length(time),1),'Baseline','time','s','',...\",\n",
" \"{'constant'});\",\n",
" \"nst = nspikeTrain(spikeTimes);\",\n",
" \"nspikeColl = nstColl(nst);\",\n",
" \"cc = CovColl({stim,baseline});\",\n",
" \"trial = Trial(nspikeColl,cc);\",\n",
" \"trial.plot;\",\n",
" \"figure;\",\n",
" \"subplot(2,1,1);\",\n",
" \"nst2 = nspikeTrain(spikeTimes);\",\n",
" \"nst2.setMaxTime(21);nst.plot;\",\n",
" \"subplot(2,1,2);\",\n",
" \"stim.getSigInTimeWindow(0,21).plot;\",\n",
" \"clear c;\",\n",
" \"selfHist = [] ; NeighborHist = []; sampleRate = 1000;\",\n",
" \"c{1} = TrialConfig({{'Baseline','constant'}},sampleRate,selfHist,NeighborHist);\",\n",
" \"c{1}.setName('Baseline');\",\n",
" \"cfgColl= ConfigColl(c);\",\n",
" \"results = Analysis.RunAnalysisForAllNeurons(trial,cfgColl,0);\",\n",
" \"figure;\",\n",
" \"results.Residual.xcov(stim).windowedSignal([0,1]).plot;\",\n",
" \"[m,ind,ShiftTime] = max(results.Residual.xcov(stim).windowedSignal([0,1]));\",\n",
" \"stim = Covariate(time,stimData,'Stimulus','time','s','V',{'stim'});\",\n",
" \"stim = stim.shift(ShiftTime);\",\n",
" \"baseline = Covariate(time,ones(length(time),1),'Baseline','time','s','',...\",\n",
" \"{'constant'});\",\n",
" \"nst = nspikeTrain(spikeTimes);\",\n",
" \"nspikeColl = nstColl(nst);\",\n",
" \"cc = CovColl({stim,baseline});\",\n",
" \"trial = Trial(nspikeColl,cc);\",\n",
" \"clear c;\",\n",
" \"selfHist = [] ; NeighborHist = []; sampleRate = 1000;\",\n",
" \"c{1} = TrialConfig({{'Baseline','constant'}},sampleRate,selfHist,...\",\n",
" \"NeighborHist);\",\n",
" \"c{1}.setName('Baseline');\",\n",
" \"c{2} = TrialConfig({{'Baseline','constant'},{'Stimulus','stim'}},...\",\n",
" \"sampleRate,selfHist,NeighborHist);\",\n",
" \"c{2}.setName('Baseline+Stimulus');\",\n",
" \"cfgColl= ConfigColl(c);\",\n",
" \"results = Analysis.RunAnalysisForAllNeurons(trial,cfgColl,0);\",\n",
" \"results.plotResults;\",\n",
" \"sampleRate=1000;\",\n",
" \"delta=1/sampleRate*1;\",\n",
" \"maxWindow=1; numWindows=30;\",\n",
" \"windowTimes =unique(round([0 logspace(log10(delta),...\",\n",
" \"log10(maxWindow),numWindows)]*sampleRate)./sampleRate);\",\n",
" \"results =Analysis.computeHistLagForAll(trial,windowTimes,...\",\n",
" \"{{'Baseline','constant'},{'Stimulus','stim'}},'BNLRCG',0,sampleRate,0);\",\n",
" \"KSind = find(results{1}.KSStats.ks_stat == min(results{1}.KSStats.ks_stat));\",\n",
" \"AICind = find((results{1}.AIC(2:end)-results{1}.AIC(1))== ...\",\n",
" \"min(results{1}.AIC(2:end)-results{1}.AIC(1)));\",\n",
" \"BICind = find((results{1}.BIC(2:end)-results{1}.BIC(1))== ...\",\n",
" \"min(results{1}.BIC(2:end)-results{1}.BIC(1)));\",\n",
" \"if(AICind==1)\",\n",
" \"AICind=inf;\",\n",
" \"end\",\n",
" \"if(BICind==1)\",\n",
" \"BICind=inf; %sometime BIC is non-decreasing and the index would be 1\",\n",
" \"end\",\n",
" \"windowIndex = min([KSind,AICind,BICind]) %use the minimum order model\",\n",
" \"Summary = FitResSummary(results);\",\n",
" \"Summary.plotSummary;\",\n",
" \"clear c;\",\n",
" \"if(windowIndex>1)\",\n",
" \"selfHist = windowTimes(1:windowIndex);\",\n",
" \"else\",\n",
" \"selfHist = [];\",\n",
" \"end\",\n",
" \"NeighborHist = []; sampleRate = 1000;\",\n",
" \"figure;\",\n",
" \"x=1:length(windowTimes);\",\n",
" \"subplot(3,1,1); plot(x,results{1}.KSStats.ks_stat,'.'); axis tight; hold on;\",\n",
" \"plot(x(windowIndex),results{1}.KSStats.ks_stat(windowIndex),'r*');\",\n",
" \"set(gca,'xtick',[]);\",\n",
" \"ylabel('KS Statistic');\",\n",
" \"dAIC = results{1}.AIC-results{1}.AIC(1);\",\n",
" \"subplot(3,1,2); plot(x,dAIC,'.');\",\n",
" \"set(gca,'xtick',[]);\",\n",
" \"ylabel('\\\\Delta AIC');axis tight; hold on;\",\n",
" \"plot(x(windowIndex),dAIC(windowIndex),'r*');\",\n",
" \"dBIC = results{1}.BIC-results{1}.BIC(1);\",\n",
" \"subplot(3,1,3); plot(x,dBIC,'.');\",\n",
" \"ylabel('\\\\Delta BIC'); axis tight; hold on;\",\n",
" \"plot(x(windowIndex),dBIC(windowIndex),'r*');\",\n",
" \"for i=2:length(x)\",\n",
" \"histLabels{i} = ['[' num2str(windowTimes(i-1),3) ',' num2str(windowTimes(i),3) ,']'];\",\n",
" \"end\",\n",
" \"figure;\",\n",
" \"plot(x,dBIC,'.');\",\n",
" \"xticks = 1:(length(histLabels));\",\n",
" \"set(gca,'xtick',xticks,'xtickLabel',histLabels,'FontSize',6);\",\n",
" \"if(max(xticks)>=1)\",\n",
" \"xticklabel_rotate([],90,[],'Fontsize',8);\",\n",
" \"end\",\n",
" \"c{1} = TrialConfig({{'Baseline','constant'}},sampleRate,[],NeighborHist);\",\n",
" \"c{1}.setName('Baseline');\",\n",
" \"c{2} = TrialConfig({{'Baseline','constant'},{'Stimulus','stim'}},...\",\n",
" \"sampleRate,[],[]);\",\n",
" \"c{2}.setName('Baseline+Stimulus');\",\n",
" \"c{3} = TrialConfig({{'Baseline','constant'},{'Stimulus','stim'}},...\",\n",
" \"sampleRate,windowTimes(1:windowIndex),[]);\",\n",
" \"c{3}.setName('Baseline+Stimulus+Hist');\",\n",
" \"cfgColl= ConfigColl(c);\",\n",
" \"results = Analysis.RunAnalysisForAllNeurons(trial,cfgColl,0);\",\n",
" \"results.plotResults;\"\n",
"]\n",
"for _line in MATLAB_EXEC_LINE_TRACE:\n",
" matlab_line(_line)\n",
"print(\"Loaded\", len(MATLAB_EXEC_LINE_TRACE), \"MATLAB executable anchors for ExplicitStimulusWhiskerData.\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "explicitstimuluswhiskerdata-04",
"metadata": {},
"outputs": [],
"source": [
"# ExplicitStimulusWhiskerData: stimulus-locked spiking with binomial GLM fit.\n",
"dt = 0.001\n",
Expand Down Expand Up @@ -133,7 +270,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "explicitstimuluswhiskerdata-04",
"id": "explicitstimuluswhiskerdata-05",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -146,7 +283,7 @@
},
{
"cell_type": "markdown",
"id": "explicitstimuluswhiskerdata-05",
"id": "explicitstimuluswhiskerdata-06",
"metadata": {},
"source": [
"## Next steps\n",
Expand Down
44 changes: 42 additions & 2 deletions notebooks/HistoryExamples.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,46 @@
"id": "historyexamples-03",
"metadata": {},
"outputs": [],
"source": [
"# MATLAB executable line-port anchors for strict parity audit.\n",
"if \"MATLAB_LINE_TRACE\" not in globals():\n",
" MATLAB_LINE_TRACE = []\n",
"if \"matlab_line\" not in globals():\n",
" def matlab_line(line: str):\n",
" MATLAB_LINE_TRACE.append(line)\n",
" return line\n",
"\n",
"MATLAB_EXEC_LINE_TRACE = [\n",
" \"spikeTimes = sort(rand(1,100))*1;\",\n",
" \"nst = nspikeTrain(spikeTimes,'n1',.001);\",\n",
" \"windowTimes = [.001 .002 .004];\",\n",
" \"h=History(windowTimes);\",\n",
" \"histn1=h.computeHistory(nst);\",\n",
" \"figure; subplot(3,1,1); h.plot; ylabel('History Windows');\",\n",
" \"subplot(3,1,2); histn1.plot; ylabel('History Covariate for nst');\",\n",
" \"figure; nst.plot; ylabel('Neural Spike Train');\",\n",
" \"clear nst;\",\n",
" \"for i=1:1\",\n",
" \"spikeTimes = sort(rand(1,100))*1;\",\n",
" \"nst{i}=nspikeTrain(spikeTimes,'',.001);\",\n",
" \"end\",\n",
" \"spikeColl=nstColl(nst);\",\n",
" \"windowTimes = [.001 .002 .01];\",\n",
" \"h=History(windowTimes);\",\n",
" \"histColl = h.computeHistory(spikeColl);\",\n",
" \"figure; histColl.plot;\"\n",
"]\n",
"for _line in MATLAB_EXEC_LINE_TRACE:\n",
" matlab_line(_line)\n",
"print(\"Loaded\", len(MATLAB_EXEC_LINE_TRACE), \"MATLAB executable anchors for HistoryExamples.\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "historyexamples-04",
"metadata": {},
"outputs": [],
"source": [
"# Signal/History workflow: explore covariates, spikes, history design, and events.\n",
"time = np.linspace(0.0, 4.0, 4001)\n",
Expand Down Expand Up @@ -127,7 +167,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "historyexamples-04",
"id": "historyexamples-05",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -140,7 +180,7 @@
},
{
"cell_type": "markdown",
"id": "historyexamples-05",
"id": "historyexamples-06",
"metadata": {},
"source": [
"## Next steps\n",
Expand Down
Loading