2

I rewrote the question using a minimal example. My previous post didn't include the code required to import NumPy and other libraries.

I'm trying to export the python output to a LaTeX export block. The issue is that the output contains colons. Previously suggested fixes cause the output to be encapsulated by an example block (which breaks the latex document).

My code:

#+begin_src jupyter-python :session PY :exports results :wrap export latex

  import numpy as np
  from sympy import *
  init_printing()

  np.random.seed(376134299)              # set random seedV

  #Format C style matrix into numpy array for pretty printing
  def format_mat(mat,size):
    in_mat = mat.copy()
    return np.reshape(in_mat,(-1,size))

  def upper_echelon(mat,size):
    in_mat = mat.copy()
    for i in range(size-1):
      for j in range(size):
        if j>i:
          ratio = in_mat[j*size+i]/in_mat[i*size+i]
          for k in range(i,size):
            in_mat[j*size+k] -= (ratio*in_mat[i*size+k])
    return in_mat


  N = 4 # size for NxN matrix
  mat = np.random.random((N*N)) # init NxN matrix
  upper_mat = upper_echelon(mat.copy(),N) # upper echelon form matrix

  # print input matrix
  print("$"+latex(Matrix(format_mat(mat.copy(),N)))+"$")

  # print upper echelon form matrix
  print("$"+latex(Matrix(format_mat(upper_mat.copy(),N)))+"$")
#+end_src

The Results:

#+RESULTS:
#+begin_export latex
: $\left[\begin{matrix}0.435551782541394 & 0.653831083538496 & 0.703284715123126 & 0.779211763281097\\0.745624842540662 & 0.382867491810448 & 0.0640634444192878 & 0.205350088572431\\0.455263877780481 & 0.782880235084324 & 0.190229654979851 & 0.731404270938654\\0.13207468759024 & 0.0418823433240818 & 0.617596076042993 & 0.648004941561776\end{matrix}\right]$
: $\left[\begin{matrix}0.435551782541394 & 0.653831083538496 & 0.703284715123126 & 0.779211763281097\\0 & -0.736431563440805 & -1.13989570807275 & -1.12858923067965\\0 & -1.38777878078145 \cdot 10^{-17} & -0.698831926546978 & -0.235493658356284\\0 & 0 & 0 & 0.433555029735554\end{matrix}\right]$
#+end_export

The desired output:

#+RESULTS:
#+begin_export latex
$\left[\begin{matrix}0.435551782541394 & 0.653831083538496 & 0.703284715123126 & 0.779211763281097\\0.745624842540662 & 0.382867491810448 & 0.0640634444192878 & 0.205350088572431\\0.455263877780481 & 0.782880235084324 & 0.190229654979851 & 0.731404270938654\\0.13207468759024 & 0.0418823433240818 & 0.617596076042993 & 0.648004941561776\end{matrix}\right]$
$\left[\begin{matrix}0.435551782541394 & 0.653831083538496 & 0.703284715123126 & 0.779211763281097\\0 & -0.736431563440805 & -1.13989570807275 & -1.12858923067965\\0 & -1.38777878078145 \cdot 10^{-17} & -0.698831926546978 & -0.235493658356284\\0 & 0 & 0 & 0.433555029735554\end{matrix}\right]$
#+end_export
6
  • 1
    I'm willing to try some more but you will have to help me: how is it that your code block knows about the np module? You must have import numpy as np somewhere, so that seems to be missing from your question, which makes the code block barf with errors when evaluated. Please make sure that your example is complete. I should be able to cut and paste it into a file and do C-c C-c on it to evaluate it without errors (possibly after installing some things, but you have to tell us that too).
    – NickD
    Commented Jul 29, 2022 at 2:09
  • 1
    Updated question with a minimal working example. My apologies.
    – Derrekito
    Commented Jul 29, 2022 at 20:53
  • Excellent! Thank you.
    – NickD
    Commented Jul 30, 2022 at 1:39
  • 1
    Unfortunately, I still cannot run your code block. I get NameError: name 'latex' is not defined from this line: print("$"+latex(Matrix(format_mat(mat.copy(),N)))+"$"). If I need to install something else to make this work, you will have to tell me.
    – NickD
    Commented Jul 30, 2022 at 1:55
  • 1
    It looks like the Jupyter back end kept some of the libraries in cache while I culled back dependencies and I didn't realize I have to close emacs (I'm guessing there's a way to purge) for the state to fully refresh. Thanks for catching that. I added "from sympy import *" and "init_printing()" which should solve that issue. (Edit: I just copied and pasted the code I POSTED into a scratch buffer and verified it should work for you.)
    – Derrekito
    Commented Jul 30, 2022 at 2:19

2 Answers 2

1

Suggested solution

Add the following two sections at the end of your file:

...

* Code                                                                                                        :noexport:

#+begin_src elisp
    (defun ndk/clean-up-latex-export-blocks (text backend info)
         ""
         (when (org-export-derived-backend-p backend 'latex)
           (replace-regexp-in-string "#\\+begin_example\n" ""
                                     (replace-regexp-in-string "#\\+end_example\n" "" text))))

    (add-to-list 'org-export-filter-export-block-functions
                    #'ndk/clean-up-latex-export-blocks)


#+end_src

* Local variables                                                                                             :noexport:

# Local Variables:
# org-babel-min-lines-for-block-output: 0
# End:

Then save the file, kill the buffer and reopen the file. Now try exporting to LaTeX/PDF again with C-c C-e l o.

Note that the two sections have been tagged noexport so they are never exported.

A more detailed explanation

The OP is correct in stating that the previous answer replaces one ill by another: it does get rid of the literalizing : at the beginning of each output line at the expense of surrounding the whole thing in an example block. AFAICT, there is no way to influence the output so that we get neither.

We are left with the option of postprocessing the output. Org mode can apply an extensive set of filters to specific portions of the exported output (or to the whole shebang if desired). See the Advanced Export Configuration section in the manual.

These filters are functions of three variables, text, backend and info: the text variable is the raw output of the exporter (possibly processed through earlier filters: if there are multiple filters, the output of each filter is the input of the next filter - as an analogy, think of "filters" like grep and sed on a command-line pipeline). Org mode keeps track of them in a set of variables named org-export-filter-TYPE-functions where TYPE is the filter type as described in the manual reference above. These variables are lists of filters, nil by default (i.e. no filtering). You then write a filter function and add it to the appropriate variable.

In the above instance, we want the filter to be applied to export blocks, so we use the org-export-filter-export-block-functions list to add our filter to. The filter itself looks for the #+begin_example and #+end_example lines in the input text and deletes them in the output text. Note that the filter is only applied if we are exporting to LaTeX and only to #+begin_export blocks.

The Local variables section makes use of a standard and very useful Emacs mechanism to set variables that will be buffer-local to this file only -- see the Specifying file variables section in the Emacs manual.

When you first open the file, you will be prompted about the local variables (they can be a security hazard if you open a malicious file). You can bypass the warning on subsequent occasions by typing ! to the prompt - read the message that you get so that you understand what is happening.

It is possible to write a filter to get rid of the literalizing : characters and it would be very similar to the above filter and would not need the local variable. I decided that it was worth doing it the way I did it, because there is less chance of the filter doing damage: the characters : are far more common in ordinary text than #+begin_example and #+end_example. But IMO, the best thing to do is to set the org-babel-min-lines-for-block-output variable to 0 in your init file and always have the example block to deal with.

1
  • 1
    This works! And it's not an inconvenient way to post-process. I was thinking about running shell scripts manually to strip out undesirable lines/characters. This is a much better solution. Also, thank you for pointing out the documentation for this. Your answer is incredibly detailed. Thank you very much!
    – Derrekito
    Commented Jul 30, 2022 at 16:55
1

NB See the other answer for a complete solution. Although this answer gets rid of the literalizing : characters, the result is wrapped in an example block and (AFAICT) there is no way to get rid of that. The other answer shows how to postprocess that output to get rid of the example block.


I do not think that this will solve all your problems (there are missing imports and undefined things in the code block AFAICT, which make evaluation of it abort with errors). But on the matter of the colons, you should be able to avoid them by setting org-babel-min-lines-for-block-output to 0 in your init file and restarting emacs:

(setq org-babel-min-lines-for-block-output 0)

The doc string for the variable (C-h v org-babel-min-lines-for-block-output) says:

org-babel-min-lines-for-block-output is a variable defined in ‘ob-core.el’.

Its value is 10

The minimum number of lines for block output.
If number of lines of output is equal to or exceeds this
value, the output is placed in a #+begin_example...#+end_example
block.  Otherwise the output is marked as literal by inserting
colons at the starts of the lines.  This variable only takes
effect if the :results output option is in effect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.