program define compart,rclass
version 8
syntax varlist [if] [in] [fweight iweight] [,part(numlist) Matrix(string) type(string) DETails noSTANDardized VARiables SQUare]

preserve
unab varlist:`varlist'
di "`varlist'"
tokenize `varlist'
marksample touse
local nbvar:word count `varlist'
qui count
local nbind=r(N)
tempname p
qui gen `p'=1
qui su `p' [`weight'`exp'] if `touse'
local nbind=r(N)
if "`square'"=="" {
   local quad=1
}
else {
   local quad=2
}

if "`type'"!=""&"`type'"!="polychoric" {
   di in red "The type of the matrix is not authorized. Please correct your {hi:type} option."
   error 198
}
if "`type'"!=""&"`matrix'"!="" {
   di in red "You cannot define in the same time the {hi:type} and the {hi:matrix} options"
   error 198
}

/* DEFINITION OF THE PARTITION OF THE VARIABLES*/

local newpart
foreach i in `part' {
    if `i'!=0 {
       local newpart `newpart' `i'
    }
}
local part `newpart'
local meme=0
local diff=0
local nbpart:word count `part'
forvalues i=1/`nbpart' {
    local iti:word `i' of `part'
    local meme=`meme'+`iti'*(`iti'-1)/2
    forvalues j=`=`i'+1'/`nbpart' {
       local itj:word `j' of `part'
       local diff=`diff'+`iti'*`itj'
    }
}

local perc=`meme'/(`meme'+`diff')
di "meme: `meme' ; diff: `diff' ; perc: `perc'"


local test=0
local last0=0
forvalues i=1/`nbpart' {
   local first`i'=`last`=`i'-1''+1
   local size`i':word `i' of `part'
   local last`i'=`first`i''+`size`i''-1
   local test=`test'+`size`i''
   local list`i'
   forvalues j=`first`i''/`last`i'' {
      local list`i' `list`i'' ``j''
   }
}
if `test'!=`nbvar' {
   di in red "{p}The described partition of the variables is composed of a number of variables different of the number of variables of varlist.{p_end}"
   exit 198
}

/* BY DEFAULT, STANDARDIZATION*/
if "`standardized'"=="" {
   forvalues i=1/`nbvar' {
      qui su ``i'' [`weight'`exp']
      qui replace ``i''=(``i''-r(mean))/r(sd)
   }
}

tempname Cov W
if "`matrix'"==""&"`type'"!="polychoric" {
   /* COVARIANCE OR CORRELATION MATRIX*/
   qui matrix accum `Cov'=`varlist' [`weight'`exp'],nocons dev
   qui matrix `Cov'=`Cov'/(`nbind'-1)
}
else if "`type'"=="polychoric" {
   qui polychoric `varlist'
   qui matrix `Cov'=r(R)
}
else {
   qui matrix `Cov'=`matrix'
}
 /* WE SAVE THE MATRIX AND WE COMPUTE THE AVERAGE COVARIANCE */
qui matrix `W'=`Cov'
local sum=0
forvalues i=1/`nbvar' {
   forvalues j=`=`i'+1'/`nbvar' {
      local sum=`sum'+ `W'[`i',`j']^`quad'
   }
}

/* WE SAVE THE DATA AND WE COMPUTES THE USED PERCENTILES OF THE COVARIANCE*/

tempfile compartfile
qui save `compartfile',replace

drop _all
set obs `=`nbvar'*(`nbvar'-1)'
local n=1
qui gen i=.
qui gen j=.
qui gen corr=.
forvalues i=1/`nbvar' {
   forvalues j=`=`i'+1'/`nbvar' {
       qui replace i=`i' in `n'
       qui replace j=`j' in `n'
       qui replace corr=`W'[`i',`j']^`quad' in `n'
       local ++n
   }
}
matrix list `W'
su corr
sort corr
centile corr,centile(`=100-`perc'*100')
local centile=r(c_1)
if `diff'!=0 {
   local perc2=(`meme'+1)/(`meme'+`diff')
   centile corr,centile(`=100-`perc2'*100')
   local centile2=r(c_1)
   local centile=(`centile'+`centile2')/2
}
qui use `compartfile',clear

/***************************************************/

if `nbpart'==1 {
   local mean=0
*   local mean=(2*`sum')/(`nbvar'*(`nbvar'-1))
}
else {
   local mean=(2*`sum')/(`nbvar'*(`nbvar'-1))
   local mean=0
   *local mean=`centile'
}

/*THE MATRIX IS CENTERED*/

forvalues i=1/`nbvar' {
   matrix `W'[`i',`i']=0
   forvalues j=`=`i'+1'/`nbvar' {
      matrix `W'[`i',`j']=(`W'[`i',`j']^`quad'-`mean')
      matrix `W'[`j',`i']=`W'[`i',`j']
   }
}

/*WE COMPUTE THE INDEX D*/
local C=0
local C1=0
local C2=0
local minrho=2
local summeme=0
local sumdiff=0
if "`square'"!="" {
   local maxrho=0
}
else {
   local maxrho=-2
}
*set trace on
forvalues i=1/`nbpart' {
   forvalues j=1/`nbpart' {
       forvalues k=`first`i''/`last`i'' {
           forvalues l=`first`j''/`last`j'' {
               if `i'!=`j' {
                  if `k'>`l' {
                     local sumdiff=`sumdiff'+`Cov'[`k',`l']
                  }
                  if (`Cov'[`k',`l'])^`quad'>(`maxrho')^`quad' {
                      local maxrho=(`Cov'[`k',`l'])
                  }
                  matrix `W'[`k',`l']=-(`W'[`k',`l'])
               }
               else if (`Cov'[`k',`l'])^`quad'<(`minrho')^`quad'&`k'!=`l' {
                  local minrho=`Cov'[`k',`l']
               }
               if `i'==`j'&`k'>`l' {
                  local summeme=`summeme'+`Cov'[`k',`l']
               }
               local C=`C'+`W'[`k',`l']
               local C1=`C1'+abs(`W'[`k',`l'])
               if `W'[`k',`l']>+0 {
                  local ++C2
               }
          }
      }
   }
}
if `meme'!=0 {
   local summeme=`summeme'/`meme'
}
if `diff'!=0 {
    local sumdiff=`sumdiff'/`diff'
}
local diffsum=`summeme'-`sumdiff'
set trace off
di "Summeme: `summeme' ; Sumdiff: `sumdiff'"

local minrho=(`minrho')^(`quad')
local maxrho=(`maxrho')^(`quad')

local C=sign(`C')*(abs(`C'))^(1/`quad')/(`nbvar'*(`nbvar'-1))+`mean'
local C1=(`C1')^(1/`quad')/(`nbvar'*(`nbvar'-1))
local C2=(`C2')/(`nbvar'*(`nbvar'-1))*100
return local Pcov=`=`C'/`C1''
return local Pel=`=`C2'/100'

if `nbpart'==1 {
    local C=`C'*(`nbvar'+1)/`nbvar'
}

*di "C:" `C' " C1: " `C1' " C2: " `C2'
if `nbpart'==1 {
   local maxrho=0
}
if `nbpart'==`nbvar' {
   local minrho=0
}
di " C=(`meme'*`minrho'-`diff'*`maxrho')/(`meme'+`diff')"
local C=(`meme'*`minrho'-`diff'*`maxrho')/(`meme'+`diff')
di in green "{hline 80}"
di in green "Number of individuals: " _col(71) in ye %8.0f `nbind'
di in green "Number of variables: " _col(71) in ye %8.0f `nbvar'
di in green "COMPART index: " _col(71) in ye %8.6f `C'
di in green "Proportion of the covariances explained by the COMPART index: " _col(73) in ye %6.2f `=abs(`C')/`C1'*100' "%"
di in green "Proportion of positive elements in the matrix: " _col(73) in ye %6.2f `C2' "%"
di in green "Minimum correlation coefficient for 2 variables of the same group: " _col(74) in ye %5.2f `minrho'
di in green "Maximum correlation coefficient for 2 variables of two different groups: " _col(74) in ye %5.2f `maxrho'
di in green "Average correlation coefficient: " _col(74) in ye %5.2f `mean'
di in green "{hline 80}"
di
if "`details'"!="" {
   di in green "Matrix of the coefficients"
   di in green "{hline 26}"
   matrix list `W' ,noheader format(%7.4f)
   di
}
if "`variables'"!="" {
   di in green "Details for each variable"
   di in green "{hline 26}"
   di
   di in green "{hline 80}"
   di in green "Items" _col(17) "COMPART" _col(26) "Problematic items"
   di in green "{hline 80}"
   tempname Cvar
   matrix `Cvar'=J(1,`nbvar',0)
   forvalues i=1/`nbvar' {
      local C`i'=0
      local pourri`i'
      forvalues j=1/`nbvar' {
         local C`i'=`C`i''+`W'[`i',`j']
         if `W'[`i',`j']<0 {
            local pourri`i' `pourri`i'' ``j''
         }
      }
      local C`i'=`C`i''/(`nbvar'-1)
      matrix `Cvar'[1,`i']=`C`i''
      di in ye abbrev("``i''",14) _col(15) %9.6f `C`i'' _c
      if "`pourri`i''"!="" {
         di in ye _col(26) "`pourri`i''"
      }
      else {
         di
      }
   }
   di in green "{hline 80}"
   matrix colnames `Cvar'=`varlist'
   matrix rownames `Cvar'=Compart
   return matrix Cvar=`Cvar'
}
local test=`maxrho'-`minrho'
local diffsum=(`summeme'*`meme'-`diff'*`sumdiff')/(`meme'+`diff')
local diffsum=`summeme'/*-`sumdiff'*/
return local compart `C'
return local mean `mean'
return local list `varlist'
return local part `part'
restore
end
