Projection targeting with phototagging to study the structure and function of retinal ganglion cells.
The 3 matches
- [1] § STAR★Methods › Quantification and statistical analysis › ReaChR cell identification ↔ Phototagging_methods_code/phototagging_functions/Reachr_classification_AMR.m, lines 54–101 · score 0.66 · ReaChR signal, PC1, strengths, variance, deviations, histogram
- [2] § STAR★Methods › Method details › Visual stimulation ↔ src/yass/rf/run.py, lines 135–246 · score 0.58 · frame rate, white noise, MATLAB, stimuli, temporal
- [3] § STAR★Methods › Quantification and statistical analysis › Receptive field estimation ↔ src/yass/rf/run.py, lines 135–246 · score 0.55 · Gaussian fit, pixels, triggered, frames, RF, STA
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 542 lines · 20 KB · Apache-2.0 · 2 matches
- import h5py
- import parmap
- import numpy as np
- import scipy.io as sio
- import os
- from tqdm import tqdm
- import scipy
- import scipy.io
- import scipy.optimize as opt
- from scipy.spatial.distance import cdist
- from scipy.ndimage import gaussian_filter
- import networkx as nx
- from pkg_resources import resource_filename
- from yass import read_config
- from yass.template import upsample_resample, shift_chans
- from yass.rf.sta_fit import get_fit_on_sta
- from yass.rf.util import get_rf, get_circle_plotting_data, classifiy_contours
- def run():
- """RF computation
- """
- CONFIG = read_config()
- stim_movie_file = os.path.join(CONFIG.data.root_folder, CONFIG.data.stimulus)
- triggers_fname = os.path.join(CONFIG.data.root_folder, CONFIG.data.triggers)
- spike_train_fname = os.path.join(CONFIG.path_to_output_directory,
- 'spike_train.npy')
- saving_dir = os.path.join(CONFIG.path_to_output_directory, 'rf')
- rf = RF(stim_movie_file, triggers_fname, spike_train_fname, saving_dir)
- rf.calculate_STA()
- rf.detect_multi_rf()
- rf.classification()
- class RF(object):
- def __init__(self, saving_dir, stim_movie_file,triggers_fname,
- spike_train_fname, soft_assignment_fname=None,
- fname_classification_boundary=None, matlab_bin='matlab'):
- # default parameter
- self.n_color_channels = 3
- self.sp_frame_rate = 20000
- #self.data_sample_len = 36000000 # len of white noise data (this script doesn't look at natural scenes)
- self.load_spike_train(spike_train_fname)
- if soft_assignment_fname is not None:
- self.soft_assignment = np.load(soft_assignment_fname)
- else:
- self.soft_assignment = np.ones(self.sps.shape[0])
- self.stim_movie_file = stim_movie_file
- self.triggers_fname = triggers_fname
- self.save_dir = saving_dir
- if not os.path.exists(self.save_dir):
- os.makedirs(self.save_dir)
- if self.save_dir[-1] != '/':
- self.save_dir += '/'
- self.matlab_bin = matlab_bin
- self.fname_classification_boundary = fname_classification_boundary
- print("spike train:\t{}".format(self.sps.shape))
- print("Number of units:\t{}".format(self.Ncells))
- def load_stimulus_trigger(self, stim_movie_file, triggers_fname):
- print('Loading Stimulus...')
- # Load stim file
- h5_temp = h5py.File(stim_movie_file, 'r')
- self.WN_stim = h5_temp['movie'][:]
- h5_temp.close()
- self.stim_size = self.WN_stim.shape[2:4]
- self.WN_stim = self.WN_stim.reshape((-1, self.n_color_channels,
- self.stim_size[0]*self.stim_size[1]))
- ## Load triggers
- if triggers_fname.split('.')[-1] == 'trig':
- with open(triggers_fname, 'rb'):
- self.WN_trigger_times = np.fromfile(triggers_fname, dtype='int16')
- elif triggers_fname.split('.')[-1] == 'mat':
- self.WN_trigger_times = sio.loadmat(triggers_fname)
- self.WN_trigger_times = self.WN_trigger_times['triggers'].flatten().astype('float')
- print("stim movie:\t{}".format(self.WN_stim.shape))
- np.save(self.save_dir+'stim_size.npy',self.stim_size)
- def calculate_frame_times(self):
- frame_per_pulse = 100
- ## Find pulses and calculate frame times
- # Get first locations of pulses in seconds
- pulses = np.where(np.diff(self.WN_trigger_times)==-2048)[0]+1 # find where pulse starts (diff+1)
- pulses_seconds = pulses / float(self.sp_frame_rate) # divide by 20k Hz to get seconds
- self.frame_times = np.interp(
- np.arange(0,frame_per_pulse * pulses_seconds.shape[0]),
- np.arange(0,frame_per_pulse * pulses_seconds.shape[0], frame_per_pulse),
- pulses_seconds)
- def load_spike_train(self, spike_train_fname):
- print('Loading Spike Train...')
- ## Load spikes
- sps_file_ext = os.path.splitext(spike_train_fname)[1]
- if sps_file_ext == '.mat':
- #sps = sio.loadmat(spike_train_fname)['spike_train'].astype('int32')
- # for single columnd data
- sps_temp = sio.loadmat(spike_train_fname)['spike_train'].astype('int32')
- unique_ids = np.unique(sps_temp[:,1])
- unique_ids = unique_ids[unique_ids>0] - 1
- self.sps = np.zeros(sps_temp.shape, 'int32')
- self.sps[:, 0] = sps_temp[:, 0]
- for i, k in enumerate(unique_ids):
- idx = sps_temp[:, 1] == (k+1)
- self.sps[idx, 1] = i
- elif sps_file_ext == '.npy':
- self.sps = np.load(spike_train_fname)
- # Get number of cells/units
- self.Ncells = int(np.max(self.sps[:,1])+1)
- def calculate_STA(self):
- self.load_stimulus_trigger(self.stim_movie_file, self.triggers_fname)
- self.calculate_frame_times()
- tmp_dir = os.path.join(self.save_dir, 'tmp')
- if not os.path.exists(tmp_dir):
- os.makedirs(tmp_dir)
- tmp_dir_sta = os.path.join(tmp_dir, 'sta')
- if not os.path.exists(tmp_dir_sta):
- os.makedirs(tmp_dir_sta)
- tmp_dir_rgc = os.path.join(tmp_dir, 'rgc')
- if not os.path.exists(tmp_dir_rgc):
- os.makedirs(tmp_dir_rgc)
- print('Calculating STA...')
- ############################################
- ## Get full STAs and spatial/temporal STA ##
- ############################################
- STA_temporal_length = 30 # how many bins/frames to include in STA
- Ncells = self.Ncells
- stim_size = self.stim_size
- n_color_channels = self.n_color_channels
- n_pixels = stim_size[0]*stim_size[1]
- unique_ids = np.unique(self.sps[:,1])
- args_in = []
- for i_cell in np.arange(Ncells):
- fname = os.path.join(tmp_dir_sta, 'unit_'+str(i_cell)+'.mat')
- if not os.path.exists(fname):
- ##################################
- ### Get spikes in stimulus bins ##
- ##################################
- # Get spike times of this cell in seconds
- idx_ = np.where(self.sps[:,1]==i_cell)[0]
- these_sps = self.sps[idx_, 0]
- #spikes before 36000000 are white noise spikes, divide by frame rate to get seconds
- these_sps = these_sps / float(self.sp_frame_rate)
- weight = self.soft_assignment[idx_]
- ## Line up spikes with frames
- binned_spikes = weighted_histogram(these_sps, weight, self.frame_times)
- which_spikes = np.where(binned_spikes>0)[0]
- which_spikes = which_spikes[which_spikes>STA_temporal_length]
- args_in.append([
- self.WN_stim,
- binned_spikes,
- which_spikes,
- STA_temporal_length,
- stim_size,
- fname
- ])
- if False:
- n_processors = 6
- parmap.map(sta_calculation_parallel,
- args_in,
- processes=n_processors,
- pm_pbar=True)
- else:
- for unit in tqdm(range(len(args_in))):
- sta_calculation_parallel(args_in[unit])
- sta_array = np.zeros((Ncells, stim_size[0], stim_size[1],
- n_color_channels, STA_temporal_length))
- for unit in range(Ncells):
- fname = os.path.join(tmp_dir_sta, 'unit_'+str(unit)+'.mat')
- sta = sio.loadmat(fname)['temp_stas']
- sta_array[unit] = sta
- ## run matlab code
- #print('running matlab code')
- #rf_matlab_loc = resource_filename('yass', 'rf/rf_matlab')
- #command = '{} -nodisplay -r \"cd(\'{}\'); fit_sta_liam_parallel(\'{}\', \'{}\'); exit\"'.format(
- # self.matlab_bin, rf_matlab_loc, tmp_dir_sta, tmp_dir_rgc)
- #print(command)
- #os.system(command)
- #print('done running matlab code')
- #STA_spatial = np.zeros((self.Ncells, stim_size[0], stim_size[1], n_color_channels))
- #STA_temporal = np.zeros((self.Ncells, STA_temporal_length, n_color_channels))
- #gaussian_fits = np.zeros((self.Ncells, 5))
- #for unit in unique_ids:
- # fname = os.path.join(tmp_dir_rgc, 'rgc_{}.mat'.format(unit))
- # try:
- # data = scipy.io.loadmat(fname)
- # if 'temp_rf' in data.keys():
- # STA_spatial[unit] = data['temp_rf']
- # STA_temporal[unit] = data['fit_tc']
- # gaussian_fits[unit] = data['temp_fit_params']['fit_params'][0][0][0][:5]
- # except:
- # print('unit {} corrupted'.format(unit))
- STA_spatial, STA_temporal, gaussian_fits = get_fit_on_sta(sta_array)
- # hack for now
- STA_spatial = np.tile(STA_spatial[:, :, :, None],
- (1, 1, 1, n_color_channels))
- STA_temporal = STA_temporal.transpose(0, 2, 1)
- np.save(os.path.join(self.save_dir, 'STA_spatial.npy'), STA_spatial)
- np.save(os.path.join(self.save_dir, 'STA_temporal.npy'), STA_temporal)
- np.save(os.path.join(self.save_dir, 'gaussian_fits.npy'), gaussian_fits)
- def detect_multi_rf(self):
- STA_spatial = np.load(self.save_dir+'STA_spatial.npy')
- n_units = STA_spatial.shape[0]
- n_rfs = np.zeros(n_units)
- for j in range(n_units):
- rf = STA_spatial[j][:, :, 1]
- n_rfs[j] = len(get_rf(rf - np.mean(rf), 2))
- # yass
- idx = np.where(n_rfs==1)[0]
- np.save(self.save_dir+'idx_single_rf.npy', idx)
- idx = np.where(n_rfs==0)[0]
- np.save(self.save_dir+'idx_no_rf.npy', idx)
- idx = np.where(n_rfs > 1)[0]
- np.save(self.save_dir+'idx_multi_rf.npy', idx)
- def load_data_for_classification(self, load_contours=False):
- # load data
- sta_spatial = np.load(os.path.join(self.save_dir, 'STA_spatial.npy'))
- sta_spatial[np.isnan(sta_spatial)] = 0
- sta_temporal = np.load(os.path.join(self.save_dir, 'STA_temporal.npy'))
- sta_temporal[np.isnan(sta_temporal)] = 0
- gaussian_fits = np.load(os.path.join(self.save_dir, 'gaussian_fits.npy'))
- n_units = sta_temporal.shape[0]
- spike_train = self.sps
- unique_ids, n_spikes = np.unique(spike_train[:,1], return_counts=True)
- firing_rates = np.zeros(n_units)
- firing_rates[unique_ids] = n_spikes/(np.ptp(spike_train[:,0])/self.sp_frame_rate)
- max_loc = np.abs(sta_temporal[:,:,1]).argmax(1)
- sign = np.sign(sta_temporal[np.arange(n_units), max_loc])
- peak_val = np.zeros((n_units, 3))
- for j in range(n_units):
- sta_ = (sta_spatial[j].reshape(-1, 3))*sign[j][None]
- peak_val[j] = sta_[np.max(sta_, 1).argmax()]
- peak_val = peak_val*sign
- green_val = peak_val[:, 1]
- gaussian_sd = gaussian_fits[:, 3:5]
- if load_contours:
- contours = np.zeros((n_units, 64, 2))
- for j in range(n_units):
- xy = get_circle_plotting_data(j, gaussian_fits)
- contours[j] = xy.T
- else:
- contours = None
- return gaussian_sd, green_val, firing_rates, contours
- def classification(self, fname_classification_boundary=None):
- gaussian_sd, green_val, f_rates, _ = self.load_data_for_classification()
- idx_single = np.load(os.path.join(self.save_dir, 'idx_single_rf.npy'))
- if fname_classification_boundary is None:
- fname_classification_boundary = self.fname_classification_boundary
- temp = np.load(fname_classification_boundary)
- sd_mean_noise_th = temp['sd_mean_noise_th']
- sd_ratio_noise_th = temp['sd_ratio_noise_th']
- green_noise_th = temp['green_noise_th']
- midget_on_th = temp['midget_on_th']
- midget_off_th = temp['midget_off_th']
- large_on_th = temp['large_on_th']
- large_off_th = temp['large_off_th']
- sbc_fr_th = temp['sbc_fr_th']
- labels_single, cell_types = classifiy_contours(
- gaussian_sd[idx_single],
- green_val[idx_single],
- f_rates[idx_single],
- sd_mean_noise_th,
- sd_ratio_noise_th,
- green_noise_th,
- midget_on_th,
- midget_off_th,
- large_on_th,
- large_off_th,
- sbc_fr_th)
- labels = np.ones(self.Ncells, 'int32')*-1
- labels[idx_single] = labels_single
- np.save(os.path.join(self.save_dir, 'labels.npy'), labels)
- np.save(os.path.join(self.save_dir, 'cell_types.npy'), cell_types)
- def twoD_Gaussian(self, xdata_tuple, amplitude, xo, yo, sigma_x, sigma_y, theta, offset):
- ## Define 2D Gaussian that we'll fit to spatial STAs
- (x, y) = xdata_tuple
- xo = float(xo)
- yo = float(yo)
- a = (np.cos(theta)**2)/(2*sigma_x**2) + (np.sin(theta)**2)/(2*sigma_y**2)
- b = -(np.sin(2*theta))/(4*sigma_x**2) + (np.sin(2*theta))/(4*sigma_y**2)
- c = (np.sin(theta)**2)/(2*sigma_x**2) + (np.cos(theta)**2)/(2*sigma_y**2)
- g = offset + amplitude*np.exp( - (a*((x-xo)**2) + 2*b*(x-xo)*(y-yo)+c*((y-yo)**2)))
- return g.ravel()
- def fit_gaussian(self):
- if not os.path.exists(self.save_dir+'Gaussian_params.npy'):
- print('Fitting Gaussian on STA...')
- stim_size = self.stim_size
- STA_spatial = np.load(self.save_dir+'STA_spatial.npy')
- ## Fit Gaussian to STA
- use_green_only = True
- if use_green_only:
- this_STA_spatial = STA_spatial[:,1]
- else:
- this_STA_spatial = STA_spatial_colorcat
- Gaussian_params = np.zeros((self.Ncells,7))
- Gaussian_params[:]=np.nan
- nonconverged_Gaussian_cells = np.empty(0,) # keep track of cells where fitting procedure doesn't converge
- # Loop over cells
- for i_cell in tqdm(range(self.Ncells)):
- # Get STA for this cell
- this_STA = this_STA_spatial[i_cell].reshape((-1,))
- # Create x and y indices for grid for Gaussian fit
- x = np.arange(0, stim_size[1], 1)
- y = np.arange(0, stim_size[0], 1)
- x, y = np.meshgrid(x, y)
- # Get initial guess for Gaussian parameters (helps with fitting)
- init_amp = this_STA[np.argmax(np.abs(this_STA))] # get amplitude guess from most extreme (max or min) amplitude of this_STA
- init_x,init_y = np.unravel_index(np.argmax(np.abs(this_STA)),(stim_size[0],stim_size[1])) # guess center of Gaussian as indices of most extreme (max or min) amplitude
- initial_guess = (init_amp,init_y,init_x,2,2,0,0)
- # Try to fit, if it doesn't converge, log that cell
- try:
- popt, pcov = opt.curve_fit(self.twoD_Gaussian, (x, y), this_STA, p0=initial_guess)
- Gaussian_params[i_cell] = popt
- Gaussian_params[i_cell,3:5] = np.abs(popt[3:5]) # sometimes sds are negative (in Gaussian def above, they're always squared)
- except:
- nonconverged_Gaussian_cells = np.append(nonconverged_Gaussian_cells,i_cell)
- np.save(self.save_dir+'Gaussian_params.npy',Gaussian_params)
- def get_denoiser(STA):
- max_timecourse = np.max(np.abs(STA[:,20:]), axis=1)
- max_timecourse_mean = np.mean(max_timecourse, axis=2)
- max_timecourse_std = np.std(max_timecourse, axis=2)
- good_ones = max_timecourse > (max_timecourse_mean + 4*max_timecourse_std)[:,:,np.newaxis]
- denoiser = np.zeros((3, 3, STA.shape[1]))
- for color in range(3):
- unit_id, pixel_id = np.where(good_ones[:,color])
- good_timecourse = STA[unit_id, :, color, pixel_id]
- [U,S,V] = np.linalg.svd(good_timecourse.T)
- denoiser[color] = U[:,:3].T
- return denoiser
- def denoise_STA(STA):
- denoiser = get_denoiser(STA)
- n_units, _, _, n_pixels = STA.shape
- n_colors, n_filter, n_time = denoiser.shape
- STA_denoised = np.zeros(STA.shape)
- for color in range(n_colors):
- deno = np.matmul(denoiser[color].T, denoiser[color])
- STA_temp = STA[:,:,color].transpose(0,2,1).reshape(-1, n_time)
- STA_denoised[:,:,color] = np.matmul(STA_temp, deno).reshape(n_units, n_pixels, n_time).transpose(0,2,1)
- return STA_denoised
- def get_temp_spat_filters(STA):
- [U,S,V] = np.linalg.svd(STA)
- temp_filter = U[:, 0]
- spatial_filter = V[0]
- temp_sign = np.sign(temp_filter[np.abs(temp_filter).argmax()])
- spat_sign = np.sign(spatial_filter[np.abs(spatial_filter).argmax()])
- sign = temp_sign*spat_sign
- if temp_sign != sign:
- temp_filter *= -1.0
- if spat_sign != sign:
- spatial_filter *= -1.0
- return temp_filter, spatial_filter
- def sta_calculation_parallel(arg_in):
- WN_stim = arg_in[0]
- binned_spikes = arg_in[1]
- which_spikes = arg_in[2]
- STA_temporal_length = arg_in[3]
- stim_size = arg_in[4]
- fname = arg_in[5]
- ####################
- ### Calculate STA ##
- ####################
- ## Swap out fastest version here
- _, n_color_channels, n_pixels = WN_stim.shape
- STA = np.zeros((STA_temporal_length, n_color_channels, n_pixels))
- for i in range(which_spikes.shape[0]):
- bin_number = which_spikes[i]
- STA += binned_spikes[bin_number]*WN_stim[bin_number-(STA_temporal_length-1):bin_number+1]
- if which_spikes.shape[0] == 0:
- STA += 0.5
- # full sta
- if np.sum(binned_spikes[STA_temporal_length:])>0:
- STA = STA/np.sum(binned_spikes[STA_temporal_length:])
- STA = STA.reshape(STA_temporal_length, n_color_channels,
- stim_size[0], stim_size[1])
- STA = STA.transpose(2,3,1,0)
- scipy.io.savemat(fname, mdict={'temp_stas': STA})
- def align_tc(tc, ref):
- n_units, n_timepoints, n_channels = tc.shape
- max_channels = np.abs(tc).max(1).argmax(1)
- main_tc = np.zeros((n_units, n_timepoints))
- for j in range(n_units):
- main_tc[j] = np.abs(tc[j][:,max_channels[j]])
- best_shifts = align_get_shifts_tc(main_tc, ref, upsample_factor=1)
- shifted_tc = shift_chans(tc, best_shifts)
- return shifted_tc
- def align_get_shifts_tc(wf, ref, upsample_factor = 5, nshifts = 21):
- ''' Align all waveforms on a single channel
- wf = selected waveform matrix (# spikes, # samples)
- max_channel: is the last channel provided in wf
- Returns: superresolution shifts required to align all waveforms
- - used downstream for linear interpolation alignment
- '''
- # convert nshifts from timesamples to #of times in upsample_factor
- nshifts = (nshifts*upsample_factor)
- if nshifts%2==0:
- nshifts+=1
- # or loop over every channel and parallelize each channel:
- #wf_up = []
- wf_up = upsample_resample(wf, upsample_factor)
- wf_start = 15*upsample_factor
- wf_trunc = wf_up[:,wf_start:]
- wlen_trunc = wf_trunc.shape[1]
- # align to last chanenl which is largest amplitude channel appended
- ref_upsampled = upsample_resample(ref[np.newaxis], upsample_factor)[0]
- ref_shifted = np.zeros([wf_trunc.shape[1], nshifts])
- for i,s in enumerate(range(-int((nshifts-1)/2), int((nshifts-1)/2+1))):
- ref_shifted[:,i] = np.roll(ref_upsampled, -s)[wf_start:]
- bs_indices = np.matmul(wf_trunc[:,np.newaxis], ref_shifted).squeeze(1).argmax(1)
- best_shifts = (np.arange(-int((nshifts-1)/2), int((nshifts-1)/2+1)))[bs_indices]
- return best_shifts/np.float32(upsample_factor)
- def weighted_histogram(data, weights, bin_range):
- bin_counts = np.zeros(len(bin_range)-1)
- j = 0
- ii = 0
- data = data[data < bin_range.max()]
- while ii < len(data):
- if data[ii] < bin_range[j+1]:
- bin_counts[j] += weights[ii]
- ii += 1
- else:
- j += 1
- return bin_counts
run.py at commit b18d13a, under Apache-2.0 · at the source
Overview
- Department of Biomedical Engineering, Pratt School of Engineering, Duke University, Durham, NC 27708, USA
- Department of Neurobiology, Duke University School of Medicine, Durham, NC 27708, USA
- Department of Neurobiology, David Geffen School of Medicine, University of California, Los Angeles, Los Angeles, CA 90095, USA
- Center for Cognitive Neuroscience, Duke University, Durham, NC 27708, USA
- Jules Stein Eye Institute, Department of Ophthalmology, University California, Los Angeles, Los Angeles, CA 90095, USA
- Department of Ophthalmology, University of Washington, Seattle, WA 98109, USA
- John A. Moran Eye Center, Department of Ophthalmology and Visual Sciences, University of Utah, Salt Lake City, UT 84132, USA
- Department of Pharmacology, University of North Carolina, Chapel Hill, NC 27514, USA
Abstract
Understanding the structure-function relationships across neurons is challenging, particularly when circuits are composed of dozens of distinct cell types. We refined an approach, called “projection targeting with phototagging”, that allows simultaneous elucidation of the projections, morphology, and visual response properties of diverse retinal ganglion cell (RGC) types in the mammalian retina. The approach combines retrograde virally mediated phototagging of RGCs, microscopy, and large-scale multi-electrode array (MEA) measurements. Importantly, the approach does not rely on transgenic animals and thus is potentially generalizable across species. We validated this approach in rats by targeting retinal projections to the superior colliculus (SC). We showed that multiple RGC types project to the SC and that these results in rats align well with prior findings from transgenic mouse studies.
Reproduced under the paper's license (CC BY-NC), from the paper cited above.
Repositories
Its files are read in the Code ↔ Paper reader above, with 3 matches between paragraphs and lines of code.
gdfield/Phototagging_methods
1128b36d99c73a7c5c51debc9589ea94b56eac62, 2 September 2025Availability: 1 check, the latest on 30 September 2026: the link answers
- 30 September 2026: the link answers
19 files
- Phototagging_methods_cod
e/ , MATLAB, 165 lines, 1 matchphototagging_functions/ Reachr_classification_AM R.m - Phototagging_methods_cod
e/ , MATLAB, 125 linesphototagging_functions/ Reachr_transformation_AM R.m - Phototagging_methods_cod
e/ , MATLAB, 27 linesphototagging_functions/ get_SN_vector.m - Phototagging_methods_cod
e/ , MATLAB, 115 linesphototagging_functions/ get_cell_indices.m - Phototagging_methods_cod
e/ , MATLAB, 29 linesphototagging_functions/ get_ei_max_frame.m - Phototagging_methods_cod
e/ , MATLAB, 60 linesphototagging_functions/ get_electrode_positions. m - Phototagging_methods_cod
e/ , MATLAB, 72 linesphototagging_functions/ get_psth.m - Phototagging_methods_cod
e/ , MATLAB, 92 linesphototagging_functions/ get_raster.m - Phototagging_methods_cod
e/ , MATLAB, 7 linesphototagging_functions/ infer_electrode_spacing. m - Phototagging_methods_cod
e/ , MATLAB, 1,148 linesphototagging_functions/ ipdm.m - Phototagging_methods_cod
e/ , MATLAB, 171 linesphototagging_functions/ legend_curate.m - Phototagging_methods_cod
e/ , MATLAB, 21 linesphototagging_functions/ nums_from_ids.m - Phototagging_methods_cod
e/ , MATLAB, 56 linesphototagging_functions/ plot_ReaChR_PSTH.m - Phototagging_methods_cod
e/ , MATLAB, 67 linesphototagging_functions/ plot_ReaChR_raster.m - Phototagging_methods_cod
e/ , MATLAB, 222 linesphototagging_functions/ plot_ei_.m - Phototagging_methods_cod
e/ , MATLAB, 54 linesphototagging_functions/ plot_ei_over_epi.m - Phototagging_methods_cod
e/ , MATLAB, 78 linesphototagging_functions/ set_up_fig_or_axes.m - Phototagging_methods_cod
e/ , MATLAB, 77 linesscrip-ReaChR_classificat ion.m - Phototagging_methods_cod
e/ , MATLAB, 61 linesscript-Mapping_EI_over_e pi.m
Zenodo 17795220
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
- 30 September 2026: the link answers (HTTP 200)
19 files
- Phototagging_methods_cod
e/ , MATLAB, 165 linesphototagging_functions/ Reachr_classification_AM R.m - Phototagging_methods_cod
e/ , MATLAB, 125 linesphototagging_functions/ Reachr_transformation_AM R.m - Phototagging_methods_cod
e/ , MATLAB, 27 linesphototagging_functions/ get_SN_vector.m - Phototagging_methods_cod
e/ , MATLAB, 115 linesphototagging_functions/ get_cell_indices.m - Phototagging_methods_cod
e/ , MATLAB, 29 linesphototagging_functions/ get_ei_max_frame.m - Phototagging_methods_cod
e/ , MATLAB, 60 linesphototagging_functions/ get_electrode_positions. m - Phototagging_methods_cod
e/ , MATLAB, 72 linesphototagging_functions/ get_psth.m - Phototagging_methods_cod
e/ , MATLAB, 92 linesphototagging_functions/ get_raster.m - Phototagging_methods_cod
e/ , MATLAB, 7 linesphototagging_functions/ infer_electrode_spacing. m - Phototagging_methods_cod
e/ , MATLAB, 1,148 linesphototagging_functions/ ipdm.m - Phototagging_methods_cod
e/ , MATLAB, 171 linesphototagging_functions/ legend_curate.m - Phototagging_methods_cod
e/ , MATLAB, 21 linesphototagging_functions/ nums_from_ids.m - Phototagging_methods_cod
e/ , MATLAB, 56 linesphototagging_functions/ plot_ReaChR_PSTH.m - Phototagging_methods_cod
e/ , MATLAB, 67 linesphototagging_functions/ plot_ReaChR_raster.m - Phototagging_methods_cod
e/ , MATLAB, 222 linesphototagging_functions/ plot_ei_.m - Phototagging_methods_cod
e/ , MATLAB, 54 linesphototagging_functions/ plot_ei_over_epi.m - Phototagging_methods_cod
e/ , MATLAB, 78 linesphototagging_functions/ set_up_fig_or_axes.m - Phototagging_methods_cod
e/ , MATLAB, 77 linesscrip-ReaChR_classificat ion.m - Phototagging_methods_cod
e/ , MATLAB, 61 linesscript-Mapping_EI_over_e pi.m
paninski-lab/yass
b18d13a69946c1fee28fbc1f67215d3a89d892af, 29 September 2022Availability: 1 check, the latest on 30 September 2026: the link answers
- 30 September 2026: the link answers
192 files
- doc/
conf.py , Python, 371 lines - examples/
batch/ , Python, 53 linesmulti_channel.py - examples/
batch/ , Python, 72 linesmulti_channel_apply_disk .py - examples/
batch/ , Python, 67 linesmulti_channel_apply_memo ry.py - examples/
batch/ , Python, 82 linesnew_batch_fn.py - examples/
batch/ , Python, 52 linespipeline.py - examples/
batch/ , Python, 49 linesreader.py - examples/
batch/ , Python, 55 linessingle_channel.py - examples/
batch/ , Python, 57 linessingle_channel_apply.py - examples/
batch/ , Python, 20 linesvectorize_parameter.py - examples/
complete/ , Python, 17 linesdata_loading.py - examples/
complete/ , Shell, 2 linesexport.sh - examples/
complete/ , Shell, 2 linesnnet.sh - examples/
complete/ , Shell, 2 linesthreshold.sh - examples/
complete/ , Python, 15 linesthreshold_review.py - examples/
complete/ , Shell, 3 linestrain.sh - examples/
evaluate/ , Jupyter, 45 lineschristmas-plots.ipynb - examples/
evaluate/ , Jupyter, 61 linesevaluation.ipynb - examples/
index_generator.py , Python, 40 lines - examples/
pipeline/ , Python, 24 linescluster.py - examples/
pipeline/ , Python, 70 linescustom.py - examples/
pipeline/ , Python, 33 linesdeconvolve.py - examples/
pipeline/ , Python, 23 linesdetect.py - examples/
pipeline/ , Python, 15 linespreprocess.py - examples/
pipeline/ , Python, 30 linestemplates.py - examples/
preprocess_functions.py , Python, 96 lines - examples/
stability.py , Python, 58 lines - integration-test/
integration-test.sh , Shell, 23 lines - setup.py, Python, 130 lines
- src/
diptest/ , Python, 8 lines__init__.py - src/
diptest/ , C, 285 lines_dip.c - src/
diptest/ , C, 4,410 lines_diptest.c - src/
diptest/ , Python, 133 lines_interface.py - src/
gpu_bspline_interp/ , C++, 352 linesinterpSub.cpp - src/
gpu_bspline_interp/ , CUDA, 466 linesinterpSub_kernels.cu - src/
gpu_bspline_interp/ , C++, 278 linessaved/ spikeSub.cpp - src/
gpu_bspline_interp/ , CUDA, 224 linessaved/ spikeSub_kernels.cu - src/
gpu_bspline_interp/ , Python, 22 linessetup.py - src/
gpu_rowshift/ , C++, 93 linesrowshift.cpp - src/
gpu_rowshift/ , CUDA, 262 linesrowshift_kernels.cu - src/
gpu_rowshift/ , Python, 19 linessetup.py - src/
yass/ , Python, 71 lines__init__.py - src/
yass/ , Python, 47 linesarray.py - src/
yass/ , Python, 7 linesassets/ phy/ params.py - src/
yass/ , Python, 3 linesaugment/ __init__.py - src/
yass/ , Python, 218 linesaugment/ noise.py - src/
yass/ , Python, 124 linesaugment/ run.py - src/
yass/ , Python, 353 linesaugment/ util.py - src/
yass/ , Python, 13 linesbatch/ __init__.py - src/
yass/ , Python, 666 linesbatch/ batch.py - src/
yass/ , Python, 114 linesbatch/ buffer.py - src/
yass/ , Python, 273 linesbatch/ generator.py - src/
yass/ , Python, 175 linesbatch/ pipeline.py - src/
yass/ , Python, 404 linesbatch/ reader.py - src/
yass/ , Python, 98 linesbatch/ util.py - src/
yass/ , Python, 82 linesbatch/ vectorize.py - src/
yass/ , Python, 7 linescluster/ __init__.py - src/
yass/ , Python, 1,143 linescluster/ cluster.py - src/
yass/ , Python, 1,190 linescluster/ cluster_test.py - src/
yass/ , Python, 270 linescluster/ getptp.py - src/
yass/ , Python, 272 linescluster/ ptp_split.py - src/
yass/ , Python, 280 linescluster/ run.py - src/
yass/ , Python, 53 linescluster/ sharpen.py - src/
yass/ , Python, 946 linescluster/ util.py - src/
yass/ , Python, 284 linescommand_line.py - src/
yass/ , Python, 3 linesconfig/ __init__.py - src/
yass/ , Python, 316 linesconfig/ config.py - src/
yass/ , Python, 102 linesconfig/ validate.py - src/
yass/ , Python, 273 linescorrelograms_phy.py - src/
yass/ , Python, 3 linesdeconvolve/ __init__.py - src/
yass/ , Python, 276 linesdeconvolve/ deconv_exp_utils.py - src/
yass/ , Python, 1,450 linesdeconvolve/ deconvolve_old.py - src/
yass/ , Python, 785 linesdeconvolve/ match_pursuit.py - src/
yass/ , Python, 1,461 linesdeconvolve/ match_pursuit_gpu.py - src/
yass/ , Python, 1,461 linesdeconvolve/ match_pursuit_gpu_OLD.py - src/
yass/ , Python, 862 linesdeconvolve/ match_pursuit_gpu_new.py - src/
yass/ , Python, 1,700 linesdeconvolve/ match_pursuit_gpu_test.p y - src/
yass/ , Python, 1,700 linesdeconvolve/ match_pursuit_gpu_test_O LD.py - src/
yass/ , Python, 311 linesdeconvolve/ run.py - src/
yass/ , Python, 380 linesdeconvolve/ run_old.py - src/
yass/ , Python, 2,709 linesdeconvolve/ run_original.py - src/
yass/ , Python, 320 linesdeconvolve/ util.py - src/
yass/ , Python, 1,009 linesdeconvolve/ utils.py - src/
yass/ , Python, 1,049 linesdeconvolve/ utils_old.py - src/
yass/ , Python, 7 linesdetect/ __init__.py - src/
yass/ , Python, 52 linesdetect/ deduplication.py - src/
yass/ , Python, 199 linesdetect/ deduplication_old.py - src/
yass/ , Python, 105 linesdetect/ output.py - src/
yass/ , Python, 388 linesdetect/ run.py - src/
yass/ , Python, 9 linesempty.py - src/
yass/ , Python, 3 linesevaluate/ __init__.py - src/
yass/ , Python, 286 linesevaluate/ analyzer.py - src/
yass/ , Python, 653 linesevaluate/ stability.py - src/
yass/ , Python, 94 linesevaluate/ stability_filters.py - src/
yass/ , Python, 37 linesevaluate/ util.py - src/
yass/ , Python, 544 linesevaluate/ visualization.py - src/
yass/ , Python, 5 linesexplore/ __init__.py - src/
yass/ , Python, 767 linesexplore/ explorers.py - src/
yass/ , Python, 75 linesexplore/ receptive_fields.py - src/
yass/ , Python, 34 linesexplore/ table.py - src/
yass/ , Python, 3 linesexport/ __init__.py - src/
yass/ , Python, 176 linesexport/ generate.py - src/
yass/ , Python, 264 linesgeometry.py - src/
yass/ , Python, 9 linesmerge/ __init__.py - src/
yass/ , Python, 915 linesmerge/ merge.py - src/
yass/ , Python, 107 linesmerge/ notch.py - src/
yass/ , Python, 106 linesmerge/ run.py - src/
yass/ , Python, 186 linesmerge/ util.py - src/
yass/ , Python, 1,317 linesmfm.py - src/
yass/ , Python, 4 linesneuralnetwork/ __init__.py - src/
yass/ , Python, 100 linesneuralnetwork/ model_denoiser.py - src/
yass/ , Python, 259 linesneuralnetwork/ model_detector.py - src/
yass/ , Python, 273 linesnoise.py - src/
yass/ , Python, 500 linespd_split.py - src/
yass/ , Python, 3 linesphy/ __init__.py - src/
yass/ , Python, 416 linesphy/ run.py - src/
yass/ , Python, 1,564 linespipeline.py - src/
yass/ , Python, 351 linespipeline_blocks.py - src/
yass/ , Python, 215 linespipeline_nn_training.py - src/
yass/ , Python, 381 linespipeline_original.py - src/
yass/ , Python, 471 linespipeline_residual.py - src/
yass/ , Python, 8 linespostprocess/ __init__.py - src/
yass/ , Python, 133 linespostprocess/ collision.py - src/
yass/ , Python, 282 linespostprocess/ duplicate.py - src/
yass/ , Python, 73 linespostprocess/ duplicate_l2.py - src/
yass/ , Python, 55 linespostprocess/ duplicate_soft_assignmen t.py - src/
yass/ , Python, 14 linespostprocess/ high_fr.py - src/
yass/ , Python, 14 linespostprocess/ low_fr.py - src/
yass/ , Python, 235 linespostprocess/ mad.py - src/
yass/ , Python, 20 linespostprocess/ off_centered.py - src/
yass/ , Python, 55 linespostprocess/ remove_small_and_zero_un its.py - src/
yass/ , Python, 379 linespostprocess/ run.py - src/
yass/ , Python, 17 linespostprocess/ small_ptp.py - src/
yass/ , Python, 133 linespostprocess/ util.py - src/
yass/ , Python, 64 linespostprocess/ xcorr_peaks.py - src/
yass/ , Python, 7 linespreprocess/ __init__.py - src/
yass/ , Python, 172 linespreprocess/ run.py - src/
yass/ , Python, 241 linespreprocess/ util.py - src/
yass/ , Python, 243 linesreader.py - src/
yass/ , Python, 4 linesresidual/ __init__.py - src/
yass/ , Python, 135 linesresidual/ residual.py - src/
yass/ , Python, 1,119 linesresidual/ residual_gpu.py - src/
yass/ , Python, 225 linesresidual/ run.py - src/
yass/ , Python, 8 linesrf/ __init__.py - src/
yass/ , Python, 542 lines, 2 matchesrf/ run.py - src/
yass/ , Python, 117 linesrf/ sta_fit.py - src/
yass/ , Python, 303 linesrf/ util.py - src/
yass/ , Python, 4 linessoft_assignment/ __init__.py - src/
yass/ , Python, 223 linessoft_assignment/ noise.py - src/
yass/ , Python, 184 linessoft_assignment/ run.py - src/
yass/ , Python, 516 linessoft_assignment/ template.py - src/
yass/ , Python, 852 linestemplate.py - src/
yass/ , Python, 318 linestemplate_update.py - src/
yass/ , Python, 1 linethreshold/ __init__.py - src/
yass/ , Python, 25 linesthreshold/ detect.py - src/
yass/ , Python, 378 linesthreshold/ dimensionality_reduction .py - src/
yass/ , Python, 625 linesutil.py - src/
yass/ , Python, 8 linesvisual/ __init__.py - src/
yass/ , Python, 376 linesvisual/ barplots.py - src/
yass/ , Python, 338 linesvisual/ ptp_time.py - src/
yass/ , Python, 2,019 linesvisual/ run.py - src/
yass/ , Python, 72 linesvisual/ soft_assignment.py - src/
yass/ , Python, 373 linesvisual/ util.py - src/
yass/ , Python, 429 linesyass_gui.py - tests/
conftest.py , Python, 127 lines - tests/
performance/ , Python, 104 linestest_nn_output.py - tests/
performance/ , Python, 104 linestest_threshold_output.py - tests/
reference/ , Python, 48 linestest_detect.py - tests/
reference/ , Python, 39 linestest_templates.py - tests/
unit/ , Python, 80 linesbatch/ processor.py - tests/
unit/ , Python, 45 linesbatch/ test_batch_operations.py - tests/
unit/ , Python, 133 linesbatch/ test_binary_reader.py - tests/
unit/ , Python, 181 linesbatch/ test_buffer_generator.py - tests/
unit/ , Python, 78 linesbatch/ test_reader.py - tests/
unit/ , Python, 266 linesevaluation/ retinal_evaluation.py - tests/
unit/ , Python, 105 linestest_augment.py - tests/
unit/ , Python, 80 linestest_cluster.py - tests/
unit/ , Python, 18 linestest_config.py - tests/
unit/ , Python, 34 linestest_deconvolution.py - tests/
unit/ , Python, 43 linestest_detect.py - tests/
unit/ , Python, 6 linestest_diptest.py - tests/
unit/ , Python, 19 linestest_explorer.py - tests/
unit/ , Python, 58 linestest_geometry.py - tests/
unit/ , Python, 309 linestest_neuralnet.py - tests/
unit/ , Python, 30 linestest_noise.py - tests/
unit/ , Python, 23 linestest_pipeline.py - tests/
unit/ , Python, 82 linestest_preprocess.py - tests/
unit/ , Python, 46 linestest_util.py - tests/
util.py , Python, 67 lines - LICENSE, License, 201 lines
- README.md, Text, 61 lines
- README.rst, Text, 49 lines
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 227 scripts, each with its path and the digest of its content;
- 3 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
Datasets cited
- doi:10.48324/
dandi.001677/ , at DANDI; found in the text, “Key resources table”0.251202.2310 - neuromorpho.org/
dablefiles/ , at neuromorpho.org; found in the text, “Key resources table”bohlen_rudzite
Data and code availability
• Traced retinal ganglion cell morphologies will be deposited at Neuromorpho.org. Accession information is in the key resources table. • Example MEA data will be deposited at DANDI Archive upon publication. Accession information is in the key resources table. Additional data are available upon request from the lead contact. • Example code for identifying ReaChR-positive neurons and plotting EIs over micrographs is available at https://
Reproduced under the paper's license (CC BY-NC), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 30 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 13 authors, 7 keywords, 6 MeSH terms, 3 funders, 95 references, 7 RRIDs.
Cite
This paper
Bohlen, M. O., Rudzite, A. M., Daw, T. B., Kuczewski, G. M., Spiro, E., Hammond, C., Rogers, D. R., Gallego-Ortega, A., Manookin, M. B., Roy, S., Ritola, K., Sommer, M. A., & Field, G. D. (2026). Projection targeting with phototagging to study the structure and function of retinal ganglion cells. Cell reports methods, 6(3), 101308. https://
BibTeX
@article{bohlen2026proje
author = {Bohlen, Martin O. and Rudzite, Andra M. and Daw, Tierney B. and Kuczewski, Genevieve M. and Spiro, Ergi and Hammond, Cassie and Rogers, Darienne R. and Gallego-Ortega, Alejandro and Manookin, Michael B. and Roy, Suva and Ritola, Kimberly and Sommer, Marc A. and Field, Greg D.},
title = {{Projection targeting with phototagging to study the structure and function of retinal ganglion cells}},
journal = {Cell reports methods},
year = {2026},
month = mar,
volume = {6},
number = {3},
pages = {101308},
publisher = {Elsevier},
issn = {2667-2375},
doi = {10.1016/
url = {https://
pmid = {41791371},
pmcid = {PMC13030990}
}
RIS
TY - JOUR
AU - Bohlen, Martin O.
AU - Rudzite, Andra M.
AU - Daw, Tierney B.
AU - Kuczewski, Genevieve M.
AU - Spiro, Ergi
AU - Hammond, Cassie
AU - Rogers, Darienne R.
AU - Gallego-Ortega, Alejandro
AU - Manookin, Michael B.
AU - Roy, Suva
AU - Ritola, Kimberly
AU - Sommer, Marc A.
AU - Field, Greg D.
TI - Projection targeting with phototagging to study the structure and function of retinal ganglion cells
T2 - Cell reports methods
J2 - Cell Rep Methods
PY - 2026
DA - 2026/
VL - 6
IS - 3
SP - 101308
SN - 2667-2375
PB - Elsevier
DO - 10.1016/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1016/
"type": "article-journal",
"title": "Projection targeting with phototagging to study the structure and function of retinal ganglion cells",
"container-title": "Cell reports methods",
"author": [
{
"family": "Bohlen",
"given": "Martin O."
},
{
"family": "Rudzite",
"given": "Andra M."
},
{
"family": "Daw",
"given": "Tierney B."
},
{
"family": "Kuczewski",
"given": "Genevieve M."
},
{
"family": "Spiro",
"given": "Ergi"
},
{
"family": "Hammond",
"given": "Cassie"
},
{
"family": "Rogers",
"given": "Darienne R."
},
{
"family": "Gallego-Ortega",
"given": "Alejandro"
},
{
"family": "Manookin",
"given": "Michael B."
},
{
"family": "Roy",
"given": "Suva"
},
{
"family": "Ritola",
"given": "Kimberly"
},
{
"family": "Sommer",
"given": "Marc A."
},
{
"family": "Field",
"given": "Greg D."
}
],
"container-title-short":
"volume": "6",
"issue": "3",
"page": "101308",
"DOI": "10.1016/
"PMID": "41791371",
"PMCID": "PMC13030990",
"ISSN": "2667-2375",
"publisher": "Elsevier",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
5
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.7554/elife.110588 [code]
- Opening the black box toward a modular approach to spike sorting.Journal: eLifeIn common: TensorFlow, NetworkX, h5py, 5 other tools, extracellular electrophysiology (units, LFP), 2 references
- [2] doi:10.1038/s41593-026-02232-0 [code]
- Entorhinal cortex represents task-relevant remote locations independently of CA1.Journal: Nature neuroscienceIn common: NetworkX, h5py, statsmodels, 6 other tools, systems, 1 reference
- [3] doi:10.3389/fnsys.2026.1822122 [code]
- Convergence-divergence circuits for multimodal integration of innate and learned opponent valences.Journal: Frontiers in systems neuroscienceIn common: TensorFlow, NetworkX, h5py, 5 other tools, systems, 1 reference
- [4] doi:10.1371/journal.pbio.3003831 [code]
- Disinhibitory signaling enables flexible coding of top-down information in cortical networks.Journal: PLoS biologyIn common: TensorFlow, NetworkX, h5py, 6 other tools, systems
- [5] doi:10.1016/j.isci.2026.117375 [code]
- Motor priming is associated with widespread recruitment into neural ensembles and more rapid ensemble transitions.Journal: iScienceIn common: NetworkX, h5py, statsmodels, 6 other tools, systems
- [6] doi:10.1093/nar/gkag706 [code]
- scDifformer: diffusion-based post-training for virtual cell modeling across large-scale single-cell data.Journal: Nucleic acids researchIn common: TensorFlow, NetworkX, h5py, 6 other tools
- [7] doi:10.1038/s42003-026-10957-8 [code]
- Brain defence by the extracellular matrix protein Cochlin.Journal: Communications biologyIn common: TensorFlow, NetworkX, statsmodels, 6 other tools
- [8] doi:10.1016/j.isci.2026.117088 [code]
- Spatial biases in visual feature representation of mouse dorsal lateral geniculate nucleus boutons.Journal: iScienceIn common: Statistics and Machine Learning Toolbox, systems, 5 references
- [9] doi:10.1038/s41467-026-72152-x [code]
- Centralized brain networks controlling antennal grooming coordination.Journal: Nature communicationsIn common: TensorFlow, NetworkX, h5py, 5 other tools, systems
- [10] doi:10.1038/s41467-026-75455-1 [code]
- Shared latent representations of speech production for cross-patient speech decoding.Journal: Nature communicationsIn common: TensorFlow, h5py, statsmodels, 6 other tools
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 3 repositories of the authors' code, each at its verified commit and with its license, 227 scripts, and 3 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:cf026c44921920fd…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
