PS easy way to color text - bioinformatics

I have a postscript file that contains a phylogenetic tree outputted by njplot. It basically consists of lines and labels at the end of the line. Right now it is in black and white but I would like to mark differences between different trees:
Below is a short extract from one of my files with only three of the labels.
a) What do I have to do to make e.g. "B. ovis 25840" be displayed in red?
b) How can I make a box around "B. suis 23445" and "B. Thomsen" (such as to mark that they are in the same group?)
/setpacking where {true setpacking} if
1 setlinecap 1 setlinejoin 1 setlinewidth 0 setgray
/basefont /Times-Roman findfont 12 scalefont def
/titlefont /Times-Roman findfont 12 scalefont def
/setclip {40 40 moveto 560 40 lineto 560 810 lineto 40 810 lineto closepath clip newpath} def
/title {titlefont setfont
40 815 moveto (brucella_conc_se_ani.out_nj.outtree Mon Aug 14 14:52:28 2017
) show ( Page ) show show ( of 1) show
} def
%%EndProlog
%%Page: ? 1
(1) title setclip
0 0 translate
basefont setfont
50 50 translate
0.7 setgray -10 -10 moveto 510 -10 lineto 510 760 lineto -10 760 lineto closepath stroke 0 setgray
359 8 moveto
(B. ovis 25840) show
298 67 moveto
(B. Thomsen) show
294 127 moveto
(B. suis 23445) show
showpage

Text is drawn (for text in fonts other than type 3) using the current color. So if you alter the current color before drawing the text, then it will be drawn in a different color.
There are a number of color operators in PostScript, the simplest are the setgray, setrgbcolor and setcmykcolor operators. setgray takes a value between 1 (white) and 0 (black) and sets the current color to that percentage of gray. setrgbcolor takes 3 parameters between 01 and 1 for each of R, G and B, and setcmykcolor does the same but with CMYK components.
So to answer question 'a' 1 0 0 setrgbcolor placed before the line with the text on it, would cause the text to be drawn in red.
Note that all subsequent operations would also be rendered in red, so we should consider now the gsave and grestore operators. gsave saves a copy of the graphics state, and grestore (surprise!) restores the graphics state from the most recently saved version.
You can use this to limit the effect of a graphics state change. For example:
gsave
1 0 0 setrgbcolor
(B. ovis 25840) show
grestore
would render the text in red, but the subsequent text would be in the colour in force before the gsave, presumably black.
Note that the current point on the page is part of the gstate! So :
gsave
1 0 0 setrgbcolor
359 8 moveto
(B. ovis 25840) show
298 67 moveto
grestore
(B. Thomsen) show
would cause the second 'show' to take place at the same position as the first one, overwriting it.
You don't 'draw a box', PostScript doesn't have graphics primitives like that. What you do is construct a path, and then stroke it (you could fill it instead for a filled rectangle).
For example:
0 0 moveto
0 100 lineto
100 100 lineto
100 0 liento
closepath
stroke
will construct a rectangular path with its bottom left corner at 0,0 it will be 100 units wide and tall (so a square). The 'stroke' operator then strokes the path using the current linewidth and the current colour.
If you want to dig deeper into PostScript then you will need a copy of the PostScript Language Reference Manual, which is available online in PDF format from the Adobe web site.
You might also like to look at the the 'Blue Book' which is also available there as the 'PostScript language tutorial and cookbook'

Related

How can I create a GTIN14 bar code in ZPL?

Can I print a GTIN-14 barcode using ZPL?
I have searched, but can't find much information on weather or not it is possible to print this type of bar code, including the border around it.
Any help is greatly appreciated.
Thanks!
GTIN-14 is simply an interleaved 2 of 5 barcode with bearer bars and special text formatting. Assuming a 203dpi printer and an approximate x-dimension of 25 mils (.64mm), you can calculate all the dimensions of the barcode and its border box.
25mils is approximately 5 dots at 203dpi.
The barcode height should be 1.25 inches, which is ~250 dots.
The border around the barcode should be the width of the wide bar (3x narrow, or 15 dots).
Each character in the barcode is 45 dots (9 modules * 5 dots).
The start/stop also adds 45 dots (9 modules * 5 dots).
So the total length of the barcode is 15 * 45 dots = 675 dots.
Quite zone is 0.25 inches (50 dots) left and right of the barcode.
So the box around the barcode is 805 dots wide (15 border + 50 quiet + 675 barcode + 50 quiet + 15 border) and 280 dots high (15 border + 250 barcode + 15 border).
Here's how it looks in ZPL:
^XA
^FO100,100^BY5,3
^B2N,250,N,N,N
^FD00012345678905^FS
^FO35,85^GB805,280,15^FS
^FO115,380^AB,44,28^FD0 00 12345 67890 5^FS
^XZ
The top left corner of the barcode is at 100,100. The top left corner of the border box is at 35,85.
The example uses the built-in B font, you may want to change that...
And here it is in labelary.

Edit (every page of a) Postscript file manually

I want to (manually) insert additional postscript commands in a postscript file that was converted from a PDF file via ghostscript’s pdf2ps. For the purpose of testing I created a PDF file from the following file using pdflatex:
\documentclass[a4paper]{article}
\begin{document}
Mostly empty.
\end{document}
In the converted postscript file I make the following edit:
...
%%Page: 1 1
%%PageBoundingBox: 0 0 595 841
%%BeginPageSetup
4 0 obj
<</Type/Page/MediaBox [0 0 595.28 841.89]
/Parent 3 0 R
/Resources<</ProcSet[/PDF]
/Font 8 0 R
>>
/Contents 5 0 R
>>
endobj
%%EndPageSetup
% BEGIN MANUAL EDIT
0 setgray 0 0 moveto 595 841 lineto stroke
% END MANUAL EDIT
5 0 obj
<</Length 257>>stream
q 0.1 0 0 0.1 0 0 cm
0 G
0 g
q
10 0 0 10 0 0 cm BT
/R6 9.9626 Tf
1 0 0 1 139.746 706.129 Tm
[(M)-0.699638(os)-0.399443(t)-0.900585(l)-0.798886(y)-333.819(e)-0.400668(m)-0.300195(p)-0.599165(t)26.0974(y)83.192(.)-0.800112]TJ
154.421 -615.691 Td
(1)Tj
ET
Q
Q
endstream
endobj
pagesave restore
%%PageTrailer
%%Trailer
end
%%EOF
Instead of producing a diagonal line the postscipt/PDF file remains (seemingly) unchanged. However, if I alter the page dimensions from A4 to letter size the line is shown:
%%Page: 1 1
%%PageBoundingBox: 0 0 612 792
%%BeginPageSetup
4 0 obj
<</Type/Page/MediaBox [0 0 612 792]
...
I am obviously missing something here (which is not surprising given my rudimentary knowledge of postscript). My question is: How can I make the line appear while keeping the page dimensions unchanged?
P.S.: A comment I stumbled across mentioned that pdftops (from poppler-utils) is in some sense superior to pdf2ps. Indeed, inserting commands into the converted postscript file immediately before the showpage command (which is not there at all when using pdf2ps) worked fine. So I have probably already found a solution to my problem. However, I would like to learn what the page dimensions have to do with it when using pdf2ps.
Solution
Thanks to KenS’s advice and referring to his answer to this question I was able to achieve the desired effect by adding an EndPage procedure to the postscript file:
<<
/EndPage
{
exch pop 2 lt
{
gsave
0 0 translate
0 setgray 0 0 moveto 596 842 lineto stroke
grestore
true
}{false} ifelse
} bind
>> setpagedevice
(This assumes the page size is a4.)
PostScript is a write-only language :-)
Seriously, its a programming language. In order to understand what's going on, you need to understand the program, which in the case of the output from Ghostscript's ps2write device, is distinctly non-trivial.
The syntax is basically PDF, with a prolog program which interprets it in PostScript terms.
The program will use showpage, it does it when the procedure EndStream is executed, which is (basically) when the endobj keyword is encoutnered in a page stream. You'll see that it looks like:
ET
Q
Q
Q
endstream
endobj
%%Page: 2 2
You could place anything you like between the endstream and the endobj, but you need to be aware that the graphics state at that point is determined by whatever operations have already taken place. This can include scaling, oration, skeing, flipping the vertical axis, etc. So simply inserting some PostScript into there is unlikely to work. You could do an initgraphics which would at least reset the graphics state to a known setup.
As a test I ran Ghostscript'sd ps2write device like this:
gs -sDEVICE=pdfwrite -o out.ps -c "showpage" -f
which produces a PostScript program where the (effective) content is:
%%EndResource
%%EndProlog
%%Page: 1 1
%%PageBoundingBox: 0 0 595 842
%%BeginPageSetup
4 0 obj
<</Type/Page/MediaBox [0 0 595 842]
/Parent 3 0 R
/Resources<</ProcSet[/PDF]
>>
/Contents 5 0 R
>>
endobj
%%EndPageSetup
5 0 obj
<</Length 23>>stream
q 0.1 0 0 0.1 0 0 cm
Q
endstream
endobj
%%Trailer
end
%%EOF
I then modified this more or less as you suggested:
%%EndPageSetup
0 setgray 0 0 moveto 595 842 lineto stroke
5 0 obj
<</Length 23>>stream
q 0.1 0 0 0.1 0 0 cm
Q
endstream
endobj
%%Trailer
For me this produced the expected stroke from bottom left to top right. Obviously without the PostScript file you originally produced I can't tell you why your experience is different. (no I'm not in a position to run latex to produce such a thing, and even if I did I have no way to know which version of Ghostscript and the other tools you used).
My guess would be that 'something' in your PDF file overwrote the entire page, its not entirely uncommon.

Generating random direction in C64 Basic

I have run the ‘More Bouncing Balls’ Basic program from chapter 5 of the C64 user’s manual, with the addition from the final page of the chapter. The code is as follows:
10 PRINT CHR$(147):REM SHIFT CLR/HOME
20 POKE 53280,7 : POKE 53281,13
30 X=1:Y=1
40 DX=1:DY=1
50 POKE 1024 + X + 40*Y, 81
60 FOR T=1 TO 10: NEXT T
70 POKE 1024 + X + 40*Y, 32
80 X=X+DX
90 IF X=0 OR X=39 THEN DX=-DX
100 Y=Y+DY
110 IF Y=0 OR Y=24 THEN DY=-DY
120 GOTO 50
To this were added the lines at the end, ɔ:
21 FOR L=1 TO 10
25 POKE 1024+INT(RND(1)*1000),160
27 NEXT L
85 IF PEEK(1024+X+40*Y)=160 THEN DX=-DX:GOTO 80
105 IF PEEK(1024+X+40*Y)=160 THEN DY=-DY:GOTO 100
These lines are not relevant to the question, but I included them for sake of completeness.
I wanted to add randomness to the direction of the ball (chr$(81)), and noticed that by changing DX and DY to other numbers, I would get it to move at angles other than 45°; of course, having both DX and DY set to 1, would have them both ‘push’ the ball in perpendicularly opposite directions, ɔ: halfway between both, equalling 45°.
But when trying to use a random number, I would get truly odd behaviour. I assumed the number had to be between 0 and 1, and so tried (INT(10*RND(1))+1)/10, and changed line 40 to set DX and DY to this random number. What I got instead was some very odd behaviour. The ball would move very fast at a predictable angle, disappearing at the right side and reappearing on the left, moving a few lines down, then disappearing completely, then turning up on top of the screen drawing unmoving balls one after another horizontally, then crash.
When instead setting DX or DY to an integer, i.e. 2, I would still get some strange behaviour, such as the ball disappearing at one end and reappearing at the opposite, and on this occasion the program would end after a few seconds.
What is causing this erratic behaviour? And how can I set the parameters in line 40 to allow the ball to move in different directions (kind of like in Pong) when it hits a wall?
Note 1: When changing DX and DY in lines 80 and 100 instead, I got some interesting jittering movement, but as expected, as though the ball drawn on-screen was an uneven sphere.
Note 2: I am aware one generally should not include tags in titles, but was unsure whether the question would be too unsearchable if I left them out. Feel free to edit the title if need be; I am happy to be educated.
I modified the program in this way:
1-DX is step for X.
2-DY is step for Y.
2-VX is direction of X, -1 left and +1 rigth.
3-XY is direction of Y, -1 up and +1 down.
3-When Bouncing Ball angle changes randomly (subroutine 300)
Calculation of DX and DY is for a right triangle with hypotenuse of 1 (one).
4-When plotting use only integer numbers so the "ball" doesn't have odd moves.
5-Control off limits, so "ball" doesn't disappear.
5 rem 2018-08-24 bouncing balls
6 rem https://stackoverflow.com/questions/51907035
7 rem /generating-random-direction-in-c64-basic
10 print chr$(147);:rem shift+clr/home=clear screen
20 poke 53280,7:poke 53281,13
25 rem random initial position
40 p=rnd(1)*40:x=p
45 q=rnd(1)*25:y=q
50 gosub 300
60 rem vector direction
70 vx=(rnd(1)<0.5):if vx>=0 then vx=1
80 vy=(rnd(1)<0.5):if vy>=0 then vy=1
100 rem plot
110 poke 1024+int(p)+40*int(q),32
120 poke 1024+int(x)+40*int(y),81
130 for t=1 to 30:next t
140 p=x:q=y
150 x=x+dx*vx
160 ca=0:rem change angle
170 if x<=0 or x>=39 then vx=-vx:ca=-1
175 if x<0 then x=0
176 if x>39 then x=39
180 y=y+dy*vy
190 if y<=0 or y>=24 then vy=-vy:ca=-1
195 if y<0 then y=0
196 if y>24 then y=24
200 if ca then gosub 300
210 goto 100
300 rem random angle between 15 and 75 d
egrees
305 rem a=angle in degrees r=radians
310 a=15+rnd(1)*(75-15+1):r=a*{pi}/180
320 dx=cos(r)
330 dy=sin(r)
340 return
On C64 replace {pi} using SHIFT+UP_ARROW.
If line 110 is REM then you can see the walk.
I modified the program so:
- Start position X and Y are random
- Direction DX and DY are random, values -1 or +1
10 PRINT CHR$(147):REM SHIFT CLR/HOME
20 POKE 53280,7:POKE 53281,13
25 REM RANDOM INITIAL POSITION
30 X=INT(RND(1)*39)+1:Y=INT(RND(1)*24)+1
35 REM RANDOM DIRECTION
40 DX=(RND(1)<0.5):IF DX>=0 THEN DX=1
45 DY=(RND(1)<0.5):IF DY>=0 THEN DY=1
50 POKE 1024+X+40*Y,81
60 FOR T=1 TO 30:NEXT T
70 POKE 1024+X+40*Y,32
80 X=X+DX
90 IF X<=0 OR X>=39 THEN DX=-DX
100 Y=Y+DY
110 IF Y<=0 OR Y>=24 THEN DY=-DY
120 GOTO 50

PostScript error with imagemask and raw data

In Adobe's PLRM
I found the following example using the imagemask operator.
This works fine when running with Ghostscript.
54 112 translate % Locate lower-left corner of square
120 120 scale % Scale 1 unit to 120 points
0 setgray % Set current color to black
24 23 % Specify dimensions of source mask
true % Set polarity to paint the 1 bits
[24 0 0 -23 0 23] % Map unit square to mask
{< 003B00 002700 002480 0E4940
114920 14B220 3CB650 75FE88
17FF8C 175F14 1C07E2 3803C4
703182 F8EDFC B2BBC2 BB6F84
31BFC2 18EA3C 0E3E00 07FC00
03F800 1E1800 1FF800 >}
imagemask
showpage
As an exercise I tried to rewrite the above example using an ImageType-1 dictionary and raw data, and finally came up with this code:
54 112 translate
120 120 scale
0 setgray
<<
/ImageType 1
/Width 24
/Heigth 23
/BitsPerComponent 1
/Decode [1 0]
/ImageMatrix [24 0 0 -23 0 23]
/DataSource currentfile /ASCIIHexDecode filter
>>
imagemask
003B00 002700 002480 0E4940
114920 14B220 3CB650 75FE88
17FF8C 175F14 1C07E2 3803C4
703182 F8EDFC B2BBC2 BB6F84
31BFC2 18EA3C 0E3E00 07FC00
03F800 1E1800 1FF800>
showpage
However, when running this with Ghostscript I get the following error.
Error: /undefined in --imagemask--
I'm still scratching my head to find the bug, but in vain.
How can it be imagemask is undefined? Or did I miss something obvious?
I don't know if this is exactly the code you've written, but there's a typo:
/Heigth 23
which should obviously be:
/Height 23
If I correct that, the file runs to completion, and draws the turkey.

Contour Lines Algorithm

This could very well be a duplicate, but I could not seem to find something specific to my problem.
I have a xy grid in a picture box. Each grid cell has a specific mass. I would like to create contour lines on this xy grid based on the mass.
Does anyone have any ideas to a good algorithm to perform this task? I am trying to get this done in VB6 but any algorithm would do.
Edit
Contour Grid
I have a grid. I want to display contour lines based on mass (IE, the cells with more than one point in them will be heavier in mass)
This question's a bit stale, but so's my experience: I did something like this almost 30 years ago.
This produces simple contours on a bitmap:
Calculate the field-strength at each point in the grid (I'm assuming you're trying to plot something like gravitational field contours based on the masses of the points).
Colour the alternate spaces between contour lines (which you haven't got yet) in two alternate colours. e.g. if the contour lines should be 100 units (of field-strength) apart then choose the colour of each pixel based on ToInt(pixel_field_strength / 100) % 2.
Trace the edges of the colour boundaries to produce contours. For example, if your two colours are white and black, then only retain white pixels adjacent to a black pixel.
If you're just interested in the results, use a library as suggested in the comments.
Purely for nostalgia's sake, I found my original BBC BASIC code. It still runs on modelb (a BBC Micro emulator).
10 REM THIS COMES WITH NO WARRANTY!
20
30 REM Gravity field
40
50 MODE 1
60 PROCsetup
70 FOR Y%=300 TO 900 STEP 4
80 FOR X%=200 TO 800 STEP 4
90 R=LOG(FNforce(X%,Y%))
100 GCOL0,((R*10) MOD 2)+1
110 PLOT69,X%,Y%
120 NEXT
130 NEXT
140 PROCcontour
150 VDU19,1,0,0,0,0
160 VDU19,2,0,0,0,0
170 END
180 DEFPROCsetup
190 N%=5
200 DIM X%(N%),Y%(N%),M%(N%)
210 FOR P%=1 TO N%
220 READ X%(P%),Y%(P%),M%(P%)
230 NEXT
240 ENDPROC
250 DATA 625,625,1000000
260 DATA 425,725,1000000
270 DATA 475,425,1000000
280 DATA 375,575,1000000
290 DATA 725,525,1000000
300 DEFFNforce(X,Y)
310 P=0
320 FOR P%=1 TO N%
330 DX=X%(P%)-X:DY=Y%(P%)-Y
340 R=SQR(DX*DX+DY*DY)
350 P=P+M%(P%)/R
360 NEXT
370 =P
380 DEFPROCcontour
390 GCOL0,3
400 FOR Y%=300 TO 900 STEP 4
410 FOR X%=200 TO 800 STEP 4
420 IF POINT(X%,Y%)=1 AND (POINT(X%+4,Y%)=2 OR POINT(X%-4,Y%)=2 OR POINT(X%,Y%+4)=2 OR POINT(X%,Y%-4)=2) THEN PLOT69,X%,Y%
430 NEXT
440 NEXT
450 ENDPROC

Resources