less-like pager for (swi) prolog - prolog

The typical workflow in unix is to use a pipeline of filters ending up with a pager such as less. E.g. (omitting arguments)
grep | sed | awk | less
Now, one of the typical workflows in the swi-prolog's command line is asking it to give the set of solutions for a given conjunction like
foo(X),bar(X, Y),qux(buz, Y).
It readily gives me the set of soutions. Which can be much longer than the terminal window. Or a single query
give_me_long_list(X).
can give a very long list again not fitting on the screen. So I constantly find myself in situations where I want to slap |less at the end of the line.
What I am looking for is a facility to open in a pager a set of solutions or just a single large term. Something similar to:
give_me_long_list(X), pager(X).
or
pager([X,Y], (foo(X),bar(X, Y),qux(buz, Y))).

This is not a complete solution, but wouldn't it be rather easy to write your own pager predicate? Steps:
Create temp file
dump X into temp file with the help of these or those predicates
(I haven't done any I/O with Prolog yet, but it doesn't seem too messy)
make a system call to less <tempfile>

Related

A "display" that always displays in prolog

I have a predicate check(Data,Res) that checksDats according to some rules and returns Res (a function result on Data, assuming Data answers to several criteria).
I have another function generate(N,Data) which generates a N-size Data.
My main program begins with generating many 1-size Data, then if none answered the criteria, we go on to 2-size Data and so on until we reach a certain M upper limit.
main(M):- next_number(N,M), generate(N,Data), check(Data,Res).
However, the program runs for very long time. I wanted to make sure it does not get stuck. For this, I wanted to print the generated Data each time before its being checked. But adding display did not assist, because it only actually displayed if the entire statement was true.
That's not what I want.
I want to keep track of the progran using display, similarly to System.out.println in Java.
Is there any other function that displays anyway? Or an idea how to use display in a way that will always display, regardless if the Data answered the criteria or not?
I thought to do:
(check(Data,Res) -> display(Data);display(Data)).
But I am not sure. Any ideas?
Your long process is likely to be within check - or more precisely, that check fails for most data, causing the system to backtrack repeatedly.
If you display a result in check, you'll have line upon line of tracing. Instead, you could add a write statement to generate, or even to your number generation:
main(M):-
next_number_and_tick(N,M),
generate(N,Data),
check(Data,Res).
next_number_and_tick(N,M) :-
next_number(N,M),
write('Tick - now doing '),
writeln(N).
Upon backtracking, the program will signal the data size it is now working on, giving you an idea of the volume of work it is doing.
The problem in the way you use display is that the entire statement must be true for it to display. Your idea of using "if-then" is good but not accurate. If you want to use it, you should "trick" prolog the following way:
new_check(Data,Res) :- (check(Data,Res) -> display('Victory!'),!; display('Failed Data: '), display(Data), nl, fail).
This way, if the check fails, you will get a report on which Data failed, and if it succeeded everything stops (assuming you want only 1 solution. If you want more, remoce the ! predicate).

How to concatenate many files using their basenames?

I study genetic data from 288 fish samples (Fish_one, Fish_two ...)
I have four files per fish, each with a different suffix.
eg. for sample_name Fish_one:
file 1 = "Fish_one.1.fq.gz"
file 2 = "Fish_one.2.fq.gz"
file 3 = "Fish_one.rem.1.fq.gz"
file 4 = "Fish_one.rem.2.fq.gz"
I would like to apply the following concatenate instructions to all my samples, using maybe a text file containing a list of all the sample_name, that would be provided to a loop?
cp sample_name.1.fq.gz sample_name.fq.gz
cat sample_name.2.fq.gz >> sample_name.fq.gz
cat sample_name.rem.1.fq.gz >> sample_name.fq.gz
cat sample_name.rem.2.fq.gz >> sample_name.fq.gz
In the end, I would have only one file per sample, ideally in a different folder.
I would be very grateful to receive a bit of help on this one, even though I'm sure the answer is quite simple for a non-novice!
Many thanks,
NoƩ
I would like to apply the following concatenate instructions to all my
samples, using maybe a text file containing a list of all the
sample_name, that would be provided to a loop?
In the first place, the name of the cat command is mnemonic for "concatentate". It accepts multiple command-line arguments naming sources to concatenate together to the standard output, which is exactly what you want to do. It is poor form to use a cp and three cats where a single cat would do.
In the second place, although you certainly could use a file of name stems to drive the operation you describe, it's likely that you don't need to go to the trouble to create or maintain such a file. Globbing will probably do the job satisfactorily. As long as there aren't any name stems that need to be excluded, then, I'd probably go with something like this:
for f in *.rem.1.fq.gz; do
stem=${f%.rem.1.fq.gz}
cat "$stem".{1,2,rem.1,rem.2}.fq.gz > "${other_dir}/${stem}.fq.gz"
done
That recognizes the groups present in the current working directory by the members whose names end with .rem.1.fq.gz. It extracts the common name stem from that member's name, then concatenates the four members to the correspondingly-named output file in the directory identified by ${other_dir}. It relies on brace expansion to form the arguments to cat, so as to minimize code and (IMO) improve clarity.

Editing thickness in postscript (.ps or .eps) figures via unix shell commands?

I have many figures (graphs) in postscript (.eps) format that I wish to thicken the plots with.
I found the following code, but the output file is no different. I was wondering what I was doing wrong.
The code:
# get list of all arguments
set args = ($*)
# if not enough arguments, complain.
if ($#args < 2) then
echo "Usage: ps_thicken ps_file factor"
echo "Thickens all lines in a PostScript file by changing the linewidth macro."
echo "Result goes to standard output."
exit 1
endif
sed -e "s/^\/lw {\(.*\) div setlinewidth/\/lw {$2 mul \1 div setlinewidth/" $1
Now to execute this from my command line, I use the command (filename is ps_thicken, and has appropriate permissions):
./ps_thicken old_file.eps 10 > new_thick_file.eps
Which I thought should make everything 10x thicker, but it just doesnt change anything.
Any help would be greatly appreciated, I'm pretty new to shell script!
PostScript is a programming language, so it isn't really possible to make changes in an automated fashion like this. At least not without writing a PostScript program to do so!
Note that linewidth isn't a 'macro' (PostScript doesn't have macros) its am operator. What the code you've posted for sed does (if I recall sed well enough) is look for the definition of /lw and replace it with a modified version. The problem with that is that /lw is a function declartation in a particular PostScript program. Most PostScript programs won't have (or use) a function called 'lw'.
You would be much better to prepend the PostScript program code with something like:
/oldsetlinewidth /linewidth load def
/setlinewidth {2 div oldsetlinewidth} bind def
That will define (in the current dictionary) a function called 'setlinewidth'. Now, if the following program simply uses the current definition of setlinewdith when creating its own functions, it will use the redefined one above. Which will have the effect of dividing all line widths by 2 in this case. Obviously to increase the width you would use something like 2 mul instead of 2 div.
Note that this is by no means foolproof, its entirely possible for a PostScript program to explicitly load the definition of setlinewidth from systemdict, and you can't replace that (at least not easily) because systemdict is read-only.
However its unlikely that an EPS program would pull such tricks, so that should probably work well enough for you.
[based on comments]
Hmm, you mean 'failed to import' into an application or something else ?
If you're loading the EPS into an application then simply putting that code in front of it will break it. EPS (unlike PostScript) is required to follow some rules, so to modify it successfully you will have to follow them. This includes skipping over any EPS preview.
This is not really a trivial exercise. Your best bet is probably to run the files through Ghostscript, you can do a lot by harnessing a PostScript interpreter to do the work.
Start with the 2 lines of PostScript above in a file, then run the EPS file you want to 'modify' through Ghostscript, using the eps2write device. That will produce a new EPS which has the changes 'baked in'.
Eg (assuming the linewidth modifying code is in 'lw.ps'):
gs -sDEVICE=eps2write -o out.eps lw.ps file.eps
But be aware that the resulting EPS is a completely rewritten program and will bear no relation to the original. In particular any preview thumbnail will be lost.

Using SWI-Prolog Interactively - Output Taken off

I'm using SWI-Prolog interactively. When I run my query, I get a prefix of the output and the rest is taken off (marked using the string ...|...). Is this normal or should I go back and fix my program?
The number of items shown is controlled by a prolog flag.
You can remove it by issuing
remove_max_depth:-
current_prolog_flag(toplevel_print_options,Options),
select(max_depth(_), Options, NOptions)->
set_prolog_flag(toplevel_print_options, NOptions); true.
Nothing to worry about. It's just abbreviating it visually... just press 'w' (write) to display the complete internal representation of the list.

How to delete the input cell upon evaluation?

I would like to accomplish the following: upon evaluation of an input cell, it should self-destruct (i.e. delete itself). I tried to hack something together with SelectionMove and NotebookDelete, but didn't quite get what I wanted.
Here are potential use cases:
the command might be a shorthand for a series of other commands that will be generated dynamically and inserted into the notebook
the command might only be used for side effects (e.g. to set a notebook option or to open a new notebook); leaving the command in the notebook after evaluation serves no purpose and creates clutter
Edit: As per Mr. Wizard, the answer is SelectionMove[EvaluationNotebook[], Previous, Cell]; NotebookDelete[];. I don't know why it wasn't working for me before. Here is some code that uses this idiom.
writeAndEval[nb_, boxExpr_] := (NotebookWrite[nb,
CellGroupData[{Cell[BoxData[boxExpr], "Input"]}]];
SelectionMove[nb, Previous, Cell];
SelectionMove[nb, Next, Cell];
SelectionEvaluate[nb]);
addTwoAndTwo[] := Module[{boxExpr},
boxExpr = RowBox[{"2", "+", "2"}];
SelectionMove[EvaluationNotebook[], Previous, Cell];
NotebookDelete[];
writeAndEval[EvaluationNotebook[], boxExpr];
]
Now, running addTwoAndTwo[] deletes the original input and makes it look as if you've evaluated "2+2". Of course, you can do all sorts of things instead and not necessarily print to the notebook.
Edit 2: Sasha's abstraction is quite elegant. If you are curious about "real-world" usage of this, check out the code I posted in the "what's in your toolbag" question: What is in your Mathematica tool bag?
To affect all Input cells, evaluate this is the notebook:
SetOptions[EvaluationNotebook[], CellEvaluationFunction ->
( (
SelectionMove[EvaluationNotebook[], All, EvaluationCell]; NotebookDelete[];
ToExpression##
)&)
]
If you only want to affect one cell, then select the cell and use the Options Inspector to set CellEvaluationFunction as above.
Or, building on Mr. Wizard's solution, you can create a function SelfDestruct, which will delete the input cell, if you intend to only do this occasionally:
SetAttributes[SelfDestruct, HoldAllComplete];
SelfDestruct[e_] := (If[$FrontEnd =!= $Failed,
SelectionMove[EvaluationNotebook[], All, EvaluationCell];
NotebookDelete[]]; e)
Then evaluating 2+3//SelfDestruct outputs 5 and deletes the input cell. This usage scenario seems more appealing to me.

Resources