How to process latex / tikz-timing diagrams in a PowerShell pipe? - powershell

I have several tikz-timing diagrams which I compile with a wrapper latex file. This wrapper uses the latex package standalone to produce a pdf and png file. I would like to spare all these wrapper files and replace them by only one. Additionally, I would like to pipe a list of filenames into a PowerShell function, which processes each waveform tex file which the general wrapper file.
I uploaded all files to Gist.
More in detail:
Waveform.tex is the wrapper tex file, which has a placeholder in an \input{...} macro. This placeholder is replaced by the PowerShell script.
\documentclass[convert={density=600,size=2000x800,outext=.png}]{standalone}
\usepackage[utf8]{inputenc} % UTF-8 tex file input incoding
\usepackage[T1]{fontenc} % Type1 font encoding
\usepackage[ngerman]{babel} % new german writing rules; must be loaded before microtype
\usepackage{courier} % set courier font as default for teletype writer (texttt, ttfamily, ...)
\usepackage[usenames,svgnames,table]{xcolor} % load colors and color-names
\usepackage{pgf} % primitive drawing library
\usepackage{tikz} % PGF frontend, drawing macros
\usepackage{tikz-timing} % spezial TikZ library for waveform/timing diagrams
\usetikztiminglibrary{nicetabs} % sublibrary for better looking timingtables
\begin{document}
\input{%%WaveformFile%%}
%\input{IICController} % uncomment this if timing-diagram is a fixed file name
\end{document}
IICController.tex is the example waveform:
%
\tikztimingmetachar{A}[1]{#1{Z[black]};}
%
\begin{tikztimingtable}[
timing/table/header/.style={font=\bf},
timing/wscale=2,
timing/nice tabs,
]
Master\_BusRequest & L H H 4H 4H 4H 4H L \\
Master\_BusGrant & L L H 4H 4H 4H 4H L \\
Master\_BusAbort & L L L 4L 4L 4L 4L L \\
Master\_WP\_Valid & L L L 4H 4H 4H 4H L \\
Master\_WP\_Data & A A A 4D{Phy Adr + R/W} 4D{Reg Adr} 4D{D0.0} 4D{D0.1} A \\
Master\_WP\_Last & L L L 4L 4L 4L 4H L \\
Master\_WP\_Ack & L L L 3LH 3LH 3LH 3LH L \\
\extracode
\tableheader{Signalname}{Signalverlauf}
\tablerules
\begin{background}[shift={(0.1,0)},help lines]
\vertlines{0,2,...,40}
\end{background}
\end{tikztimingtable}
And finally, here is my PowerShell script:
function Compile-Waveform
{ [CmdletBinding()]Param(
[Parameter(
Mandatory=$True,
Position=0,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[String[]]$InputFiles
)
Begin
{ $WrapperFile = "Waveform.tex"
$WrapperContent = Get-Content -Path $WrapperFile -Encoding ASCII -Raw
}
Process
{ #Write-Host "WrapperContent" -ForegroundColor Green
#Write-Host $WrapperContent -ForegroundColor Gray
#Write-Host ""
foreach($InputFile in $InputFiles)
{ Write-Host "processing file: '$Inputfile'" -ForegroundColor Yellow
$OutputFile = [String]$InputFile.Replace(".tex", ".png")
$Temp = $WrapperContent -replace "%%WaveformFile%%",$InputFile
#Write-Host "Temp" -ForegroundColor Green
#Write-Host $Temp -ForegroundColor Gray
#Write-Host ""
Write-Output $Temp | & 'C:\Program Files\MiKTeX 2.9\miktex\bin\x64\pdflatex.exe' -shell-escape -time-statistics -synctex=1 -interaction=nonstopmode
}
}
}
How to use the script?
Navigate to the folder of IICController.tex. Source the *.ps1 file and finally pipe all found waveform files into the PowerShell function:
cd d:\temp\waveform
. compile.ps1
dir IICController.tex | Compile-Waveform
Now pdflatex will print the error log:
processing file: 'D:\git\SATAController\doc\Waveforms\Simple.tex'
This is pdfTeX, Version 3.14159265-2.6-1.40.15 (MiKTeX 2.9 64-bit)
**entering extended mode
LaTeX2e <2014/05/01>
Babel <3.9l> and hyphenation patterns for 68 languages loaded.
! Emergency stop.
<*> ...600,size=2000x800,outext=.png}]{standalone}
! ==> Fatal error occurred, no output PDF file produced!
Transcript written on texput.log.
gross execution time: 26 ms
user mode: 0 ms, kernel mode: 15 ms, total: 15
puttex.log has the same content as the console output.
Has anyone an idea what is happening?
If I run Wavefom.tex with a fixed filename (see second \input line) in PowerShell, everything works fine.

Related

Why does powershell script from inno setup print spaces between each two characters?

I am running a powershell script from my inno setup installer via the command:
[Run]
Filename: {cmd}; Parameters: "/c powershell.exe -executionpolicy bypass -File ""{app}\InstallScripts\powershellScript.ps1""
and transcribing my commands/output to a text file by running the command:
StartTranscript -Path $logFile at the beginning of my script.
But in my log file which records all the commands/output I get really weird spaces between each pair of characters like so:
W i n d o w s P o w e r S h e l l T r a n s c r i p t S t a r t
S t a r t t i m e : 2 0 1 8 1 0 0 8 1 3 5 9 1 7
U s e r n a m e : D a v i d
But when I run the script manually I get the printings to the file normally, without the weird spaces.
Why is this happening and how can I correct it so when I run the script from my installer it will print the commands/output normally without these spaces between characters?

Powershell Subinacl.exe Double-Spaced Output, inability to capture summary information (statistics)

I try to run the following script on a remote machine, from the first line I get the normal output, "Command was successful" or something like that. For the second one it seems that its working, but the output its spaced and its not full, there are like 4 lines of output missing.
# This works as expected.
$output = Invoke-Command -ComputerName ServerName -ScriptBlock {auditpol /set /subcategory:"Registry" /success:enable /failure:enable}
# This creates double-spaced output and is missing the last 3 output lines.
$output = Invoke-Command -ComputerName ServerName -ScriptBlock {Subinacl.exe /verbose=1 /keyreg "HKEY_LOCAL_MACHINE\SYSTEM\Path" /sallowdeny="everyone"=SCD}
I want this output for the second code line:
SYSTEM\Path : delete Audit ACE 0 \everyone
SYSTEM\Path : new ace for \everyone
HKEY_LOCAL_MACHINE\SYSTEM\Path : 2 change(s)
Elapsed Time: 00 00:00:00
Done: 1, Modified 1, Failed 0, Syntax errors 0
Last Done : HKEY_LOCAL_MACHINE\SYSTEM\Path
But instead I get:
S Y S T E M \ P a t h : d e l e t e A u d i t A C E 0 \ e v e r y o n e
S Y S T E M \ P a t h : n e w a c e f o r \ e v e r y o n e
H K E Y _ L O C A L _ M A C H I N E \ S Y S T E M \ P a t h : 2 c h a n g e ( s )
Without the last 3 lines, which I want to see. I tried change the Output Encoding to Unicode or UTF8 but are not working. Any other solutions?
There are two unrelated problems:
(a) subinacl.exe produces UTF-16LE-encoded output.
(b) Its on-by-default /statistic option seems to write directly to the console, bypassing stdout, and therefore cannot be captured - or at least not easily; do tell us if you know how.
Therefore, the last block of lines containing statistics (summary information), which starts with Elapsed: ..., always prints to the console.
Related question subinacl get full output was prompted by the same problem.
(a), as stated, can be remedied by telling PowerShell what character encoding to expect when capturing output from external programs, via [Console]::OutputEncoding
(b) cannot be remedied if you do want to capture the statistics lines too; the next best thing is to suppress statistics output altogether with /nostatistic, which at least doesn't produce unwanted console output (but, obviously, you won't have the information at all).
Putting it all together:
$output = Invoke-Command -ComputerName ServerName -ScriptBlock {
# Tell PowerShell what character encoding to expect in subinacl's output.
[Console]::OutputEncoding = [Text.Encoding]::Unicode # UTF-16LE
# Note the addition of /nostatistic to suppress the direct-to-console summary info.
Subinacl.exe /nostatistic /verbose=1 /keyreg "HKEY_LOCAL_MACHINE\SYSTEM\Path" /sallowdeny="everyone"=SCD
}
Note: Normally, you'd restore the previous value of [Console]::OutputEncoding afterward, but since the session on the remote computer in which the script block runs ends right after, it isn't necessary here.
These tools don't often return proper object, hence your string output on the later.
You can work to handle that output differently than it's default and / or parse the string return to get the format you are after. Using the string cmdlets...
Get-Command -Name '*string*' | Format-Table -AutoSize
CommandType Name Version Source
----------- ---- ------- ------
Function ConvertFrom-SddlString 3.1.0.0 Microsoft.PowerShell.Utility
...
Function Format-String 1.3.6 PowerShellCookbook
...
Cmdlet ConvertFrom-String 3.1.0.0 Microsoft.PowerShell.Utility
Cmdlet ConvertFrom-StringData 3.1.0.0 Microsoft.PowerShell.Utility
Cmdlet Convert-String 3.1.0.0 Microsoft.PowerShell.Utility
...
Cmdlet Out-String 3.1.0.0 Microsoft.PowerShell.Utility
...
Since Subinacl is used to display or modify Access ControlEntries (ACEs) for file and folder Permissions, Ownership and Domain, whcih is the same thing that the native cmdlets...
Get-Command -Name '*acl*' | Format-Table -AutoSize
CommandType Name Version Source
----------- ---- ------- ------
...
Cmdlet Get-Acl 3.0.0.0 Microsoft.PowerShell.Security
...
Cmdlet Set-Acl 3.0.0.0 Microsoft.PowerShell.Security
...
Application cacls.exe 10.0.17134.1 C:\WINDOWS\system32\cacls.exe
Application icacls.exe 10.0.17134.1 C:\WINDOWS\system32\icacls.exe
...
... provide. Why not just use them instead as they return proper objects vs Subinacl?
As for encoding.
Are are you saying, you tried this answer, from this discussion and it did nto work for you?
Double spacing of output from SubInACL called from PowerShell
#set output encoding to unicode
[Console]::OutputEncoding = [Text.Encoding]::Unicode
$func_filePath = "G:\test\func.txt"
#use subinacl
[string]$SubInACLCommand = #"
subinacl.exe /file "$func_filePath" /setowner="hostname\Administrators"
"#
Invoke-Expression $SubInACLCommand
#revert output encoding back to default
[Console]::OutputEncoding = [Text.Encoding]::Default
Update for OP
Using RegEx to clean this up on your side. Remove double spaces and empty lines from a string.
('S Y S T E M \ P a t h : d e l e t e A u d i t A C E 0 \ e v e r y o n e
S Y S T E M \ P a t h : n e w a c e f o r \ e v e r y o n e
H K E Y _ L O C A L _ M A C H I N E \ S Y S T E M \ P a t h : 2 c h a n g e ( s )').replace(' ','|').Replace(' ','').Replace('|',' ') -creplace('(?m)^\s*\r?\n','')
# Results
SYSTEM\Path : delete Audit ACE 0 \everyone
SYSTEM\Path : new ace for \everyone
HKEY_LOCAL_MACHINE\SYSTEM\Path : 2 change(s)
Update for OP
Try this on your machine and see if the full results are actually coming back as you'd expect.
$SubinaclResults = Invoke-Command -ComputerName ServerName -ScriptBlock {Subinacl.exe /verbose=1 /keyreg "HKEY_LOCAL_MACHINE\SYSTEM\Path" /sallowdeny="everyone"=SCD}
$SubinaclResults
If the above does to bring back the full result set. My final suggestion would be to output this as a temp file on the remote machine and read it back to your workstation with Get-Content.

Jekyll's is removing static file during cleanup

I want to include a gnuplot code inside a markdown page and have Jekyll compile the graph when I save it. The graph image is being saved. But it is removed during jekyll's cleanup. The closest that I have found toward a solution is at Copying generated files from a Jekyll plugin to a site resource folder. However, I don't undersand the overall flow of Jekyll and how I keep static files from being removed. I have added site.static_files << Jekyll::StaticFile.new(site, site.source, path, filename) with no results.
If I create a dummy file outside of the _site folder, Jekyll will keep my file safe inside the _site file. I would rather not have to create that dummy file.
Here is code for my plugin. Any help will be awesome.
class RenderGNUplot < Liquid::Block
def initialize(tag_name, markup, tokens)
super
#markup = markup
#attributes = {}
markup.scan(Liquid::TagAttributes) do |key, value| #attributes[key.to_sym] = value end
end
def gnuplot(commands)
IO.popen("gnuplot", "w") { |io| io.puts commands }
end
def render(context)
site = context.registers[:site]
#file = ""
commands = super
if ( commands =~ /set output "(.*)"/ )
setfile_regex = Regexp.new(/set output "((.*))"/)
filepath = commands[setfile_regex, 1]
#file = File.basename filepath
commands = commands.sub!(commands[setfile_regex], 'set output "_site/media/' + #file +'"' )
p commands
end
gnuplot(commands)
site.static_files << Jekyll::StaticFile.new(site, site.source, "_site/media/", "#{#file}")
# site.static_files << Jekyll::StaticSitemapFile.new(site, site.dest, '/', 'sitemap.xml')
"<object id='' type='image/svg+xml' data='#{site.baseurl}/media/{#file}'>Your browser does not support SVG</object>"
end
end
Liquid::Template.register_tag('test', RenderGNUplot)
And Markdown page
---
layout: post
title: "Thin Server"
date: 2015-04-28 10:42:56
categories: thin
---
{% test location: Test%}
set terminal svg size 600,400 dynamic enhanced fname 'arial' fsize 10 #mousing jsdir 'http://localhost:4000/media/' name "histograms_1" butt dashlength 1.0
set output "media/curves.svg"
set key inside left top vertical Right noreverse enhanced autotitle box lt black linewidth 1.000 dashtype solid
set samples 50, 50
set title "Simple Plots"
set title font ",20" norotate
plot [-10:10] sin(x),atan(x),cos(atan(x))
{% endtest%}
This is the exact code that I am using. It only has the Liquid block and jekyll StaticFile
class GNUplotFile < Jekyll::StaticFile
def write(dest)
puts "WRITE---->>>>>>>>>>>"
#File.write('_site/media/BTTTTT.svg', DateTime.now)
gnuplot(#commands)
# do nothing
end
def gnuplot(commands)
IO.popen("gnuplot", "w") { |io| io.puts commands }
end
def givemethecommands(commands)
#commands = commands
end
end
class RenderGNUplot < Liquid::Block
def initialize(tag_name, markup, tokens)
super
#markup = markup
#attributes = {}
markup.scan(Liquid::TagAttributes) do |key, value| #attributes[key.to_sym] = value end
end
def render(context)
site = context.registers[:site]
#file = ""
commands = super
if ( commands =~ /set output "(.*)"/ )
setfile_regex = Regexp.new(/set output "((.*))"/)
filepath = commands[setfile_regex, 1]
#file = File.basename filepath
commands = commands.sub!(commands[setfile_regex], 'set output "_site/media/' + #file +'"' )
#p commands
end
gnuplot = GNUplotFile.new(site, site.source, "_site/media/", "#{#file}")
gnuplot.givemethecommands commands
site.static_files << gnuplot
# site.static_files << Jekyll::StaticFile.new(site, site.dest, '/', 'sitemap.xml')
"<object id='' type='image/svg+xml' data='#{site.baseurl}/media/#{#file}'>Your browser does not support SVG</object>"
end
end
Liquid::Template.register_tag('test', RenderGNUplot)

Gnuplot reading not locale encoding file

I want to plot data of an ISO_8859_1 encoded file (two columns of numbers). Those are the first 10 data points of the file:
#Pe2
1 0.8000
2 0.8000
3 0.8000
4 0.8000
5 0.8000
6 0.8000
7 0.8000
8 0.8000
9 0.8000
10 0.8000
The original file has 15000 data points. I create this data with MATLAB, specifically setting ISO_8859_1 encoding, so I am sure that that's the encoding. This is a snippet of the matlab code:
slCharacterEncoding('ISO-8859-1'); %Instruction before writing anything to the file.
fprintf(fileID,' %7d %7.4f',Tempo(i),y(i)); %For loop in this instruction
fprintf(fileID,'\r'); %Closing the file
fclose(fileID);
This is the script that I run. This file is encoded with the default Windows txt files encoding:
set encoding iso_8859_1
set terminal wxt size 1000,551
# Line width of the axes
set border linewidth 1.5
# Line styles
set style line 1 lc rgb '#dd181f' lt 1 lw 1 pt 0 # red
# Axes label
set xlabel 'tiempo'
set ylabel 'valor'
plot 'Pe2.txt' with lines ls 1
This is the output of the gnuplot console when I run the script. After that I input "show encoding":
G N U P L O T
Version 4.6 patchlevel 5 last modified February 2014
Build System: MS-Windows 32 bit
Copyright (C) 1986-1993, 1998, 2004, 2007-2014
Thomas Williams, Colin Kelley and many others
gnuplot home: http://www.gnuplot.info
faq, bugs, etc: type "help FAQ"
immediate help: type "help" (plot window: hit 'h')
Terminal type set to 'wxt'
gnuplot> cd 'C:\Example'
gnuplot> load 'script.txt'
"script.txt", line 10: warning: Skipping data file with no valid points
gnuplot> plot 'Pe2.txt' with lines ls 1
^
"script.txt", line 10: x range is invalid
gnuplot> show encoding
nominal character encoding is iso_8859_1
however LC_CTYPE in current locale is Spanish_Spain.1252
gnuplot>
If I open the file, make some change undo the change and save the file, gnuplot plots the file. I guess that it's because it saves it with local encoding which is the one gnuplot uses to read files.
How do I plot files with gnuplot which are not with the local encoding format?
I also have what it seems to be a similar problem when I output a file with VS2010Css. If I don't specifically set the culture with:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
I am not able to save a file wich gnuplot is able to plot. I believe that this last problem is because of the "," and the "."
In Css I save the files with this:
StreamWriter Writer = new StreamWriter(dir + #"\" + + (k+1) + "_" + nombre + extension);
Writer.WriteLine("#" + (k+1) + "_" + nombre);
Writer.WriteLine();
Writer.WriteLine("{0,32} {1,32}", "#tiempo", "#valor");
for (int i = 0; i < tiempo.GetLength(0); i++)
{
Writer.WriteLine("{0,32} {1,32}", tiempo[i].ToString(), valor[i, k]);
}
Thank you.
Your file has only carriage returns (\r 0xd) as line breaks which doesn't work with gnuplot. You must use only line feed (\n 0xa), but \r\n does also work.

Ghostscript error converting multi-page PS to multi-page PDF using pdfwrite

I'm using Matlab to output a multi-page PS file:
print(figure, '-dpsc2', fullfile(folder, [file '.ps']), '-r600', '-append')
and then using Matlab to invoke Ghostscript to convert the resulting PS file to a PDF:
system(['"' gsPath '" -sDEVICE=pdfwrite \
-dDEVICEWIDTHPOINTS=' num2str(int32(width*72)) ' \
-dDEVICEHEIGHTPOINTS=' num2str(int32(height*72)) ' \
-dPDFFitPage \
-o "' fullfile(folder, [file '.pdf']) '" "' fullfile(folder, [file '.ps']) '"']);
which is just a really hard-to-read way of writing something along the lines of
gswin64c -sDEVICE=pdfwrite ^
-dDEVICEWIDTHPOINTS=100 ^
-dDEVICEHEIGHTPOINTS=100 ^
-dPDFFitPage ^
-o "C:\folder\output.pdf" "C:\folder\input.ps"
where I've put in example values for device dimensions and input/output paths. When I use this code to print a single figure (one page) to PDF, everything works perfectly. However, when printing multiple figures (multiple pages) to PDF, Ghostscript throws an error:
GPL Ghostscript 9.06 (2012-08-08)
Copyright (C) 2012 Artifex Software, Inc. All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
**** Unable to open the initial device, quitting.
Now, if I remove the -dDEVICEWIDTHPOINTS=100 -dDEVICEHEIGHTPOINTS=100 part of my Ghostscript command and again attempt to print multiple figures to a PDF, it works fine (except for the page size being different than what I want).
GPL Ghostscript 9.06 (2012-08-08)
Copyright (C) 2012 Artifex Software, Inc. All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Loading NimbusSanL-Regu font from %rom%Resource/Font/NimbusSanL-Regu... 4032872 2490784 2311720 1014184 2 done.
Has anyone else run into a similar problem and found a workaround for this issue? One of the keys here is that I need to be able to control the page size of the PDF produced. Thanks!
Below is an example that should run fine. First we create a multi-page PS file:
fname = 'test';
if exist([fname '.ps'], 'file'), delete([fname '.ps']); end
hfig = figure;
for i=1:10
plot(cumsum(rand(100,1)-0.5))
drawnow
print(hfig, '-dpsc2', '-append', [fname '.ps'])
end
close(hfig)
Next we convert it to PDF using Ghostscript, and properly crop the figures:
gs_path = 'C:\Program Files\gs\gs9.07\bin\gswin64c.exe';
gs_opts = '-dBATCH -dNOPAUSE -q';
% ps2pdf
cmd = sprintf('"%s" %s -sDEVICE=pdfwrite -dPDFFitPage -o %s %s', ...
gs_path, gs_opts, [fname '.pdf'], [fname '.ps']);
disp(cmd); system(cmd);
% get bbox
cmd = sprintf('"%s" %s -sDEVICE=bbox %s', ...
gs_path, gs_opts, [fname '.pdf']);
disp(cmd); [~,out] = system(cmd);
out = textscan(out, '%s', 'Delimiter','');
bbox = regexp(out{1}, '^%%BoundingBox: (\d+) (\d+) (\d+) (\d+)','tokens','once');
bbox = str2double(vertcat(bbox{:}));
bbox = [min(bbox(:,1:2)) max(bbox(:,3:4))];
% crop to bounding box
cmd = sprintf(['"%s" %s -o %s -sDEVICE=pdfwrite' ...
' -dDEVICEWIDTHPOINTS=%d -dDEVICEHEIGHTPOINTS=%d -dFIXEDMEDIA' ...
' -c "<</PageOffset [-%d -%d]>> setpagedevice" -f %s'], ...
gs_path, gs_opts, [fname '_cropped.pdf'], ...
bbox(3)-bbox(1), bbox(4)-bbox(2), bbox(1), bbox(2), [fname '.pdf']);
disp(cmd); system(cmd);