00001 #ifndef SUMA_BRAINWRAP_INCLUDED
00002 #define SUMA_BRAINWRAP_INCLUDED
00003 
00004 typedef enum { SUMA_3dSS_NO_PAUSE = 0, SUMA_3dSS_DEMO_PAUSE, SUMA_3dSS_INTERACTIVE } SUMA_3DSS_MODES;
00005 
00006 float SUMA_LoadPrepInVol (SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt, SUMA_SurfaceObject **SOhull);
00007 int SUMA_Find_IminImax (SUMA_SurfaceObject *SO, SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt, int ni, 
00008                         float *MinMax, float *MinMax_dist , float *MinMax_over, float *MinMax_over_dist,
00009                         float *Means, float *undershish, float *overshish, int *dvecind_under, int *dvecind_over, int ShishMax);
00010 int SUMA_SkullMask (SUMA_SurfaceObject *SO, SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt, SUMA_COMM_STRUCT *cs);
00011 int SUMA_StretchToFitLeCerveau (SUMA_SurfaceObject *SO, SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt, SUMA_COMM_STRUCT *cs);
00012 byte *SUMA_FindVoxelsInSurface_SLOW (SUMA_SurfaceObject *SO, SUMA_VOLPAR *VolPar, int *N_inp, int fillhole) ;
00013 short *SUMA_SurfGridIntersect (SUMA_SurfaceObject *SO, float *NodeIJKlist, SUMA_VOLPAR *VolPar, int *N_inp, int fillhole, THD_3dim_dataset *fillholeset);
00014 short *SUMA_FindVoxelsInSurface (SUMA_SurfaceObject *SO, SUMA_VOLPAR *VolPar, int *N_inpnt, int  fillhole, THD_3dim_dataset *fillholeset) ;
00015 int SUMA_Reposition_Touchup(SUMA_SurfaceObject *SO, SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt, float limtouch, SUMA_COMM_STRUCT *cs) ;
00016 float *SUMA_Suggest_Touchup(SUMA_SurfaceObject *SO, SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt, float limtouch, SUMA_COMM_STRUCT *cs, int *N_touch);
00017 float *SUMA_Suggest_Touchup_Grad(SUMA_SurfaceObject *SO, SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt, float limtouch, SUMA_COMM_STRUCT *cs, int *N_touch);
00018 int SUMA_DidUserQuit(void);
00019 EDIT_options *SUMA_BlankAfniEditOptions(void);
00020 
00021 
00022 
00023 
00024 
00025 
00026 #define SUMA_WRAP_BRAIN_SMOOTH_NN(niter, dsmooth, refNodeList){ \
00027    SUMA_SurfaceObject m_SOref;   \
00028    int m_in;   \
00029    float *m_a, m_P2[2][3], m_U[3], m_Un, m_Rref, m_R, m_Dr, m_Dn;  \
00030    if (!refNodeList) {  \
00031       refNodeList = (float *)SUMA_malloc(sizeof(float)*SO->N_Node*3);   \
00032       if (!refNodeList) { SUMA_SL_Crit("Failed to allocate for refNodeList!"); SUMA_RETURN(NOPE); }   \
00033    }  \
00034    SUMA_SO_RADIUS(SO, m_Rref);   \
00035    memcpy((void*)refNodeList, (void *)SO->NodeList, SO->N_Node * 3 * sizeof(float));  \
00036    dsmooth = SUMA_NN_GeomSmooth( SO, niter, SO->NodeList, 3, SUMA_ROW_MAJOR, dsmooth, cs);    \
00037    memcpy((void*)SO->NodeList, (void *)dsmooth, SO->N_Node * 3 * sizeof(float));   \
00038    SUMA_RECOMPUTE_NORMALS(SO);   \
00039    \
00040    if (0) { \
00041         \
00042       for (m_in=0; m_in < SO->N_Node; ++m_in) { \
00043          m_a = &(SO->NodeList[3*m_in]); \
00044          SUMA_UNIT_VEC(SO->Center, m_a, m_U, m_Un);\
00045          SUMA_POINT_AT_DISTANCE_NORM(m_U, SO->Center, (m_Un+2), m_P2);   \
00046          SO->NodeList[3*m_in] = m_P2[0][0]; SO->NodeList[3*m_in+1] = m_P2[0][1]; SO->NodeList[3*m_in+2] = m_P2[0][2];   \
00047       }  \
00048    }  else {   \
00049       SUMA_SO_RADIUS(SO, m_R);   \
00050       m_Dr = ( m_Rref - m_R ) / m_Rref;   \
00051       for (m_in=0; m_in < SO->N_Node; ++m_in) { \
00052          m_a = &(SO->NodeList[3*m_in]); \
00053          SUMA_UNIT_VEC(SO->Center, m_a, m_U, m_Un);\
00054          m_Dn = m_Dr*m_Un + m_Un;   \
00055          if (m_Un) { \
00056             SUMA_POINT_AT_DISTANCE_NORM(m_U, SO->Center, m_Dn, m_P2);  \
00057             SO->NodeList[3*m_in] = m_P2[0][0]; SO->NodeList[3*m_in+1] = m_P2[0][1]; SO->NodeList[3*m_in+2] = m_P2[0][2];   \
00058          }  \
00059       }  \
00060    }  \
00061 }
00062 
00063 
00064 #define SUMA_WRAP_BRAIN_SMOOTH_MATCHAREA(niter, dsmooth, refNodeList){ \
00065    SUMA_SurfaceObject m_SOref;   \
00066    if (!refNodeList) {  \
00067       refNodeList = (float *)SUMA_malloc(sizeof(float)*SO->N_Node*3);   \
00068       if (!refNodeList) { SUMA_SL_Crit("Failed to allocate for refNodeList!"); SUMA_RETURN(NOPE); }   \
00069    }  \
00070    memcpy((void*)refNodeList, (void *)SO->NodeList, SO->N_Node * 3 * sizeof(float));  \
00071    dsmooth = SUMA_NN_GeomSmooth( SO, niter, SO->NodeList, 3, SUMA_ROW_MAJOR, dsmooth, cs);    \
00072    memcpy((void*)SO->NodeList, (void *)dsmooth, SO->N_Node * 3 * sizeof(float));   \
00073    m_SOref.PolyArea = NULL; m_SOref.NodeDim = 3; m_SOref.FaceSetDim = 3;   \
00074    m_SOref.NodeList = refNodeList; m_SOref.N_Node = SO->N_Node;   \
00075    m_SOref.FaceSetList = SO->FaceSetList; m_SOref.N_FaceSet = SO->N_FaceSet;  \
00076    SUMA_EquateSurfaceAreas(SO, &m_SOref, 0.1, cs);  \
00077 }
00078 
00079 
00080 
00081 
00082 #define SUMA_WRAP_BRAIN_SMOOTH_TAUB(niter, dsmooth, refNodeList){ \
00083       dsmooth = SUMA_Taubin_Smooth( SO, NULL,   \
00084                                     0.6307, -.6732, SO->NodeList, \
00085                                     niter, 3, SUMA_ROW_MAJOR, dsmooth, cs);   \
00086       memcpy((void*)SO->NodeList, (void *)dsmooth, SO->N_Node * 3 * sizeof(float)); \
00087 }
00088 
00089 
00090 
00091 
00092 
00093 
00094 #define SUMA_REPOSITION_TOUCHUP(limtouch){  \
00095       int m_in, m_N_troub = 0, m_cond1=0, m_cond2=0, m_cond3 = 0;   \
00096       float m_MinMax_over[2], m_MinMax[2], m_MinMax_dist[2], m_MinMax_over_dist[2], m_Means[3], m_tb; \
00097       float m_U[3], m_Un, *m_a, m_P2[2][3], *m_norm, m_shft; \
00098       float *m_touchup=NULL, **m_wgt=NULL, *m_dsmooth=NULL; \
00099       m_touchup = (float *)SUMA_calloc(SO->N_Node, sizeof(float));   \
00100       if (!m_touchup) { SUMA_SL_Crit("Failed to allocate"); exit(1); }  \
00101       for (m_in=0; m_in<SO->N_Node; ++m_in) {   \
00102          SUMA_Find_IminImax(SO, Opt, m_in,  m_MinMax, m_MinMax_dist, m_MinMax_over, m_MinMax_over_dist, m_Means, NULL, NULL, NULL, NULL, 0); \
00103          
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115  \
00116          m_tb = (m_MinMax[1] - Opt->t2) * 0.5 + Opt->t2; \
00117          m_cond1 = (    (m_MinMax_over_dist[0] < m_MinMax_dist[0]) || (m_MinMax_dist[0] > 1 && m_MinMax[0] >= m_MinMax_over[0] ) \
00118                      || (m_MinMax[0] > m_tb && m_MinMax_over[0] < m_MinMax[0]) ); \
00119          if (m_MinMax_over[1] > m_MinMax[1] && m_MinMax_over[1] > 0.9 * Opt->t98 && (m_MinMax_over_dist[1] < m_MinMax_over_dist[0]) ) m_cond2 = 0;  \
00120          else m_cond2 = 1; \
00121          if (m_MinMax_over[0] > 1.2 * m_Means[0]) m_cond3 = 0;\
00122          else m_cond3 = 1; \
00123          if (Opt->NodeDbg == m_in) {   \
00124                m_a = &(SO->NodeList[3*m_in]);   \
00125                fprintf(SUMA_STDERR, "%s: Debug during touchup for node %d:\n"   \
00126                                     " MinMax     =[%.1f,%.1f] MinMax_dist     = [%.2f,%.2f] \n"   \
00127                                     " MinMax_over=[%.1f,%.1f] MinMax_over_dist= [%.2f,%.2f] \n"   \
00128                                     " Val at node %.1f, mean below %.1f, mean above %.1f\n"  \
00129                                     " zalt= %f, r/2 = %f\n"    \
00130                                     " Conditions: %f %d %d %d\n",    \
00131                        FuncName, m_in, \
00132                        m_MinMax[0], m_MinMax[1], m_MinMax_dist[0], m_MinMax_dist[1], \
00133                        m_MinMax_over[0], m_MinMax_over[1], m_MinMax_over_dist[0], m_MinMax_over_dist[1], \
00134                        m_Means[0], m_Means[1], m_Means[2],   \
00135                        m_a[2] - SO->Center[2], Opt->r/2, \
00136                        m_MinMax_over_dist[0] , m_cond1 , m_cond2, m_cond3); \
00137          }  \
00138          if (m_MinMax_over_dist[0] && m_cond1 && m_cond2 && m_cond3) {   \
00139                m_a = &(SO->NodeList[3*m_in]);   \
00140                  \
00141                if (0 && LocalHead) { fprintf(SUMA_STDERR, "%s: Suggest repair for node %d (better min above):\n"   \
00142                                     " MinMax     =[%.1f,%.1f] MinMax_dist     = [%.2f,%.2f] \n"   \
00143                                     " MinMax_over=[%.1f,%.1f] MinMax_over_dist= [%.2f,%.2f] \n"   \
00144                                     " Val at node %.1f, mean below %.1f, mean above %.1f\n"  \
00145                                     " zalt= %f, r/2 = %f\n",    \
00146                        FuncName, m_in, \
00147                        m_MinMax[0], m_MinMax[1], m_MinMax_dist[0], m_MinMax_dist[1], \
00148                        m_MinMax_over[0], m_MinMax_over[1], m_MinMax_over_dist[0], m_MinMax_over_dist[1], \
00149                        m_Means[0], m_Means[1], m_Means[2],   \
00150                        m_a[2] - SO->Center[2], Opt->r/2); } \
00151                {  \
00152                                              \
00153                                                \
00154                                              \
00155                   m_touchup[m_in] = m_MinMax_over_dist[0]; \
00156                }  \
00157             ++m_N_troub;   \
00158          }  \
00159          
00160  \
00161       }  \
00162       if (LocalHead) fprintf (SUMA_STDERR,"%s: ********************* %d troubled nodes found\n", FuncName, m_N_troub); \
00163       if (1){ \
00164          
00165 \
00166          if (LocalHead) fprintf (SUMA_STDERR,"%s: ********************* Now filtering...\n", FuncName); \
00167          m_wgt = SUMA_Chung_Smooth_Weights(SO);   \
00168          if (!m_wgt) { \
00169             SUMA_SL_Err("Failed to compute weights.\n"); \
00170             exit(1); \
00171          }  \
00172          m_dsmooth = SUMA_Chung_Smooth (SO, m_wgt, 200, 20, m_touchup, 1, SUMA_COLUMN_MAJOR, NULL, ps->cs);   \
00173          if (LocalHead) fprintf (SUMA_STDERR,"%s: ********************* filtering done.\n", FuncName);   \
00174       } else { \
00175          m_dsmooth = m_touchup; m_touchup = NULL;  \
00176       }  \
00177          \
00178       for (m_in=0; m_in<SO->N_Node; ++m_in) {   \
00179          m_a = &(SO->NodeList[3*m_in]);   \
00180          if (1 || !SUMA_IS_EYE_ZONE(m_a,SO->Center)) { \
00181             if (m_a[2] - SO->Center[2] > 10 )  m_shft = m_touchup[m_in];  \
00182             else m_shft = m_dsmooth[m_in];   \
00183             if (m_shft) { \
00184                m_a = &(SO->NodeList[3*m_in]);   \
00185                m_norm = &(SO->NodeNormList[3*m_in]);  \
00186                SUMA_POINT_AT_DISTANCE(m_norm, m_a, SUMA_MIN_PAIR(m_shft, limtouch), m_P2);   \
00187                SO->NodeList[3*m_in] = m_P2[0][0]; SO->NodeList[3*m_in+1] = m_P2[0][1]; SO->NodeList[3*m_in+2] = m_P2[0][2];   \
00188                if (0 && LocalHead) fprintf(SUMA_STDERR,"%s: Acting on node %d because it is in top half, boosting by %f\n", \
00189                         FuncName, m_in, SUMA_MIN_PAIR(m_shft, limtouch));   \
00190             }\
00191          }  \
00192       }  \
00193       if (m_touchup) SUMA_free(m_touchup); m_touchup = NULL;   \
00194       if (m_dsmooth) SUMA_free(m_dsmooth); m_dsmooth = NULL;   \
00195       if (m_wgt) SUMA_free2D ((char **)m_wgt, SO->N_Node); m_wgt = NULL;   \
00196 }
00197 
00198 #define SUMA_IS_EYE_ZONE(n,c) ( ( ( (n)[1] - (c)[1] ) < -10 && ( (n)[2] - (c)[2] ) < 0 ) ? 1 : 0 ) 
00199 
00200 
00201 
00202 
00203 
00204 #define SUMA_MEAN_NEIGHB_COORD(SO, i, mnc) { \
00205    int m_j, m_in; \
00206    mnc[0] = 0; mnc[1] = 0; mnc[2] = 0; \
00207    for (m_j = 0; m_j < SO->FN->N_Neighb[i]; ++m_j) {  \
00208       m_in = 3*SO->FN->FirstNeighb[i][m_j]; \
00209       mnc[0] += SO->NodeList[m_in]; \
00210       mnc[1] += SO->NodeList[m_in+1]; \
00211       mnc[2] += SO->NodeList[m_in+2]; \
00212    }  \
00213    mnc[0] = mnc[0] / (SO->FN->N_Neighb[i]); mnc[1] = mnc[1] / (SO->FN->N_Neighb[i]);  mnc[2] = mnc[2] / (SO->FN->N_Neighb[i]); \
00214 }
00215 
00216 
00217 
00218 #define SUMA_MEAN_SEGMENT_LENGTH(SO, l) { \
00219    int m_cnt=0, m_j;   \
00220    float *m_p1, *m_p2, m_d=0.0, m_v[3];  \
00221    l = 0.0; \
00222    for (m_j=0; m_j < SO->EL->N_EL; ++m_j) {  \
00223       if (SO->EL->ELps[m_j][2] >= 0) { \
00224          m_p1 = &(SO->NodeList[3*SO->EL->EL[m_j][0]]); m_p2 = &(SO->NodeList[3*SO->EL->EL[m_j][1]]); \
00225          SUMA_UNIT_VEC(m_p1, m_p2, m_v, m_d);   \
00226          l += m_d;   \
00227          ++m_cnt; \
00228       }  \
00229    }  \
00230    if (m_cnt) l /= m_cnt; \
00231 }
00232 
00233 
00234 
00235 
00236 #define SUMA_MAX_SHISH_JUMP(vec, diffmax, i_diffmax, thresh_clip){  \
00237    int m_kk = 1, m_thresh = 0;   \
00238    float m_diff;  \
00239    m_diff = 0; diffmax = 0;  i_diffmax = 0;\
00240    while (vec[m_kk] >=0 && m_kk < ShishMax && !m_thresh) {   \
00241       m_diff = vec[m_kk] - vec[m_kk - 1]; \
00242       if (m_diff > diffmax) {diffmax = m_diff; i_diffmax = m_kk-1; }  \
00243       if (diffmax > thresh_clip) m_thresh = 1;   \
00244       ++ m_kk; \
00245    }  \
00246 }
00247 
00248 
00249 
00250 
00251 #define SUMA_MAX_NEG_SHISH_JUMP(vec, diffmax, i_diffmax){  \
00252    int m_kk = 1, m_thresh = 0;   \
00253    float m_diff;  \
00254    m_diff = 0; diffmax = 0;  i_diffmax = 0;\
00255    while (vec[m_kk] >=0 && m_kk < ShishMax && !m_thresh) {   \
00256       m_diff = vec[m_kk] - vec[m_kk - 1]; \
00257       if (m_diff < diffmax) {\
00258          diffmax = m_diff; i_diffmax = m_kk-1; \
00259       }  \
00260       ++ m_kk; \
00261    }  \
00262 }
00263 
00264 
00265 
00266 #define SUMA_MIN_SHISH_JUMP(vec, diffmin, i_diffmin, thresh_clip, N_neg){  \
00267    int m_kk = 1;   \
00268    float m_diff;  \
00269    m_diff = 0; diffmin = 0;  i_diffmin = 0; N_neg=0;\
00270    while (vec[m_kk] >=0 && m_kk < ShishMax ) {   \
00271       m_diff = vec[m_kk] - vec[m_kk - 1]; \
00272       if (m_diff < diffmin) { diffmin = m_diff; i_diffmax = m_kk-1; }  \
00273       if (SUMA_ABS(diffmin) > thresh_clip) ++N_neg;   \
00274       ++ m_kk; \
00275    }  \
00276 }
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 #define SUMA_ONE_SHISH_PLEASE(nl, U, in_vol, dvec, stp, n_stp, nxx, nxy, shish, N_shishmax){\
00292    int m_istep, m_nind;   \
00293    static THD_fvec3 m_ncoord, m_ndicom; \
00294    static THD_ivec3 m_nind3;  \
00295    static double m_jmp, m_td[3];  \
00296    m_istep = 0; \
00297    m_jmp = 0.0;  \
00298    while (m_istep <= n_stp) {   \
00299       m_td[0] = m_jmp * U[0]; m_td[1] = m_jmp * U[1]; m_td[2] = m_jmp * U[2]; \
00300          \
00301       m_ndicom.xyz[0] = nl[0] + m_td[0] ; m_ndicom.xyz[1] = nl[1]+ m_td[1]; m_ndicom.xyz[2] = nl[2]+ m_td[2];  \
00302       m_ncoord = THD_dicomm_to_3dmm(in_vol, m_ndicom);   \
00303       m_nind3 = THD_3dmm_to_3dind(in_vol, m_ncoord);  \
00304       m_nind = m_nind3.ijk[0] + m_nind3.ijk[1] * nxx + m_nind3.ijk[2] * nxy;  \
00305       if (m_istep < N_shishmax) shish[m_istep] = dvec[m_nind];  \
00306       else break; \
00307       m_jmp += stp;  \
00308       ++m_istep;  \
00309    }  \
00310    if (m_istep < N_shishmax) shish[m_istep] = -1;  \
00311 }
00312 
00313 
00314 #endif