COREM: configurable retina simulator (Martínez-Cañada et al., 2016)

 Download zip file 
Help downloading and running models
Accession:225095
COREM is a configurable simulator for retina modeling that has been implemented within the framework of the Human Brain Project (HBP). The software platform can be interfaced with neural simulators (e.g., NEST) to connect with models of higher visual areas and with the Neurorobotics Platform of the HBP. The code is implemented in C++ and computations of spatiotemporal equations are optimized by means of recursive filtering techniques and multithreading. Most retina simulators are more focused on fitting specific retina functions. By contrast, the versatility of COREM allows the configuration of different retina models using a set of basic retina computational primitives. We implemented a series of retina models by combining these primitives to characterize some of the best-known phenomena observed in the retina: adaptation to the mean light intensity and temporal contrast, and differential motion sensitivity. The code has been extensively tested in Linux. The software can be also adapted to Mac OS. Installation instructions as well as the user manual can be found in the Github repository: https://github.com/pablomc88/COREM
Reference:
1 . Martínez-Cañada P, Morillas C, Pino B, Ros E, Pelayo F (2016) A Computational Framework for Realistic Retina Modeling. Int J Neural Syst 26:1650030 [PubMed]
Citations  Citation Browser
Model Information (Click on a link to find other models with that property)
Model Type: Realistic Network;
Brain Region(s)/Organism: Retina;
Cell Type(s): Retina bipolar GLU cell; Retina photoreceptor cone GLU cell; Retina ganglion GLU cell; Retina amacrine cell; Retina horizontal cell;
Channel(s):
Gap Junctions:
Receptor(s):
Gene(s):
Transmitter(s):
Simulation Environment: C or C++ program;
Model Concept(s): Vision;
Implementer(s): Martínez-Cañada, Pablo [pablomc at ugr.es]; Carrillo, Richard R. [rcarrillo at atc.ugr.es];
Search NeuronDB for information about:  Retina ganglion GLU cell; Retina photoreceptor cone GLU cell; Retina bipolar GLU cell;
%INRLOAD loads an INR file
%   This function allows the user to partially read a INR file in a matrix
%   which is returned by the function.
%   INRLOAD filename load the whole INR filename file.
%   If additional arguments are specified, a specific part of the file is
%   loaded:
%   INRLOAD filename x_ini x_end only reads a column from all source images
%   (from column x_ini to column x_end). First column is zero.
%   INRLOAD filename x_ini x_end y_ini y_end only reads a square from 
%   all source images (from column x_ini to column x_end and from row x_ini
%   to row x_end).
%   INRLOAD filename x_ini x_end y_ini y_end z_ini z_end only reads a
%   square from a specific interval of source images (from image z_ini to
%   image z_end).
%   INRLOAD filename x_ini x_end y_ini y_end z_ini z_end v_ini v_end
%   only reads a square from a specific interval of source images of a
%   specific interval of pixel dimensions (from dim. v_ini to dim. v_end).
%   (in case a pixel is defined by a vector).
%   Inf can be specified as coordinate value to designate the last
%   coordinate in that dimension.
%   im=INRLOAD returns a matrix im whose dimenions are size(im)=[X Y Z V].
%   Take into account that when plotting images Matlab increases the first
%   matrix dimension to plot a column. That is, the first matrix coordinate is
%   the image height and the second one is the image width. Moreover, color
%   channel dimension (V) is expected to be the third dimension. So, in order
%   to show a grayscaled frame you first have to traspose it. Alternatively you can
%   permute the dimensions of the whole INRLOAD output: permute(im,[2 1 4 3])
%   [im,dl]=INRLOAD also returns a matrix dl of dimensions 2 x 4 in which
%   each column represents the coordinate of the first and the last element
%   loaded for each dimension.
%
%   Usage example:
%   a=inrload('sequence.inr', 0,Inf, 0,Inf, 0,99);
%   it loads the first 100 complete frames from file sequence.inr.
%
%   See also INRWRITE.

%   Copyright (C) 2016 by Richard R. Carrillo 
%   $Revision: 1.3 $  $Date: 1/11/2016 $

%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 3 of the License, or
%   (at your option) any later version.
function [voxels, dim_limits]=inrload(varargin)

nargs=nargin;
voxels=[]; % Defualt return values
dim_limits=[];

if nargs ~= 1 && nargs ~= 3 && nargs ~= 5 && nargs ~= 7 && nargs ~= 9
      disp('You must specify 1, 3, 5, 7 or 9 arguments');
      disp('inrload filename [x_ini x_end [y_ini y_end [z_ini z_end [v_ini v_end]]]]');
      disp('All arguments must numeric except the first one')
      disp('type: help inrload for more help');
else
    filename = varargin{1};

    fid = fopen(filename,'rb');
    if fid ~= -1 % Successfully opened
        header=inr_read_header(fid);
        if isempty(header.read_error) % Header successfully read
            % Display file data dimensions
            disp(['Dimensions of data in file (X,Y,Z,V): ' num2str(header.n_dims(1)) sprintf(' x %i', header.n_dims(2:end))])

            Dim_names='XYZV';
            N_dims=length(Dim_names);

            % If fn argument dimension data types are strings, convert to doubles
            % The type may change denpending on how the fn is executed
            for arg_ind=2:nargs
                if isa(varargin{arg_ind},'char')
                    vargs_num(arg_ind-1) = str2double(varargin{arg_ind});
                else
                    vargs_num(arg_ind-1) = varargin{arg_ind};
                end
            end

            user_dim_size=[zeros(N_dims,1) ones(N_dims,1)*Inf]; % Default dimension coordinates of data to load: load all data: 0 -> Inf
            % Replace dim_size values with the dimension limits specified by user
            for arg_ind=1:(nargs-1)/2 % Parse input dimension coordenate intervals
                user_dim_size(arg_ind,:) = [vargs_num(arg_ind*2 - 1) vargs_num(arg_ind*2)];
            end
            
            % If only 1 argument has been specified or [0,Inf] interval has
            % been specified for all dimension, load the file completelly
            if nargs == 1 || (all(user_dim_size(:,1)==0) && all(isinf(user_dim_size(:,2))))
                disp(['loading file: ' filename ' completely']);
                % Read the whole file at once to speed up the loading process
                % Use the pixel data type specified in file header to read
                % data from file and create voxels matrix with the same
                % format (*)
                voxels=fread(fid, Inf, ['*' header.matlab_data_type]);
                disp(' 100%');
                if numel(voxels)==prod(header.n_dims)
                    inr_dim_encoding=[header.n_dims(4) header.n_dims(1:3)]; % color hannels (V dim.) are encoded together
                    voxels=reshape(voxels, inr_dim_encoding); % convert vector obtained from fread into a matrix
                    voxels=permute(voxels,[2 3 4 1]); % Place the color channel dimension in the end as in CImg and INR header
                    %voxels=permute(voxels,[2 1 3 4]); % Permute X and Y dimensions to show images correctly with matlab image(voxels(:,:,1,1))
                    dim_limits = [zeros(1,N_dims) ; header.n_dims-1];
                else
                    disp('Error: Number of voxel values in file does not correspond with dimension sizes in header')
                end
            else % only a part of the file must be loaded
                dim_max_auto=isinf(user_dim_size(:,2)); % Dimensions in which the user want to load up to the last element
                user_dim_size(dim_max_auto,2)=header.n_dims(dim_max_auto)-1;
                dim_min_auto=isinf(user_dim_size(:,1)); % Dimensions in which the user want to load from the last element (that is, only the last element)
                user_dim_size(dim_min_auto,1)=header.n_dims(dim_min_auto)-1;
                
                stat_msg=['Partially loading activity file ' filename ': '];
                for dim_ind=1:N_dims
                    stat_msg = [stat_msg Dim_names(dim_ind) '=[' num2str(user_dim_size(dim_ind,1)) ', ' num2str(user_dim_size(dim_ind,2)) '] '];
                end
                disp(stat_msg);
                disp(' 00%')
                % Check that input argument values are compatible with
                % dimensions of data in the specified file
                if all(user_dim_size >= 0)
                    if all(user_dim_size(:,1) < header.n_dims') && all(user_dim_size(:,2) < header.n_dims')
                        % Load binary (pixel) data from file

                        n_z_dim_end=(1+user_dim_size(3,2)-user_dim_size(3,1));
                        % Allocate matrix space (just for speed efficiency when adding values).
                        % Output matrix will has dimensions X,Y,Z,V (accoring to INR header field order and Cimg coordinates),
                        % that is voxels(width, height, frames, color_channels), however this is not the standard Matlab
                        % represetation for images/videos. Matlab expexts voxels(height, width, color_channels, frames),
                        % So, a matrix dimension permutation will be required after using this fn in order to use
                        % Matlab functions to show, play, etc the loaded data.
                        % But firstly we load frames as they are stored in file that is: V,X,Y,Z, so we allocate a matrix
                        % with these dimensions. Before exiting this fn we will permute dimensions to obtain CImg
                        % coordinates ordering in voxels matrix.
                        voxels=zeros(user_dim_size(4,2)-user_dim_size(4,1)+1, user_dim_size(1,2)-user_dim_size(1,1)+1, 1+user_dim_size(2,2)-user_dim_size(2,1), n_z_dim_end, header.matlab_data_type);
                        progress_end = n_z_dim_end; % For percentage display
                        process_update_period = ceil(progress_end / 100);

                        % Move file pointer to the first required data
                        % in Z dim, that is, to the first frame to
                        % load, which size is X*Y*V: prod(header.n_dims([1:2 4])) 
                        fseek(fid, user_dim_size(3,1) * (header.data_size/8) * prod(header.n_dims([1:2 4])), 'cof');                            
                        for n_z_dim=1:n_z_dim_end
                            % For the remaining dimensions (X, Y and V) we load all the elements
                            % since it is normally faster than moving the file pointer many times
                            im_voxels=fread(fid, prod(header.n_dims([1:2 4])), ['*' header.matlab_data_type]); % Read a whole frame each time
                            % In an INR file color channels of the first
                            % pixel are stored first, then pixel of the
                            % first row and then the first frame, so
                            % dimensions: 4, 1, 2 and 3
                            im_voxels=reshape(im_voxels, header.n_dims([4 1:2]));
                            % Store the required part of the read frame in output matrix
                            voxels(:,:,:,n_z_dim) = im_voxels(1+(user_dim_size(4,1):user_dim_size(4,2)), 1+(user_dim_size(1,1):user_dim_size(1,2)), 1+(user_dim_size(2,1):user_dim_size(2,2)));
                            % Display progress percentage
                            current_progress = n_z_dim;
                            % we do not want to print the percentage so many times that we slow down the loading process
                            if mod(current_progress,process_update_period)==0 % Always true for progress_end < 100 since progress_end would be 1
                               fprintf(1,'\b\b\b\b% 3.f%%',100*current_progress/progress_end);
                            end
                        end
                        voxels=permute(voxels,[2 3 4 1]); % Set color channel as the last matrix dimension as in CImg and INR header
                        %voxels=permute(voxels,[2 1 3 4]); % Permute X and Y dimensions to show images correctly with matlab image(voxels(:,:,1,1))
                        dim_limits = user_dim_size'; % Return first and last coord. of loaded data
                        fprintf(1,'\b\b\b\b100%%\n');
                    else
                        disp('Error: all specified dimension limits must be lower than the dimensions in the specified file')
                    end
                    
                else
                    disp('Error: all specified dimension limits must be positive or zero')
                end
                
            end
            if header.change_endianness
                voxels=swapbytes(voxels); % File endianness and computer endianness are different, so data bytes must be swapped
            end
        else
            disp(['Error reading file header: ' header.read_error])
        end
        fclose(fid);
    else
        disp(['Cannot open input file: ' varargin{1}]);
    end    
end

% Load INR file header and returns a struct containing the header fields
function header=inr_read_header(fid)
INR_header_ID='#INRIMAGE-4#';
INR_header_end='##}';

header=struct('read_error',''); % field read_ok will specify the obtained error or '' if the file header was successfully read
if fid ~= -1 % Valid file identifier
    header_id=fscanf(fid,'%[^{]', 1); % Read format ID string
    if strncmp(INR_header_ID,header_id,length(header_id)) == 1
        fscanf(fid,' { \n', 1); % Skip block start and new line
        end_header=false;
        while ~end_header
            header_line = fgetl(fid);
            if ischar(header_line) % If a valid file line has been read:
                if strcmp(INR_header_end, header_line) == 0 % If it is not the header end:
                    [param_name,param_name_read]=sscanf(header_line,'%[^=]=',1);
                    if param_name_read==1
                        param_value=sscanf(header_line,'%*[^=]=%[^\n]',1); % Skip param name and '=' and get param value
                        param_name=strtrim(param_name); % Remove leading and trailing space and tab character
                        param_value=strtrim(param_value);
                        switch param_name
                            case 'XDIM' % Length in X dimension
                                header.n_dims(1)=str2num(param_value);
                            case 'YDIM'
                                header.n_dims(2)=str2num(param_value);
                            case 'ZDIM'
                                header.n_dims(3)=str2num(param_value);
                            case 'VDIM'
                                header.n_dims(4)=str2num(param_value);
                            case 'VX'
                                header.voxel_size(1)=str2num(param_value);
                            case 'VY'
                                header.voxel_size(2)=str2num(param_value);
                            case 'VZ'
                                header.voxel_size(3)=str2num(param_value);
                            case 'TYPE'
                                header.data_type=param_value;
                            case 'PIXSIZE'
                                header.data_size=sscanf(param_value,' %u',1);
                            case 'SCALE'
                                header.scale=param_value;
                            case 'CPU'
                                header.cpu=param_value;
                            otherwise
                                if ~isempty(param_name) || ~isempty(param_value) % The line has a parameter name not recognized
                                    warning(['Unexpected header parameter: ' param_name '=' param_value])
                                end
                        end
                    end
                else
                    end_header=true; % header end found: exit loop
                end
            else
                end_header=true; % file end found: exit
            end
        end
    else
        header.read_error='The format of specified file is unknown';
    end
    if isempty(header.read_error) % Header successfully read
        % Translate INR data type name into Matlab data type name
        if isfield(header, 'data_type') && isfield(header, 'data_size')
            data_type_inr=[header.data_type '_' num2str(header.data_size)]; % Compose a data type name just to be used in switch statement
            switch lower(data_type_inr)
                case 'unsigned fixed_8'
                    header.matlab_data_type='uint8';
                case 'signed fixed_8'
                    header.matlab_data_type='int8';
                case 'unsigned fixed_16'
                    header.matlab_data_type='uint16';
                case 'signed fixed_16'
                    header.matlab_data_type='int16';
                case 'unsigned fixed_32'
                    header.matlab_data_type='uint32';
                case 'signed fixed_32'
                    header.matlab_data_type='int32';
                case 'unsigned fixed_64'
                    header.matlab_data_type='uint64';
                case 'signed fixed_64'
                    header.matlab_data_type='int64';
                case {'float_32','double_32'}
                    header.matlab_data_type='single';
                case {'float_64','double_64'}
                    header.matlab_data_type='double';
                otherwise
                    header.read_error='Incompatible data type specified in file header';
            end
            if isempty(header.read_error) % Data type successfully obtained
                if isfield(header, 'cpu') % Endianness specified in header
                    [~,~,local_endianness]=computer;
                    switch header.cpu
                        case {'decm','alpha','pc'}
                            header.endianness='L';
                        case {'sun','sgi'}
                            header.endianness='B';
                        otherwise
                            header.read_error='Unknown CPU type specified in header';
                    end
                    if isfield(header, 'endianness')
                        header.change_endianness=(header.endianness~=local_endianness);
                    end
                end
            end
        end
    end
else
    header.read_error='Invalid file identifier';
end