def find_prf_cpu(idxPrc, aryFuncChnk, aryPrfTc, aryMdlParams, strVersion,<EOL>lgcXval, varNumXval, queOut, lgcRstr=None, lgcPrint=True):
<EOL>varNumMdls = aryPrfTc.shape[<NUM_LIT:0>]<EOL>varNumFtr = aryPrfTc.shape[<NUM_LIT:1>]<EOL>varNumVoxChnk = aryFuncChnk.shape[<NUM_LIT:0>]<EOL>vecBstXpos = np.zeros(varNumVoxChnk, dtype=aryMdlParams.dtype)<EOL>vecBstYpos = np.zeros(varNumVoxChnk, dtype=aryMdlParams.dtype)<EOL>vecBstSd = np.zeros(varNumVoxChnk, dtype=aryMdlParams.dtype)<EOL>vecBstRes = np.add(np.zeros(varNumVoxChnk), np.inf).astype(np.float32)<EOL>aryBstBts = np.zeros((varNumVoxChnk, varNumFtr)).astype(np.float32)<EOL>if lgcXval:<EOL><INDENT>aryBstResFlds = np.zeros((varNumVoxChnk, varNumXval), dtype=np.float32)<EOL><DEDENT>aryFuncChnk = aryFuncChnk.T<EOL>aryFuncChnk = aryFuncChnk.astype(np.float32)<EOL>aryPrfTc = aryPrfTc.astype(np.float32)<EOL>if lgcXval:<EOL><INDENT>itXval = KFold(n_splits=varNumXval)<EOL>vecSplts = np.arange(aryPrfTc.shape[-<NUM_LIT:1>], dtype=np.int32)<EOL>lstIdxTrn = []<EOL>lstIdxtst = []<EOL>for idxTrn, idxTst in itXval.split(vecSplts):<EOL><INDENT>lstIdxTrn.append(idxTrn)<EOL>lstIdxtst.append(idxTst)<EOL><DEDENT>aryIdxTrn = np.stack(lstIdxTrn, axis=-<NUM_LIT:1>).astype(np.int32)<EOL>aryIdxTst = np.stack(lstIdxtst, axis=-<NUM_LIT:1>).astype(np.int32)<EOL><DEDENT>if idxPrc == <NUM_LIT:0>:<EOL><INDENT>varStsStpSze = <NUM_LIT:20><EOL>vecStatPrf = np.linspace(<NUM_LIT:0>,<EOL>varNumMdls,<EOL>num=(varStsStpSze+<NUM_LIT:1>),<EOL>endpoint=True)<EOL>vecStatPrf = np.ceil(vecStatPrf)<EOL>vecStatPrf = vecStatPrf.astype(int)<EOL>vecStatPrc = np.linspace(<NUM_LIT:0>,<EOL><NUM_LIT:100>,<EOL>num=(varStsStpSze+<NUM_LIT:1>),<EOL>endpoint=True)<EOL>vecStatPrc = np.ceil(vecStatPrc)<EOL>vecStatPrc = vecStatPrc.astype(int)<EOL>varCntSts01 = <NUM_LIT:0><EOL>varCntSts02 = <NUM_LIT:0><EOL><DEDENT>if lgcRstr is None:<EOL><INDENT>lgcVxl = np.arange(varNumVoxChnk, dtype=np.int32)<EOL><DEDENT>aryPrfTcVar = np.var(aryPrfTc, axis=-<NUM_LIT:1>)<EOL>varZero32 = np.array(([<NUM_LIT:0.0>])).astype(np.float32)[<NUM_LIT:0>]<EOL>for idxMdl in range(<NUM_LIT:0>, varNumMdls):<EOL><INDENT>if lgcRstr is not None:<EOL><INDENT>lgcVxl = np.flatnonzero(lgcRstr[:, idxMdl])<EOL><DEDENT>if idxPrc == <NUM_LIT:0>:<EOL><INDENT>if varCntSts02 == vecStatPrf[varCntSts01]:<EOL><INDENT>strStsMsg = ('<STR_LIT>' +<EOL>str(vecStatPrc[varCntSts01]) +<EOL>'<STR_LIT>' +<EOL>str(vecStatPrf[varCntSts01]) +<EOL>'<STR_LIT>' +<EOL>str(varNumMdls))<EOL>if lgcPrint:<EOL><INDENT>print(strStsMsg)<EOL><DEDENT>if varCntSts01 < varStsStpSze:<EOL><INDENT>varCntSts01 = varCntSts01 + int(<NUM_LIT:1>)<EOL><DEDENT><DEDENT><DEDENT>if np.logical_and(np.all(np.greater(aryPrfTcVar[idxMdl], varZero32),<EOL>axis=<NUM_LIT:0>),<EOL>np.greater(lgcVxl.size, <NUM_LIT:0>)):<EOL><INDENT>vecMdl = aryPrfTc[idxMdl, :, :].T<EOL>if lgcXval:<EOL><INDENT>if strVersion == '<STR_LIT>':<EOL><INDENT>if varNumFtr == <NUM_LIT:1>:<EOL><INDENT>aryResXval = cy_lst_sq_xval_one(np.squeeze(vecMdl),<EOL>aryFuncChnk[:, lgcVxl],<EOL>aryIdxTrn,<EOL>aryIdxTst)<EOL><DEDENT>elif varNumFtr == <NUM_LIT:2>:<EOL><INDENT>aryResXval = cy_lst_sq_xval_two(vecMdl,<EOL>aryFuncChnk[:, lgcVxl],<EOL>aryIdxTrn,<EOL>aryIdxTst)<EOL><DEDENT>else:<EOL><INDENT>if lgcPrint:<EOL><INDENT>print('<STR_LIT>' +<EOL>'<STR_LIT>')<EOL><DEDENT><DEDENT><DEDENT>elif strVersion == '<STR_LIT>':<EOL><INDENT>aryResXval = np_lst_sq_xval(vecMdl, aryFuncChnk[:, lgcVxl],<EOL>aryIdxTrn, aryIdxTst)<EOL><DEDENT>vecTmpRes = np.mean(aryResXval, axis=<NUM_LIT:1>)<EOL><DEDENT>else:<EOL><INDENT>if strVersion == '<STR_LIT>':<EOL><INDENT>if varNumFtr == <NUM_LIT:1>:<EOL><INDENT>aryTmpBts, vecTmpRes = cy_lst_sq_one(<EOL>np.squeeze(vecMdl), aryFuncChnk[:, lgcVxl])<EOL><DEDENT>elif varNumFtr == <NUM_LIT:2>:<EOL><INDENT>aryTmpBts, vecTmpRes =cy_lst_sq_two(vecMdl, aryFuncChnk[:, lgcVxl])<EOL><DEDENT>else:<EOL><INDENT>if lgcPrint:<EOL><INDENT>print('<STR_LIT>' +<EOL>'<STR_LIT>')<EOL><DEDENT><DEDENT><DEDENT>elif strVersion == '<STR_LIT>':<EOL><INDENT>aryTmpBts, vecTmpRes = np_lst_sq(vecMdl,<EOL>aryFuncChnk[:, lgcVxl])<EOL><DEDENT><DEDENT>vecLgcTmpRes = np.less(vecTmpRes, vecBstRes[lgcVxl])<EOL>vecLgcTmpRes = np.flatnonzero(vecLgcTmpRes)<EOL>vecBstXpos[lgcVxl[vecLgcTmpRes]] = aryMdlParams[idxMdl, <NUM_LIT:0>]<EOL>vecBstYpos[lgcVxl[vecLgcTmpRes]] = aryMdlParams[idxMdl, <NUM_LIT:1>]<EOL>vecBstSd[lgcVxl[vecLgcTmpRes]] = aryMdlParams[idxMdl, <NUM_LIT:2>]<EOL>vecBstRes[lgcVxl[vecLgcTmpRes]] = vecTmpRes[vecLgcTmpRes]<EOL>if not lgcXval:<EOL><INDENT>aryBstBts[lgcVxl[vecLgcTmpRes], :] =aryTmpBts[:, vecLgcTmpRes].T<EOL><DEDENT>if lgcXval:<EOL><INDENT>aryBstResFlds[lgcVxl[vecLgcTmpRes], :] =aryResXval[vecLgcTmpRes, :]<EOL><DEDENT><DEDENT>if idxPrc == <NUM_LIT:0>:<EOL><INDENT>varCntSts02 = varCntSts02 + <NUM_LIT:1><EOL><DEDENT><DEDENT>if lgcXval:<EOL><INDENT>vecVxlTst = np.zeros(aryFuncChnk.shape[<NUM_LIT:1>])<EOL>aryBstPrm = np.stack((vecBstXpos, vecBstYpos, vecBstSd), axis=<NUM_LIT:1>)<EOL>aryUnqRows = fnd_unq_rws(aryBstPrm, return_index=False,<EOL>return_inverse=False)<EOL>arySsTotXval = np.zeros((aryBstResFlds.shape),<EOL>dtype=aryBstResFlds.dtype)<EOL>for vecPrm in aryUnqRows:<EOL><INDENT>lgcPrm = np.isclose(aryBstPrm, vecPrm, atol=<NUM_LIT>).all(axis=<NUM_LIT:1>)<EOL>lgcIndMdl = np.where(np.isclose(aryMdlParams, vecPrm,<EOL>atol=<NUM_LIT>).all(axis=<NUM_LIT:1>))[<NUM_LIT:0>][<NUM_LIT:0>]<EOL>if np.all(np.invert(lgcPrm)):<EOL><INDENT>if lgcPrint:<EOL><INDENT>print('<STR_LIT>' + str(idxPrc))<EOL><DEDENT><DEDENT>vecVxlTst[lgcPrm] += <NUM_LIT:1><EOL>aryVxlTc = aryFuncChnk[:, lgcPrm]<EOL>aryMdlTc = aryPrfTc[lgcIndMdl, :, :].T<EOL>aryBstBts[lgcPrm, :] = np.linalg.lstsq(aryMdlTc,<EOL>aryVxlTc,<EOL>rcond=-<NUM_LIT:1>)[<NUM_LIT:0>].T<EOL>for idxXval in range(varNumXval):<EOL><INDENT>aryFuncChnkTst = aryVxlTc[<EOL>aryIdxTst[:, idxXval], :]<EOL>aryFuncDev = np.subtract(aryFuncChnkTst,<EOL>np.mean(aryFuncChnkTst,<EOL>axis=<NUM_LIT:0>)[None, :])<EOL>vecSsTot = np.sum(np.power(aryFuncDev,<EOL><NUM_LIT>),<EOL>axis=<NUM_LIT:0>)<EOL>arySsTotXval[lgcPrm, idxXval] = vecSsTot<EOL><DEDENT><DEDENT>errMsg = '<STR_LIT>'<EOL>assert len(vecVxlTst) == np.sum(vecVxlTst), errMsg<EOL>lgcExclZeros = np.all(np.greater(arySsTotXval,  np.array([<NUM_LIT:0.0>])),<EOL>axis=<NUM_LIT:1>)<EOL>if lgcPrint:<EOL><INDENT>print('<STR_LIT>' + str(len(lgcExclZeros)))<EOL>print('<STR_LIT>' +<EOL>str(np.sum(lgcExclZeros)))<EOL><DEDENT>aryBstR2fld = np.subtract(<EOL><NUM_LIT:1.0>, np.divide(aryBstResFlds,<EOL>arySsTotXval))<EOL>vecBstR2 = np.subtract(<EOL><NUM_LIT:1.0>, np.mean(np.divide(aryBstResFlds,<EOL>arySsTotXval),<EOL>axis=<NUM_LIT:1>))<EOL>lstOut = [idxPrc,<EOL>vecBstXpos,<EOL>vecBstYpos,<EOL>vecBstSd,<EOL>vecBstR2,<EOL>aryBstBts,<EOL>aryBstR2fld]<EOL>queOut.put(lstOut)<EOL><DEDENT>else:<EOL><INDENT>vecFuncMean = np.mean(aryFuncChnk, axis=<NUM_LIT:0>)<EOL>aryFuncDev = np.subtract(aryFuncChnk, vecFuncMean[None, :])<EOL>vecSsTot = np.sum(np.power(aryFuncDev,<EOL><NUM_LIT>),<EOL>axis=<NUM_LIT:0>)<EOL>vecBstR2 = np.subtract(<NUM_LIT:1.0>,<EOL>np.divide(vecBstRes,<EOL>vecSsTot))<EOL>lstOut = [idxPrc,<EOL>vecBstXpos,<EOL>vecBstYpos,<EOL>vecBstSd,<EOL>vecBstR2,<EOL>aryBstBts]<EOL>queOut.put(lstOut)<EOL><DEDENT>
Find best fitting pRF model for voxel time course, using the CPU.

Parameters
----------
idxPrc : int
    Process ID of the process calling this function (for CPU
    multi-threading). In GPU version, this parameter is 0 (just one thread
    on CPU).
aryFunc : np.array
    2D array with functional MRI data, with shape aryFunc[voxel, time].
aryPrfTc : np.array
    Array with pRF model time courses, with shape
    aryPrfTc[x-pos*y-pos*SD, number of feautures, number of volumes]
aryMdlParams : np.array
    2D array with all pRF model parameter combinations.
strVersion : str
    Which version to use for pRF finding; 'numpy' or 'cython'.
lgcXval: boolean
    Logical to determine whether we cross-validate.
varNumXval: int
    Number of folds for k-fold cross-validation.
queOut : multiprocessing.queues.Queue
    Queue to put the results on.
lgcRstr : boolean numpy array or None, default None
    Logical to restrict certain models to particular voxels.
lgcPrint : boolean
    Whether print statements should be executed.

Returns
-------
lstOut : list
    List containing the following objects:
    idxPrc : int
        Process ID of the process calling this function (for CPU
        multi-threading). In GPU version, this parameter is 0.
    vecBstXpos : np.array
        1D array with best fitting x-position for each voxel, with shape
        vecBstXpos[voxel].
    vecBstYpos : np.array
        1D array with best fitting y-position for each voxel, with shape
        vecBstYpos[voxel].
    vecBstSd : np.array
        1D array with best fitting pRF size for each voxel, with shape
        vecBstSd[voxel].
    vecBstR2 : np.array
        1D array with R2 value of 'winning' pRF model for each voxel, with
        shape vecBstR2[voxel].
    aryBstBts : np.array
        2D array with beta parameter estimates of 'winning' pRF model for
        each voxel, with shape aryBstBts[voxel, feautures].

Notes
-----
The list with results is not returned directly, but placed on a
multiprocessing queue. This version performs the model finding on the CPU,
using numpy or cython (depending on the value of `strVersion`).