6

I have this code for highlight the diagonal, the first row and the first column with different colours! (This code has been build from egreg on this community :-D in a past question)

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{xparse,environ}

\ExplSyntaxOn
\NewEnviron{matlabtabular}[1]
 {
  \tl_set:Nx \l_angelino_matlab_preamble_tl 
   {
    \tl_tail:n { #1 }
   }
  \tl_put_left:Nn \l_angelino_matlab_preamble_tl { | >{\columncolor{red!20}} }
  \angelino_matlabtab:VV \l_angelino_matlab_preamble_tl \BODY
 }

\cs_new_protected:Nn \angelino_matlabtab:nn
 {
  \seq_set_split:Nnn \l_angelino_matlabtab_rows_seq { \hline } { #2 }
  % the first item is empty
  \seq_pop_left:NN \l_angelino_matlabtab_rows_seq \l_angelino_matlabtab_body_tl
  % the last item is empty
  \seq_pop_right:NN \l_angelino_matlabtab_rows_seq \l_tmpa_tl
  % separate the first row
  \seq_pop_left:NN \l_angelino_matlabtab_rows_seq \l_angelino_matlabtab_body_tl
  % fix the first row
  \tl_put_left:Nn \l_angelino_matlabtab_body_tl { \hline\rowcolor{blue!20} }
  \tl_put_right:Nn \l_angelino_matlabtab_body_tl { \hline }
  \seq_map_inline:Nn \l_angelino_matlabtab_rows_seq
   {
    \int_incr:N \l_angelino_matlab_currentrow_int
    \int_zero:N \l_angelino_matlab_currentcol_int
    \seq_set_split:Nnn \l_angelino_matlabtab_row_seq { & } { ##1 }
    \seq_pop_left:NN \l_angelino_matlabtab_row_seq \l_angelino_matlabtab_first_tl
    \tl_put_right:NV \l_angelino_matlabtab_body_tl \l_angelino_matlabtab_first_tl
    \seq_map_inline:Nn \l_angelino_matlabtab_row_seq
     {
      \int_incr:N \l_angelino_matlab_currentcol_int
      \int_compare:nTF { \l_angelino_matlab_currentcol_int == \l_angelino_matlab_currentrow_int }
       {
        \tl_put_right:Nn \l_angelino_matlabtab_body_tl { & \cellcolor{green} ####1 }
       }
       {
        \tl_put_right:Nn \l_angelino_matlabtab_body_tl { & ####1 }
       }
     }
    \tl_put_right:Nn \l_angelino_matlabtab_body_tl { \hline }
   }
  \begin{tabular}{#1}
  \l_angelino_matlabtab_body_tl
  \end{tabular}
 }
\cs_generate_variant:Nn \angelino_matlabtab:nn { VV }
\int_new:N \l_angelino_matlab_currentcol_int
\int_new:N \l_angelino_matlab_currentrow_int
\seq_new:N \l_angelino_matlabtab_rows_seq
\seq_new:N \l_angelino_matlabtab_row_seq
\tl_new:N \l_angelino_matlabtab_body_tl
\tl_new:N \l_angelino_matlabtab_first_tl
\tl_new:N \l_angelino_matlab_preamble_tl
\ExplSyntaxOff

\begin{document}

\begin{matlabtabular}{|l|c|c|c|}
\hline
&\textbf{ciao}&\textbf{ciao2}&\textbf{ciao3}\\\hline
\textbf{ciao}&5.3&0.913&0.278\\\hline
\textbf{ciao2}&-30&0.632&0.547\\\hline
\textbf{ciao3}&20&-60&0.958\\\hline
\end{matlabtabular}

\end{document}

How can improve this code so that if a number is not on diagonal is >0 the number is print in blue and if the number is <0 the number is print in red???????

  • None of the numbers in your example are less than 0. – cfr Feb 04 '16 at 23:11
  • In the exsampe, but the table generate from matlab have number less than 0 – Luca Angelino Feb 04 '16 at 23:20
  • The problem is, that the whole stuff is constructed as a token list, making the query \fp_compare:nNnTF difficult, in my point of view. –  Feb 04 '16 at 23:27
  • I am not an latex expert but this code is very powerful for my task. I need only this small improve! If it is not possible I must impreve the code that generate the table – Luca Angelino Feb 04 '16 at 23:33
  • The point is that your minimal example should set up the problem. If that problem involves distinguishing numbers greater than zero from those less than zero, then you want your example to include numbers of each kind. What's the point of the example numbers if a solution which works for the MWE (by making them all blue) won't work for your real case (where some should be red)? – cfr Feb 04 '16 at 23:41
  • Could you please include a link to the previous question where the code came from... –  Feb 04 '16 at 23:49
  • I've added the expl3 tag, since the whole code is expl3 –  Feb 04 '16 at 23:57
  • The first question was http://tex.stackexchange.com/questions/284214/how-can-i-color-highlight-the-diagonal-of-a-matrix Now I have update the table with value less than 0 – Luca Angelino Feb 04 '16 at 23:59

1 Answers1

4

Here's a possible solution:

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{xparse,environ}

\ExplSyntaxOn
\NewEnviron{matlabtabular}[1]
 {
  \tl_set:Nx \l_angelino_matlab_preamble_tl 
   {
    \tl_tail:n { #1 }
   }
  \tl_put_left:Nn \l_angelino_matlab_preamble_tl { | >{\columncolor{red!20}} }
  \angelino_matlabtab:VV \l_angelino_matlab_preamble_tl \BODY
 }

\cs_new_protected:Nn \angelino_matlabtab:nn
 {
  \seq_set_split:Nnn \l_angelino_matlabtab_rows_seq { \hline } { #2 }
  % the first item is empty
  \seq_pop_left:NN \l_angelino_matlabtab_rows_seq \l_angelino_matlabtab_body_tl
  % the last item is empty
  \seq_pop_right:NN \l_angelino_matlabtab_rows_seq \l_tmpa_tl
  % separate the first row
  \seq_pop_left:NN \l_angelino_matlabtab_rows_seq \l_angelino_matlabtab_body_tl
  % fix the first row
  \tl_put_left:Nn \l_angelino_matlabtab_body_tl { \hline\rowcolor{blue!20} }
  \tl_put_right:Nn \l_angelino_matlabtab_body_tl { \hline }
  \seq_map_inline:Nn \l_angelino_matlabtab_rows_seq
   {
    \int_incr:N \l_angelino_matlab_currentrow_int
    \int_zero:N \l_angelino_matlab_currentcol_int
    \seq_set_split:Nnn \l_angelino_matlabtab_row_seq { & } { ##1 }
    \seq_pop_left:NN \l_angelino_matlabtab_row_seq \l_angelino_matlabtab_first_tl
    \tl_put_right:NV \l_angelino_matlabtab_body_tl \l_angelino_matlabtab_first_tl
    \seq_map_inline:Nn \l_angelino_matlabtab_row_seq
     {
      \int_incr:N \l_angelino_matlab_currentcol_int
      \int_compare:nTF { \l_angelino_matlab_currentcol_int == \l_angelino_matlab_currentrow_int }
       {
        \tl_put_right:Nn \l_angelino_matlabtab_body_tl { & \cellcolor{green} ####1 }
       }
       {
        \tl_put_right:Nn \l_angelino_matlabtab_body_tl { & \angelino_print_number:n { ####1 } }
       }
     }
    \tl_put_right:Nn \l_angelino_matlabtab_body_tl { \hline }
   }
  \begin{tabular}{#1}
  \l_angelino_matlabtab_body_tl
  \end{tabular}
 }
\cs_generate_variant:Nn \angelino_matlabtab:nn { VV }

\cs_new_protected:Nn \angelino_print_number:n
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_if_in:NnTF \l_tmpa_tl { \\ }
   {
    \tl_replace_once:Nnn \l_tmpa_tl { \\ } { }
    \__angelino_print_number:V \l_tmpa_tl
    \\
   }
   {
    \__angelino_print_number:V \l_tmpa_tl
   }
 }
\cs_new_protected:Nn \__angelino_print_number:n
 {
  \fp_compare:nTF { #1 > 0 }
   {
    \textcolor{blue}{$#1$}
   }
   {
    \textcolor{red}{$#1$}
   }
 }
\cs_generate_variant:Nn \__angelino_print_number:n { V }
\int_new:N \l_angelino_matlab_currentcol_int
\int_new:N \l_angelino_matlab_currentrow_int
\seq_new:N \l_angelino_matlabtab_rows_seq
\seq_new:N \l_angelino_matlabtab_row_seq
\tl_new:N \l_angelino_matlabtab_body_tl
\tl_new:N \l_angelino_matlabtab_first_tl
\tl_new:N \l_angelino_matlab_preamble_tl
\ExplSyntaxOff

\begin{document}

\begin{matlabtabular}{|l|c|c|c|}
\hline
&\textbf{ciao}&\textbf{ciao2}&\textbf{ciao3}\\\hline
\textbf{ciao}&0.815&0.913&0.278\\\hline
\textbf{ciao2}&-0.906&0.632&0.547\\\hline
\textbf{ciao3}&-0.127&0.098&0.958\\\hline
\end{matlabtabular}

\end{document}

enter image description here


With some more work we can add customization of colors; in the new optional argument to \begin{matlabtabular} you can specify colors for

header legend diag positive negative

Each should be of the form <key>=<color> like in the example below. The default are

header=blue!20,
legend=red!20,
diag=green,
positive=., % normalcolor
negative=., % normalcolor

like in the first specification you gave.

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{xparse,environ}

\ExplSyntaxOn
\NewEnviron{matlabtabular}[2][]
 {
  \keys_set:nn { angelino/matlabtab } { #1 }
  \tl_set:Nx \l_angelino_matlabtab_preamble_tl 
   {
    \tl_tail:n { #2 }
   }
  \tl_put_left:Nn \l_angelino_matlabtab_preamble_tl { | >{\columncolor{\l_angelino_matlabtab_legend_tl}} }
  \angelino_matlabtab:VV \l_angelino_matlabtab_preamble_tl \BODY
 }

\keys_define:nn { angelino/matlabtab }
 {
  header   .tl_set:N  = \l_angelino_matlabtab_head_tl,
  header   .initial:n = blue!20,
  legend   .tl_set:N  = \l_angelino_matlabtab_legend_tl,
  legend   .initial:n = red!20,
  diag     .tl_set:N  = \l_angelino_matlabtab_diag_tl,
  diag     .initial:n = green,
  positive .tl_set:N = \l_angelino_matlabtab_positive_tl,
  positive .initial:n = .,
  negative .tl_set:N = \l_angelino_matlabtab_negative_tl,
  negative .initial:n = .,
 }

\cs_new_protected:Nn \angelino_matlabtab:nn
 {
  \seq_set_split:Nnn \l_angelino_matlabtab_rows_seq { \hline } { #2 }
  % the first item is empty
  \seq_pop_left:NN \l_angelino_matlabtab_rows_seq \l_angelino_matlabtab_body_tl
  % the last item is empty
  \seq_pop_right:NN \l_angelino_matlabtab_rows_seq \l_tmpa_tl
  % separate the first row
  \seq_pop_left:NN \l_angelino_matlabtab_rows_seq \l_angelino_matlabtab_body_tl
  % fix the first row
  \tl_put_left:Nn \l_angelino_matlabtab_body_tl { \hline\rowcolor{\l_angelino_matlabtab_head_tl} }
  \tl_put_right:Nn \l_angelino_matlabtab_body_tl { \hline }
  \seq_map_inline:Nn \l_angelino_matlabtab_rows_seq
   {
    \int_incr:N \l_angelino_matlabtab_currentrow_int
    \int_zero:N \l_angelino_matlabtab_currentcol_int
    \seq_set_split:Nnn \l_angelino_matlabtab_row_seq { & } { ##1 }
    \seq_pop_left:NN \l_angelino_matlabtab_row_seq \l_angelino_matlabtab_first_tl
    \tl_put_right:NV \l_angelino_matlabtab_body_tl \l_angelino_matlabtab_first_tl
    \seq_map_inline:Nn \l_angelino_matlabtab_row_seq
     {
      \int_incr:N \l_angelino_matlabtab_currentcol_int
      \int_compare:nTF { \l_angelino_matlabtab_currentcol_int == \l_angelino_matlabtab_currentrow_int }
       {
        \tl_put_right:Nn \l_angelino_matlabtab_body_tl { & \cellcolor{\l_angelino_matlabtab_diag_tl} ####1 }
       }
       {
        \tl_put_right:Nn \l_angelino_matlabtab_body_tl { & \angelino_print_number:n { ####1 } }
       }
     }
    \tl_put_right:Nn \l_angelino_matlabtab_body_tl { \hline }
   }
  \begin{tabular}{#1}
  \l_angelino_matlabtab_body_tl
  \end{tabular}
 }
\cs_generate_variant:Nn \angelino_matlabtab:nn { VV }

\cs_new_protected:Nn \angelino_print_number:n
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_if_in:NnTF \l_tmpa_tl { \\ }
   {
    \tl_replace_once:Nnn \l_tmpa_tl { \\ } { }
    \__angelino_print_number:V \l_tmpa_tl
    \\
   }
   {
    \__angelino_print_number:V \l_tmpa_tl
   }
 }
\cs_new_protected:Nn \__angelino_print_number:n
 {
  \fp_compare:nTF { #1 >= 0 }
   {
    \textcolor{\l_angelino_matlabtab_positive_tl}{$#1$}
   }
   {
    \textcolor{\l_angelino_matlabtab_negative_tl}{$#1$}
   }
 }
\cs_generate_variant:Nn \__angelino_print_number:n { V }
\int_new:N \l_angelino_matlabtab_currentcol_int
\int_new:N \l_angelino_matlabtab_currentrow_int
\seq_new:N \l_angelino_matlabtab_rows_seq
\seq_new:N \l_angelino_matlabtab_row_seq
\tl_new:N \l_angelino_matlabtab_body_tl
\tl_new:N \l_angelino_matlabtab_first_tl
\tl_new:N \l_angelino_matlabtab_preamble_tl
\ExplSyntaxOff

\begin{document}

\begin{matlabtabular}{|l|c|c|c|}
\hline
&\textbf{ciao}&\textbf{ciao2}&\textbf{ciao3}\\\hline
\textbf{ciao}&0.815&0.913&0.278\\\hline
\textbf{ciao2}&-0.906&0.632&0.547\\\hline
\textbf{ciao3}&-0.127&0.098&0.958\\\hline
\end{matlabtabular}

\bigskip

\begin{matlabtabular}[positive=blue,negative=red]{|l|c|c|c|}
\hline
&\textbf{ciao}&\textbf{ciao2}&\textbf{ciao3}\\\hline
\textbf{ciao}&0.815&0.913&0.278\\\hline
\textbf{ciao2}&-0.906&0.632&0.547\\\hline
\textbf{ciao3}&-0.127&0.098&0.958\\\hline
\end{matlabtabular}

\end{document}
egreg
  • 1,121,712
  • It is really spectacle – Luca Angelino Feb 05 '16 at 00:42
  • The last questions is if I rename this as \NewEnviron{matlabtabular2} and the last (http://tex.stackexchange.com/questions/284214/how-can-i-color-highlight-the-diagonal-of-a-matrix) leave \NewEnviron{matlabtabular} for have two type of table the compile generate error! :-( why????? – Luca Angelino Feb 05 '16 at 00:44
  • @LucaAngelino Doing things this way is not the best approach. I'll think to a more general setting. The main obstacle is the requirement of not touching the body of the table as generated by MatLab, of course. – egreg Feb 05 '16 at 00:45
  • with matlab I can add simply text first and later the values! – Luca Angelino Feb 05 '16 at 00:49
  • @LucaAngelino I added a new version so you can customize the colors. – egreg Feb 05 '16 at 09:37
  • Thanks a lot. I thought that in latex, such as in html, there is a way for add a table with an style name and by changing the style name I can obtain every customization – Luca Angelino Feb 08 '16 at 12:38