Predicting Mortality of ICU Patients: The PhysioNet/Computing in Cardiology Challenge 2012 1.0.0

File: <base>/sources/mmacas_at_seznam.cz/entry10/sofa_score.m (4,610 bytes)
function [SOFA_SCORE]=sofa_score(varargin)
% [SOFA_SCORE]=sofa_score(tm,category,val,truncated)
%
% Calculates SOFA scores. Variables are:
%
%tm      - (Nx1 Cell Array) Cell array containing time of measurement
%category- (Nx1 Cell Array) Cell array containing type (category)
%           measurement
%value   - (Nx1 Cell Array) Cell array containing value of measurement
%truncated - (Logical) Optional flag, if true, will attempt to calculate
%             "truncated" SOFA even if some of the input variables are
%             missing. Default is 0 (false) .
% SAP_SCORE - (Scalar) Value between 0 and 56 representing the severity of
%             the patient's status (higher scores are worse).  A NaN
%             value is returned along with a warning message if the SOFA
%             score cannot be calculated.
%
% Jakub Kuzilek, 2012
%
% Based on Ikaro Silva saps_score function.
%
% Version 1.0

truncated=0;
inputs={'tm','category','val','truncated'};
for n=1:nargin
    if(~isempty(varargin{n}))
        eval([inputs{n} '=varargin{n};'])
    end
end

if iscell(val)
    for m = 1:length(val)
        val{m} = str2num(val{m});
    end
    val=cell2mat(val);
end

%SOFA variable names
SOFA={{'NIMAP'},{'PaO2','FiO2','MechVent'},{'Creatinine'},...
    {'Bilirubin'},{'Platelets'},{'GCS'}};

MX_SOFA=56; %Max SOFA value

%Convert SOFA info into tables [min range, max range, SOFA score;...]
%Also convert the units in the table to match the units of the data
MechVent=49; %Equivalent to a RespRate that will yield a SOFA value of 3
PaO2 = [401,10000,0;301,400,1;201,300,2;101,200,3;0,100,4];
Platelets = [151,10000,0;101,150,1;51,100,2;21,50,3;0,20,4];
Bilirubin = [0,1.2,0;1.21,1.9,1;2,5.9,2;6,11.9,3;12,1000,4];
NIMAP = [0,70,1];
GCS=[14.9,15,0;13,14,1;10,12,2;6,9,3;0,5,4];
Creatinine = [0,1.19,0;1.2,1.9,1;2,3.4,2;3.5,4.9,3;5,2000,4];


%Only use data for the first 32 hrs (standard SOFA)
tm=cell2mat(tm);
fr_data=find(str2num(tm(:,1:2))<48);
val=val(fr_data);
tm=tm(fr_data);
category=category(fr_data);

%Loop through all SOFA variables, adding risk points to SOFA_SCORE according to their tables
SOFA_SCORE=NaN;
for s=1:length(SOFA)
    %Get data for the selected category only (If more than one name exist for the variables, merge data)
    sofa_var=SOFA{s};
    sig_ind= val.*0;
    eval(['table=' regexprep(sofa_var{1},' ','_') ';'])
    for i=1:length(sofa_var)
        sig_ind=sig_ind | strcmp(sofa_var(i),category);
    end
    tmp_data=val(sig_ind);
    
    if(strcmp(sofa_var{1},'PaO2'))
        %For Respiration, check Mechanical Ventilation flag
        %If subject is on ventillation, this is equivalent to having a
        %RespRate that will yield a SOFA value of 3
        tmp_category=category(sig_ind);
        mech_vent_ind=find(strcmp(sofa_var(2),tmp_category)==1);
        if(~isempty(mech_vent_ind) && any(mech_vent_ind))
            tmp_data=MechVent;
        else
           tmp_category=category(sig_ind);
           indx = find(sig_ind);
           FiO2_ind=find(strcmp(sofa_var(3),tmp_category)==1);
           PaO2_ind=find(strcmp(sofa_var(1),tmp_category)==1);
           for m = 1:length(PaO2_ind)
                for n = 1:length(FiO2_ind)
                    tmp_data(end+1) = val(indx(PaO2_ind(m)))/(val(indx(FiO2_ind(n)))+eps);
                end
            end
            tmp_data = tmp_data';
        end
    end
    
    
    %Set out of bound values to NaN
    tmp_data(tmp_data < min(table(:,1)))=NaN;
    tmp_data(tmp_data > max(table(:,2)))=NaN;
    %Get the lowest and highest values for the measured variable
    if(all(isnan(tmp_data)) || isempty(tmp_data))
        if(~truncated)
            warning(['No SOFA score for variable ' sofa_var{:} '... exiting.'])
            SOFA_SCORE=NaN;
            break
        else
            warning(['No variable ' sofa_var{:} '... attempting truncated SOFA.'])
        end
    else
        mn=nanmin(tmp_data);
        mn_sofa_ind=find( ( mn(1) >= table(:,1) & mn(1) <= table(:,2) ) ==1);
        mn_sofa_val=table(mn_sofa_ind,3);
        if isempty(mn_sofa_val), mn_sofa_val = 0; end
        mx=nanmax(tmp_data);
        mx_sofa_ind=find( ( mx(1) >= table(:,1) & mx(1) <= table(:,2) ) ==1);
        mx_sofa_val=table(mx_sofa_ind,3);
        if isempty(mx_sofa_val), mx_sofa_val = 0; end
        %Add worst case scenario to SOFA SCORE
        if(isnan(SOFA_SCORE))
            SOFA_SCORE= nanmax(mn_sofa_val,mx_sofa_val);
        else
            SOFA_SCORE= SOFA_SCORE + nanmax(mn_sofa_val,mx_sofa_val);
        end
    end
end

if isnan(SOFA_SCORE), SOFA_SCORE = MX_SOFA; end % if all data is missing