Changing page orientation in word using Quarto? - r

Is there a way of changing the page orientation for specific segments of a document when using Quarto and rendering to Word?
The ideal approach would be something similar to BLOCK_LANDSCAPE_START/BLOCK_LANDSCAPE_STOP from officedown.
But also interested in other approaches (for example using the reference-doc).

There's no unified solution for this yet, but you can get around by using a custom Lua filter. Store the filter given below to a file, say docx-landscape.lua, and then use it by listing it under filters in the document's YAML section. Use a fenced div with class landscape to mark content that should appear in landscape mode.
E.g.:
---
title: "Nullus"
filters:
- docx-landscape.lua
---
This is in portrait mode.
::: landscape
This should appear in landscape mode.
:::
Things should be back to normal here.
where the filter docx-landscape.lua contains
local ooxml = function (s)
return pandoc.RawBlock('openxml', s)
end
local end_portrait_section = ooxml
'<w:p><w:pPr><w:sectPr></w:sectPr></w:pPr></w:p>'
local end_landscape_section = ooxml [[
<w:p>
<w:pPr>
<w:sectPr>
<w:pgSz w:h="11906" w:w="16838" w:orient="landscape" />
</w:sectPr>
</w:pPr>
</w:p>
]]
function Div (div)
if div.classes:includes 'landscape' then
div.content:insert(1, end_portrait_section)
div.content:insert(end_landscape_section)
return div
end
end
The filter takes a few shortcuts, but should work ok in most cases. Please let me know about any issues with it.
Addendum: if you prefer officedown commands, then append the following to the filter to make those commands work:
function RawBlock (raw)
if raw.text:match 'BLOCK_LANDSCAPE_START' then
return end_portrait_section
elseif raw.text:match 'BLOCK_LANDSCAPE_STOP' then
return end_landscape_section
end
end

Related

Identing a map from a yaml template in terraform

I am in Terraform 14 and I am trying to add labels to my template file which should generate a YAML:
Template File:
labels:
${labels}
Code:
locals {
labels = merge(
var.labels,
map(
"module", basename(abspath(path.module)),
"module_version", var.module_version
)
)
prometheus_config = templatefile("${path.module}/prometheus.tmpl", {
labels = indent(8, yamlencode(local.labels))
})
When I try to add the labels indenting with 8 this outputs in the template file causing YAML errors:
Error Output:
labels:
"module": "my_module"
"module_version": "1.0"
As you can see the module_version has indent 8 which is correct but the module line is not indented.
I tried many things like moving ${labels} everywhere in the beginning, with multiple indentations but nothing seems to work.
It is for this reason that the templatefile documentation recommends using yamlencode for the entire data structure, rather than trying to concantenate bits of YAML together using just string templates. That way the yamlencode function can guarantee you a correctly-formatted result and you only have to produce a suitable data structure:
In your case, that would involve replacing the template contents with the following:
${yamlencode({
labels = labels
})}
...and then replacing the prometheus_config definition with the following:
locals {
prometheus_config = templatefile("${path.module}/prometheus.tmpl", {
labels = local.labels
})
}
Notice that the yamlencode call is now inside the template, and it covers the entire YAML document rather than just a fragment of it.
With a simple test configuration I put together with some hard-coded values for the variables you didn't show, I got the following value for local.prometheus_config:
"labels":
"module": "example"
"module_version": "1.0"
If this was a full example of the YAML you are aiming to generate then I might also consider simplifying but just inlining the yamlencode call directly inside the local value definition, and not have the separate template file at all:
locals {
prometheus_config = yamlencode({
labels = local.labels
})
}
If the real YAML is much larger or is likely to grow larger later then I'd probably still keep that templatefile call, but I just wanted to note this for completeness, since there's more than one way to get this done.
So using terraform 14 I was not able to transform lists or maps into yaml with yamlencode. Every option I tried using the suggested answer produced results with the wrong indentation. Maybe due to the many indentation levels in the file... I am not sure. So I dropped the use of yamlencode in the solution.
Solution:
I decided to use inline solution so for lists I transform then with string with join and for maps I use jsonencode so:
# var.list is a list in terraform
# local.abels is a map in terraform
thanos_config = templatefile("${path.module}/thanos.tmpl", {
urls = join(",", var.list),
labels = jsonencode(local.labels)
})
The resulting plan output is a bit ugly but it works.

How does one use a CDSView with MultiLine on GMAPPlot?

(First Question so apologies)
Bokeh 1.3.4
Situation:
I am trying top map a Bokeh MultiLine using a CDSView and all the existing examples seem to use the "figure" object which has a helper (multi_line) which accepts a view as an argument. I am doing this on top of a GMAPPlot which does not support multi_line (only MultiLine) (see below). The commented out line throws an error saying GMAPPlot does not support multi_line.
plot = GMapPlot(
x_range=Range1d(), y_range=Range1d(), map_options=map_options, sizing_mode='scale_height'
)
.
.
.
sel_sa1s = []
v_bf = [True if sa1_val in sel_sa1s else False for sa1_val in v_source.data['SA1']]
v_view = CDSView(source=v_source, filters=[BooleanFilter(v_bf)])
v_ml = MultiLine(xs="xs",ys="ys",line_color="black", line_width="w")
#v_rend = plot.multi_line(xs="xs",ys="ys",line_color="black", line_width="w", source=v_source, view=v_view)
v_rend = plot.add_glyph(v_source, v_ml, name='votes')
The snippet shown above works and maps the entire network (very crowded) because there is no filter. What I want to have happen is for the filter to be initialised to hide everything then when the user clicks on an area (SA1) it will display the network related to that SA1.
Actually I can do that but only one area at a time and it would be much more efficient to be able to load the whole map and use a filtered view to control which sub-networks are displayed.
It seems that GMAPPlot only likes the pattern:
create glyph
add glyph
So, my question is - how does one use a CDSView in this environment (how does one add it to the renderer?)
Screenshot of unfiltered data set
It seems that GMAPPlot only likes the pattern:
create glyph
add glyph
That has not been true for some time. There is a higher level bokeh.plotting.gmap function that creates and configures GMapPlot instances with deafult axes, etc, and also has all the same methods and conveniences as figure (e.g. multi_line). It will be much less work to go this route than assembling everything by hand from low-level objects.

Command-line equivalent of CSS filter

I'm currently working with pictures and I try to do the same thing as the CSS filter below but in command line:
filter: invert(0.86) hue-rotate(180deg);
To do the trick I used imagemagick's convert tool.
convert $in -evaluate add -26% -negate -modulate 100,100,0 $out
I get close to the result I expect, but I have a huge quality drop. Let's show this in an example
Original version (a random jpg image)
Clean version (made with CSS, expected result)
Dirty one, made with convert
Is there any way (with this tool or another) to convert my image smoothly? The best would be to directly apply css to this image but I don't know whether it's possible in commandline...

Jupyter Notebook different ways to display out

There seems to be 3 ways to display output in Jupyter:
By using print
By using display
By just writing the variable name
What is the exact difference, especially between number 2 and 3?
I haven't used display, but it looks like it provides a lot of controls. print, of course, is the standard Python function, with its own possible parameters.
But lets look at a simple numpy array in Ipython console session:
Simply giving the name - the default out:
In [164]: arr
Out[164]: array(['a', 'bcd', 'ef'], dtype='<U3')
This is the same as the repr output for this object:
In [165]: repr(arr)
Out[165]: "array(['a', 'bcd', 'ef'], dtype='<U3')"
In [166]: print(repr(arr))
array(['a', 'bcd', 'ef'], dtype='<U3')
Looks like the default display is the same:
In [167]: display(arr)
array(['a', 'bcd', 'ef'], dtype='<U3')
print on the other hand shows, as a default, the str of the object:
In [168]: str(arr)
Out[168]: "['a' 'bcd' 'ef']"
In [169]: print(arr)
['a' 'bcd' 'ef']
So at least for a simple case like this the key difference is between the repr and str of the object. Another difference is which actions produce an Out, and which don't. Out[164] is an array. Out[165] (and 168) are strings. print and display display, but don't put anything on the Out list (in other words they return None).
display can return a 'display' object, but I won't get into that here. You can read the docs as well as I can.

Multiline Comment Workarounds?

I (sort of) already know the answer to this question. But I figured it is one that gets asked so frequently on the R Users list, that there should be one solid good answer. To the best of my knowledge there is no multiline comment functionality in R. So, does anyone have any good workarounds?
While quite a bit of work in R usually involves interactive sessions (which casts doubt on the need for multiline comments), there are times when I've had to send scripts to colleagues and classmates, much of which involves nontrivial blocks of code. And for people coming from other languages it is a fairly natural question.
In the past I've used quotes. Since strings support linebreaks, running an R script with
"
Here's my multiline comment.
"
a <- 10
rocknroll.lm <- lm(blah blah blah)
...
works fine. Does anyone have a better solution?
You can do this easily in RStudio:
select the code and click CTR+SHIFT+C
to comment/uncomment code.
This does come up on the mailing list fairly regularly, see for example this recent thread on r-help. The consensus answer usually is the one shown above: that given that the language has no direct support, you have to either
work with an editor that has region-to-comment commands, and most advanced R editors do
use the if (FALSE) constructs suggested earlier but note that it still requires complete parsing and must hence be syntactically correct
A neat trick for RStudio I've just discovered is to use #' as this creates an self-expanding comment section (when you return to new line from such a line or insert new lines into such a section it is automatically comment).
[Update] Based on comments.
# An empty function for Comments
Comment <- function(`#Comments`) {invisible()}
#### Comments ####
Comment( `
# Put anything in here except back-ticks.
api_idea <- function() {
return TRUE
}
# Just to show api_idea isn't really there...
print( api_idea )
`)
####
#### Code. ####
foo <- function() {
print( "The above did not evaluate!")
}
foo()
[Original Answer]
Here's another way... check out the pic at the bottom. Cut and paste the code block into RStudio.
Multiline comments that make using an IDE more effective are a "Good Thing", most IDEs or simple editors don't have highlighting of text within simple commented -out blocks; though some authors have taken the time to ensure parsing within here-strings. With R we don't have multi-line comments or here-strings either, but using invisible expressions in RStudio gives all that goodness.
As long as there aren't any backticks in the section desired to be used for a multiline comments, here-strings, or non-executed comment blocks then this might be something worth-while.
#### Intro Notes & Comments ####
invisible( expression( `
{ <= put the brace here to reset the auto indenting...
Base <- function()
{ <^~~~~~~~~~~~~~~~ Use the function as a header and nesting marker for the comments
that show up in the jump-menu.
--->8---
}
External <- function()
{
If we used a function similar to:
api_idea <- function() {
some_api_example <- function( nested ) {
stopifnot( some required check here )
}
print("Cut and paste this into RStudio to see the code-chunk quick-jump structure.")
return converted object
}
#### Code. ####
^~~~~~~~~~~~~~~~~~~~~~~~~~ <= Notice that this comment section isnt in the jump menu!
Putting an apostrophe in isn't causes RStudio to parse as text
and needs to be matched prior to nested structure working again.
api_idea2 <- function() {
} # That isn't in the jump-menu, but the one below is...
api_idea3 <- function() {
}
}
# Just to show api_idea isn't really there...
print( api_idea )
}`) )
####
#### Code. ####
foo <- function() {
print( "The above did not evaluate and cause an error!")
}
foo()
## [1] "The above did not evaluate and cause an error!"
And here's the pic...
I can think of two options. The first option is to use an editor that allows to block comment and uncomment (eg. Eclipse). The second option is to use an if statement. But that will only allow you to 'comment' correct R syntax. Hence a good editor is the prefered workaround.
if(FALSE){
#everything in this case is not executed
}
If find it incredible that any language would not cater for this.
This is probably the cleanest workaround:
anything="
first comment line
second comment line
"
Apart from using the overkilled way to comment multi-line codes just by installing RStudio, you can use Notepad++ as it supports the syntax highlighting of R
(Select multi-lines) -> Edit -> Comment/Uncomment -> Toggle Block Comment
Note that you need to save the code as a .R source first (highlighted in red)
I use vim to edit the R script.
Let's say the R script is test.R, containing say "Line 1", "Line 2", and "Line 3" on 3 separate lines.
I open test.R on the command line with Vim by typing "vim test.R".
Then I go to the 1st line I want to comment out, type "Control-V", down arrow to the last line I want to comment out, type a capital I i.e. "I" for insert, type "# ", and then hit the Escape key to add "# " to every line that I selected by arrowing down. Save the file in Vim and then exit Vim by typing ":wq". Changes should show up in Rstudio.
To delete the comments in Vim, start at the first line on top of the character "#" you want to delete, again do "Control-V", and arrow down to the last line you want to delete a "#" from. Then type "dd". The "#" signs should be deleted.
There's seconds-worth of lag time between when changes to test.R in Vim are reflected in Rstudio.
Now there is a workaround, by using package ARTofR or bannerCommenter
Examples here:
In RStudio an easy way to do this is to write your comment and once you have used CTRL + Shift + C to comment your line of code, then use CTRL + SHIFT + / to reflow you comment onto multiple lines for ease of reading.
In RStudio you can use a pound sign and quote like this:
#' This is a comment
Now, every time you hit return you don't need to add the #', RStudio will automatically put that in for you.
Incidentally, for adding parameters and items that are returned, for standardization if you type an # symbol inside those comment strings, RStudio will automatically show you a list of codes associated with those comment parameters:
#' #param tracker_df Dataframe of limit names and limits
#' #param invoice_data Dataframe of invoice data
#' #return return_list List of scores for each limit and rejected invoice rows

Resources