From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0.migadu.com ([2001:41d0:403:58f0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms13.migadu.com with LMTPS id gCtFN5JxgWfZ+gAAqHPOHw:P1 (envelope-from ) for ; Fri, 10 Jan 2025 19:14:27 +0000 Received: from aspmx1.migadu.com ([2001:41d0:403:58f0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0.migadu.com with LMTPS id gCtFN5JxgWfZ+gAAqHPOHw (envelope-from ) for ; Fri, 10 Jan 2025 20:14:27 +0100 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=berkeley.edu header.s=google header.b="J9IWjoS/"; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=reject) header.from=berkeley.edu ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1736536466; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=zwi7rAIglM8YKo253Gop96lOGVtSGfkbOeXmnt1niVk=; b=LNZr7y66xJEna12YYsTDoEj1fPkrOUjL6a79dR/+WOTSaomjnPCWzVmcTHlLmomueWcLhx HA4yTytCpot7keQbTui6DoSlUs7RqwY7PrOMdoVgGWWm4kgXtkrvyaZomwBjM6q3HqZvxJ CUNvbbQRHLwMYyRKb7TG/kWnZfEMuCGjYIQcEFoN/IoseTTXAlTC3zxMqUeR/KzL/PJqKo HElmbDdKMo8w6Q3DrfYegEt47nudbTCWHw+vSPPXn6EiuXRL6AIR2K+pxR/Hg+atABWuzG BLyFdT+bFzSf08xAVK6jEA7nMzyMVPJJkKiinpXkDlxyGivH7ev7wWC/bUHARw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=berkeley.edu header.s=google header.b="J9IWjoS/"; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=reject) header.from=berkeley.edu ARC-Seal: i=1; s=key1; d=yhetil.org; t=1736536466; a=rsa-sha256; cv=none; b=pkxwHxUPOhzDXzZifY4TpnHHxRbT2TSg0Xxo/LKnSrJD+DODnNn5Qz7Lg5mMYAEh6qzSfW JmXibuZCJcl+ryAH0iZgGFPITCfdeDAYID9FJX3qZ98aidP+K83vnDQHQ9PNQq//Thfvp5 S+8aNvKfncNAjPoUwnRn3VRDtakTx7c4/i1MkUBhp8hq4ywH+zqJxNjfw6NRCuNmb2wsmE 5C01CaRxXQZhylPgYLGOc6KvTvFLxWceEgX7WTHsL99KLr2uY1c8roRV9exhkB9Idlixcr Efxdd3NvNskTAUTageFZgG7OxTcBsVMqG90UHEa4i0X27cqHaObv0q+v0ywHxg== Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 81BB18FF39 for ; Fri, 10 Jan 2025 20:14:25 +0100 (CET) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tWKK4-0001iu-39; Fri, 10 Jan 2025 14:05:36 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tWKJo-0001gT-JF for emacs-orgmode@gnu.org; Fri, 10 Jan 2025 14:05:24 -0500 Received: from mail-pl1-x643.google.com ([2607:f8b0:4864:20::643]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tWKJk-0003Yf-2o for emacs-orgmode@gnu.org; Fri, 10 Jan 2025 14:05:15 -0500 Received: by mail-pl1-x643.google.com with SMTP id d9443c01a7336-2156e078563so35676155ad.2 for ; Fri, 10 Jan 2025 11:05:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=berkeley.edu; s=google; t=1736535908; x=1737140708; darn=gnu.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=zwi7rAIglM8YKo253Gop96lOGVtSGfkbOeXmnt1niVk=; b=J9IWjoS/uVth5L3NeFCHw/WFNHPNFT03xaSB5vXsAujyTIEW9ko8+g1zxRHeE4+52G yazGWElzytHBKmcwn6bbIz1q8xhnFsdk23CIUAp4Vf/l1wW8dJXSnxf0Ts0bGKAmwBMx y6H6rpLFRzMZkP/doMllK6xlXDjlXacl+pprPWR/pAU+e+q4wZ8FXzgiR3ct1tVEli02 FwSG5zJMG/8Xng1k4ftTU/vVrKelvdHaap615Z1lUCqr46TCxsSdFq5lPajq49K5u080 F+XbCMHU9EkaPKhwUvt5I2yn76sISqWsW5tbuFqI2Q80IJSYwbeZhdggHRo8cfSp6Z4S Fd0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736535908; x=1737140708; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=zwi7rAIglM8YKo253Gop96lOGVtSGfkbOeXmnt1niVk=; b=fHW6WefDCtwJnHKNq5wEgzJyDeLBMpg3E9Kb782dHR2xe8Z7yQw69yWJCuS1ozvXHU /Gv13Pl+F3OHuijd9ZPqL7ybjO5/WeTmu/eDnZN7UQDVyiz5g6DaB7eGRmalRrCBSy7X 2uE5EC5ksrSPkULcxj+1HsYJ/HgTSAVc8nqxrQfmK9yhONj1W5FZmIeGjhV6PzeAaPdv ZY2M6an8I6nnYagPQOdSKO6Bmw8iT52lRLyHqK7S9vwSvpCwm5fnRrzHvqlnPmFF+moG naKWlL1+ZaetkYyERLa6SJPFkEF3GBItFYo3uJ+nAP8hJJcf7GjPi98o74+oawkK7fAn GD1g== X-Gm-Message-State: AOJu0YyPEIy5aNawiJQ6fDXfImJEQhXmfrofXwU3VYUheHOPdRNVJWeA 5HYGO2GLNQgdBjegBs95eRAwMpVkZAD7/zoIdrAI1+rcSsLpzZ7jq/qmg2n0o4mM7Q8YjLsn9XZ doJ7T X-Gm-Gg: ASbGncu15okdJkJKmYi7z2FXKH3krnBUi5JyQtLOjxRaNi9sfUiEY3nmfsqtv+dC2SY Qr+Oh7DxFP+elhJanMTfbTM2J2R9fUNI0/oHAX4m2gQqXzNs4NQ/V9cMccjnKDv89FHsIH9dsg/ hsGXtLbcg0sUufXRugnHSlDT0rkk31j2A0J30Dk27x6nn61MQCBxg1M3TKkrp4bEqUomvgOsfq3 yPtFGUtyetxV5/fxu4R5Nuvdsc5acQAqZ84FXWuG0gza+1lfsYcmlDQQ+uB0kSfAGdxqIUL6/Wh khtRbvJLn66kSx919ctG4scHfRKgUOlMeQ7f/NcZQO97r5Y= X-Google-Smtp-Source: AGHT+IF1scuTqBTL+XnJvmfz9kSWQrK4mtK8GuETZ1h6R9dUthcL3n7Dj1RYFm9IbT1lOkBLDZbHMg== X-Received: by 2002:a05:6a00:3019:b0:725:f376:f4f4 with SMTP id d2e1a72fcca58-72d21f477f0mr17651178b3a.13.1736535908086; Fri, 10 Jan 2025 11:05:08 -0800 (PST) Received: from smtpclient.apple (157-131-199-171.fiber.dynamic.sonic.net. [157.131.199.171]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-a31d5047e95sm3102896a12.67.2025.01.10.11.05.07 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Jan 2025 11:05:07 -0800 (PST) From: Richard H Stanton Message-Id: <5BD57C55-9277-4F5C-B1D7-765393C81DE4@berkeley.edu> Content-Type: multipart/alternative; boundary="Apple-Mail=_FE899B90-7B68-4385-BD9D-3CAB6BAD960F" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.300.87.4.3\)) Subject: Re: How to specify column alignment in LaTeX table output? Date: Fri, 10 Jan 2025 11:04:56 -0800 In-Reply-To: Cc: emacs-orgmode@gnu.org To: Rens Oliemans References: <87wmf4qoju.fsf@rensoliemans.nl> <9F2C7295-E505-47DA-BF76-078F0C28B9E6@berkeley.edu> <87wmf3vw3i.fsf@rensoliemans.nl> X-Mailer: Apple Mail (2.3826.300.87.4.3) Received-SPF: pass client-ip=2607:f8b0:4864:20::643; envelope-from=rhstanton@berkeley.edu; helo=mail-pl1-x643.google.com X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.369, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: emacs-orgmode-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-Migadu-Scanner: mx11.migadu.com X-Migadu-Spam-Score: -3.25 X-Spam-Score: -3.25 X-Migadu-Queue-Id: 81BB18FF39 X-TUID: pZLq4s3cPtqi --Apple-Mail=_FE899B90-7B68-4385-BD9D-3CAB6BAD960F Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On Jan 10, 2025, at 8:59=E2=80=AFAM, Richard H Stanton = wrote: >=20 >>=20 >> On Jan 10, 2025, at 1:47=E2=80=AFAM, Rens Oliemans = wrote: >>=20 >> Richard H Stanton writes: >>=20 >>> what are the recommended headers for a Python code block that = exports a table? For example, ":results output raw=E2=80=9D and = ":results output drawer=E2=80=9D both seem to work (without :wrap), = while =E2=80=9C:results output=E2=80=9D puts everything in an example = block, which then seems to get exported verbatim, not as a LaTeX table. >>=20 >> Take a look at >> = https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-python.html. = I found >> this link in the Org manual, "(org) Results of Evaluation", and then = to >> "Documentation" link of python. =46rom that page: >>=20 >> :results {output, value}: Output results come from whatever the = python code >> prints on stdout. Value results are the value of the last = expression >> evaluated in the code block. Value mode is the default (as with = other >> languages). In value mode you can use the following subtypes: >>=20 >> verbatim: value is returned as string. In particular, use this = to >> prevent conversion of lists and tuples to tables. >>=20 >> table: (Org 9.7+) Try to convert the result to an Org table. = Dicts, >> numpy arrays, and pandas DataFrames/Series can be returned as = tables >> this way (by default, they are printed verbatim). Note that = lists and >> tuples are already converted to table by default (use verbatim = to >> prevent that). >>=20 >> So, ':results output' will output whatever python prints to stdout. = With >> 'print()', I think that this will just be a string, and no conversion = will take >> place. If you specify 'output raw', python will still just print the = string, but >> *Org mode* will now interpret it as raw Org mode. This will probably = work fine, >> but you'll have to add '|' and newlines in your string correctly. = Alternative: >>=20 >> ':results value', the default. In this case ob-python will convert = lists and >> tuples to tables by default (and optionally, dicts and DataFrames as = well). >>=20 >> That would be my recommendation: a code block with the default = headers, which >> returns a list of lists. I've attached an org file which does this. >>=20 >>> I actually generate this table from a Python code block. In the = past, I=E2=80=99ve often run into problems with raw output (like this), = where running the code block multiple times causes the output to appear = multiple times, rather than overwriting. >>=20 >> ':results append' will cause the output to appear multiple times, but = I expect >> that it happened due to other circumstances (':results replace' is = default and I >> expect you didn't change that). One such circumstance is when you, = say, add a >> ':results output' header argument, and then change it back. For = reasons unknown >> to me, Org mode will then see the previous #+RESULTS: block as = unrelated to the >> current one, and will not replace it. >>=20 >> This is then kind of annoying, because you'll have to add the = #+ATTR_LATEX: line >> to the table again. I'd fix this manually, but if it gets annoying = you can use >> the suggestion by PA. >=20 >=20 > Thanks, Rens. Lots of useful information! >=20 > Regarding output appearing multiple times, I realize it=E2=80=99s not = tables that are the prime offender. It=E2=80=99s more when I=E2=80=99m = outputting text, usually trying to get Python to generate LaTeX code, = e.g., after symbolically solving a system of equations in Python. >=20 > Here=E2=80=99s an example: >=20 > #+begin_src python :results output replace raw=20 > print("a") > #+end_src >=20 > Every time I run this code block, I get another line containing = =E2=80=9Ca=E2=80=9D. If I don't use the raw option, e.g., >=20 > #+begin_src python :results output > print("a") > #+end_src >=20 > the multiple-output problem goes away, but now it appears as=20 >=20 > #+RESULTS: > : a >=20 > The extra =E2=80=9C: =E2=80=9C interferes with LaTeX if I=E2=80=99ve = just output something like =E2=80=9C\begin{equation}=E2=80=9D, which is = why I=E2=80=99m using raw in the first place. >=20 > Wrapping the output in a LaTeX environment helps, e.g., >=20 > #+begin_src python :results output raw :wrap flushleft > print("a") > #+end_src >=20 > But is there a =E2=80=9Cpreferred=E2=80=9D way to output arbitrary = text (e.g., LaTeX equations) from Python code blocks so that they = compile fine *and* don=E2=80=99t append? >=20 > Thanks for this discussion. This is about where I get to every time I = think I want to use org mode to create LaTeX documents with embedded, = live calculations, and then after wrestling with the headers for a while = I tend to go back again to separate .py and .tex files controlled by GNU = Make=E2=80=A6 After a bit of experimentation, I think the solution is to put results = in a drawer, e.g., #+begin_src python :results output raw drawer print("a") #+end_src This produces #+RESULTS: :results: a :end: This exports to LaTeX vey nicely and (I assume because it's obvious = where the end is) org doesn=E2=80=99t over-write when you rerun the code = block. Just one more thing that might be helpful: I run various packages that = fold and/or hide drawers because most of the time I don=E2=80=99t want = to see them. But now I *do* want to see :results: drawers. So I created = some functions (with the help of ChatGPT) to make sure :results: drawers = are always visible: =E2=80=94=E2=80=94 (defun org-open-drawer-if-closed () (interactive) "Open the drawer at point if it is closed." (when (and (looking-at org-drawer-regexp) (not (org-at-item-p))) (save-excursion (let ((element (org-element-at-point))) (when (eq (org-element-type element) 'drawer) (org-flag-drawer nil)))))) (defun my-org-unfold-results-drawers (&optional state) "Unfold all :results: drawers in the current buffer. STATE is ignored and is only present to match the signature for = functions used in `org-cycle-hook`." (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward "^[ \t]*:results:$" nil t) ;; Go to the beginning of the line with :results: (beginning-of-line) ;; Unfold the drawer using org-cycle (org-open-drawer-if-closed) ;; Move forward to avoid toggling the same drawer again (forward-line)))) (add-hook 'org-mode-hook (lambda () (my-org-unfold-results-drawers) (add-hook 'org-cycle-hook #'my-org-unfold-results-drawers))) =E2=80=94=E2=80=94 --Apple-Mail=_FE899B90-7B68-4385-BD9D-3CAB6BAD960F Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8
On Jan 10, 2025, = at 8:59=E2=80=AFAM, Richard H Stanton <rhstanton@berkeley.edu> = wrote:


On Jan = 10, 2025, at 1:47=E2=80=AFAM, Rens Oliemans = <hallo@rensoliemans.nl> wrote:

Richard H Stanton = <rhstanton@berkeley.edu> writes:

what are the recommended headers for a Python code block = that exports a table? For example, ":results output raw=E2=80=9D and = ":results output drawer=E2=80=9D both seem to work (without :wrap), = while =E2=80=9C:results output=E2=80=9D puts everything in an example = block, which then seems to get exported verbatim, not as a LaTeX = table.

Take a look = at
https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-python.h= tml. I found
this link in the Org manual, "(org) Results of = Evaluation", and then to
"Documentation" link of python. =46rom that = page:

  :results {output, value}: Output results come = from whatever the python code
  prints on stdout. Value = results are the value of the last expression
  evaluated in = the code block. Value mode is the default (as with = other
  languages). In value mode you can use the following = subtypes:

      verbatim: value is = returned as string. In particular, use this = to
      prevent conversion of lists = and tuples to tables.

      table: = (Org 9.7+) Try to convert the result to an Org table. = Dicts,
      numpy arrays, and pandas = DataFrames/Series can be returned as = tables
      this way (by default, they = are printed verbatim). Note that lists = and
      tuples are already converted = to table by default (use verbatim = to
      prevent that).

So, = ':results output' will output whatever python prints to stdout. = With
'print()', I think that this will just be a string, and no = conversion will take
place. If you specify 'output raw', python will = still just print the string, but
*Org mode* will now interpret it as = raw Org mode. This will probably work fine,
but you'll have to add = '|' and newlines in your string correctly. Alternative:

':results = value', the default. In this case ob-python will convert lists = and
tuples to tables by default (and optionally, dicts and DataFrames = as well).

That would be my recommendation: a code block with the = default headers, which
returns a list of lists. I've attached an org = file which does this.

I actually = generate this table from a Python code block. In the past, I=E2=80=99ve = often run into problems with raw output (like this), where running the = code block multiple times causes the output to appear multiple times, = rather than overwriting.

':results append' will = cause the output to appear multiple times, but I expect
that it = happened due to other circumstances (':results replace' is default and = I
expect you didn't change that). One such circumstance is when you, = say, add a
':results output' header argument, and then change it = back. For reasons unknown
to me, Org mode will then see the previous = #+RESULTS: block as unrelated to the
current one, and will not = replace it.

This is then kind of annoying, because you'll have to = add the #+ATTR_LATEX: line
to the table again. I'd fix this manually, = but if it gets annoying you can use
the suggestion by = PA.


Thanks, Rens. Lots of = useful information!

Regarding output appearing multiple times, I realize it=E2=80= =99s not tables that are the prime offender. It=E2=80=99s more when = I=E2=80=99m outputting text, usually trying to get Python to generate = LaTeX code, e.g., after symbolically solving a system of equations in = Python.

Here=E2=80=99s an = example:

#+begin_src python = :results output replace raw 
print("a")
#+end_src

Every = time I run this code block, I get another line containing =E2=80=9Ca=E2=80= =9D. If I don't use the raw option, e.g.,

#+begin_src python :results output
print("a")
#+end_src

the = multiple-output problem goes away, but now it appears as 

#+RESULTS:
: = a

The extra =E2=80=9C: =E2=80= =9C interferes with LaTeX if I=E2=80=99ve just output something like = =E2=80=9C\begin{equation}=E2=80=9D, which is why I=E2=80=99m using raw = in the first place.

Wrapping the output in a LaTeX environment helps, = e.g.,

#+begin_src python = :results output raw :wrap flushleft
print("a")
#+end_src

But is = there a =E2=80=9Cpreferred=E2=80=9D way to output arbitrary text (e.g., = LaTeX equations) from Python code blocks so that they compile fine *and* = don=E2=80=99t append?

Thanks = for this discussion. This is about where I get to every time I think I = want to use org mode to create LaTeX documents with embedded, live = calculations, and then after wrestling with the headers for a while I = tend to go back again to separate .py and .tex files controlled by GNU = Make=E2=80=A6

After a bit of = experimentation, I think the solution is to put results in a drawer, = e.g.,

#+begin_src python :results output raw = drawer
print("a")
#+end_src

T= his = produces

#+RESULTS:
:results:
a
:end:

This exports to LaTeX vey = nicely and (I assume because it's obvious where the end is) org = doesn=E2=80=99t over-write when you rerun the code = block.

Just one more thing that might be = helpful: I run various packages that fold and/or hide drawers because = most of the time I don=E2=80=99t want to see them. But now I *do* want = to see :results: drawers. So I created some functions (with the help of = ChatGPT) to make sure :results: drawers are always = visible:

=E2=80=94=E2=80=94

<= div>
(defun org-open-drawer-if-closed ()
  = (interactive)
  "Open the drawer at point if it is = closed."
  (when (and (looking-at org-drawer-regexp) (not = (org-at-item-p)))
    = (save-excursion
      (let ((element = (org-element-at-point)))
        (when (eq = (org-element-type element) 'drawer)
      =     (org-flag-drawer = nil))))))


(defun = my-org-unfold-results-drawers (&optional state)
  = "Unfold all :results: drawers in the current buffer.
  =  STATE is ignored and is only present to match the signature for = functions used in `org-cycle-hook`."
  = (interactive)
  (save-excursion
    = (goto-char (point-min))
    (while = (re-search-forward "^[ \t]*:results:$" nil t)
    =   ;; Go to the beginning of the line with = :results:
      = (beginning-of-line)
      ;; Unfold the drawer = using org-cycle
      = (org-open-drawer-if-closed)
      ;; Move = forward to avoid toggling the same drawer again
    =   (forward-line))))

(add-hook = 'org-mode-hook
          (lambda = ()
            = (my-org-unfold-results-drawers)
        =     (add-hook 'org-cycle-hook = #'my-org-unfold-results-drawers)))



=E2=80=94=E2=80=94

<= div>

= --Apple-Mail=_FE899B90-7B68-4385-BD9D-3CAB6BAD960F--