Gnuplot animation vector - gnuplot

i am trying to make a fluid vector animation in gnuplot. To create the vector values i use FORTRAN. My FORTRAN subroutine program prints vector data in a txt file called vekdata.txt and creates another file called plotvek.txt with gnuplot commands. This subroutine is inside a do loop so for every iteration vekdata.txt gets updated.
So i was wandering how i can make an animation of this as it develops in time? Is there some simple commands? As it is now it prints a huge amount of picture to my screen. Every picture is a bit different so i know the code works.
do t=1,1000
call vektorplot(storu,storv,n,Re,t)
end do
open(21,access='sequential',file='plotvek.txt',status='unknown')
write(21,*)'set term png enhanced'
write(21,*)'# plotvek.txt'
write(21,*)'set output sprintf(''frame_%09d.png'',',t,')'
!animation commands
write(21,*)'set output sprintf("frame_%9d",'t,')'
close(21,status='keep')
call execute_command_line("gnuplot -persist plotvek.txt")

I'm posting here an alternative.
Although I usually prefer the animated gif as Karl answers, sometimes too big gifs are difficult to rented and especially for very long movies, they tend to create unresponsive applications (browser or slide presentations).
Basically you write to a file every frame and then create a movie.
In this link you have both gif and movie examples. I'm going to recall here the principles.
For every frame you set a png terminal and output file. As fortran command, this would be something like:
write(21,*)'set term png enhanced'
write(21,*)'# plotvek.txt'
write(21,*)'set output sprintf("frame_%09d.png",',n+1,')'
[...]
Then, once the program is run, you can create a movie:
mencoder mf://frame_%09d.png -mf fps=30 -ovc lavc -o my_video.avi
Of course mencoder has a tons of options to tune your movie.
Another alternative to mencoder is ffmpeg:
ffmpeg -framerate 1/5 -i frame_%09d.png -c:v libx264 -r 30 -pix_fmt yuv420p my_video.mp4

The gif terminal has an option to make a gif animation, but you have to plot it all in one call to the gnuplot script.
You could try something like this:
$ makevectors | gnuplot
where makevectors is the executable of your fortran code, only it prints everything to STDOUT, first
set term gif animation
set out 'vectors.gif'
# plus the rest of your settings
do for [i=1:100] {plot '-' using 1:2:($3*30):($4*25) with vectors}
, then 100 data sets, with an EOF after each. Lastly print
set out
(Ok, the output would close anyway, but just to be very orderly) and you've got a file with that gif animation.
Update: I'd recommend you move your gnuplot commands to a script file and have gnuplot call that on the command line makevectors | gnuplot script.gp. That way you don't have to recompile the program every time you want to change a line colour or something.

Related

Postscript to PDF scale to fit into A4

I need to create an A4 PDF file by fitting into page this 13.44x16.44 inches Postscript file. I thought ps2pdf could help me but I cannot get the desired effect.
I use this command to create the PDF:
ps2pdf -dFIXEDMEDIA -dPDFFitPage -sPAPERSIZE=a4 ori.postscript salida.pdf
Please note I used -dFIXEDMEDIA and -dPDFFitPage to force fit the Postscript file into the A4 paper size, but those apparently aren't working.
This is the original file:
Edit: Here's the original file
And this is the resulting file. As you can see, the image isn't resized to fit, but just placed as is:
Firstly; the order of operands in Ghostscript is important, they are applied in the command line order. So you would want to apply the -sPAPERSIZE before you apply -dFIXEDMEDIA and both of those before you apply -dPDFFitPage.
I'd also suggest that you use Ghostscript directly rather than using the ps2pdf script.
If that still doesn't work for you, then you will need to provide an example file to show the problem, I can't tell you anything by looking at pictures.
You should also state the operating system and version of Ghostscript being used.
EDIT
The problem is that your PostScript program doesn't request a media size, it simply draws on whatever media happens to be available at the time. Some programs will rescale their content to fit whatever media is currently available, this isn't one of them. Anything which doesn't lie on the current media is allowed to be clipped off.
The 'FitPage' code relies on the PostScript program requesting a media size, which it then compares to the current (fixed) size. From that it works out how much to scale the content so that it fits into the new media.
If your program doesn't request a media size then there's no way for Ghostscript to know how much to scale it so it fits.
Now your program does have BoundingBox comments, but those are just comments, a PostScript consumer will ignore them. But you can use them.....
You can either modify the header of your PostScript program to pretend its an EPS instead of a PostScirpt program. :
Change
%!PS-Adobe-2.0
To
%!PS-Adobe-2.0 EPSF-3.0
and then use -dEPSFitPage instead of -dPDFFitPage then it will produce something like what (I think) you want. Note that PDFFitPage is for PDF input, so you shouldn't really be using it anyway. For PostScript input you want -dPSFitPage
Alternatively, read the BoundingBox comments and apply a media size request and origin translation yourself.
This command:
gs -sPAPERSIZE=a4 -dFIXEDMEDIA -dPSFitPage -sDEVICE=pdfwrite -sOutputFile=\temp\out.pdf -c "<</PageSize [968 1184]>> setpagedevice -20 -50 translate" -f d:\temp\ori.eps
Produces the same output as treating the file as EPS would.

FFmpeg: how to make video out of slides and audio

So i have several images some png and some jpgs. And i have mp3 audio. I want to make a video file don't care what format.
So i want either:
A video made up of xyz size meaning images are centered and cropped if they go beyond dimensions coupled with audio in mp3 format..
or just one image centered or and cropped, still image, video with audio.
I have tried copying and pasting things and even modifying them after reading documents but in the end i got a blank video with audio and huge file that took forever to complete.
I have windows 7.
u have to rename the images in a sequence.
example if u have a.png , bds.png , asda.png....
rename it to image1.png, image2.png , image3.png and so on
(it should be in the sequence u want the images to come in the video)
now make sure u are in the folder u have saved the rename images
now use
ffmpeg -i image%d.png output.mp4 (whichever format u want)
now to add audio(say 'input.mp3') to 'output.mp4'
use ffmpeg -i input.mp3 -i output.mp4 output2.mp4
this should work.
hope this helps.

output.png from gnuplot is not as good as the figure from prompt shell

I often plot graphs in gnuplot prompt shell, like this:
gunuplot> plot sin(x) with linespoints pointtype 3
and the figure showed up is great.
Today, I save the graph in a .png file, like this:
gnuplot> set term png
gnuplot> set output "output.png"
gunuplot> plot sin(x) with linespoints pointtype 3
Then, I open output.png with eog in Ubuntu, like this:
$ eog output.png
I found that, the output.png displayed in eog is not as good as the figure plotted in prompt shell.
Why is that? Do I need to adjust some settings before save the output.png?
PS
I found that a way around it, first,
set term postscript
set output "output.ps"
then in linux shell,
$ convert output.ps output.jpg
This way some sort of solve the my problem.
The source of your problems with the PNG quality is most likely the missing antialiasing in the png terminal of Gnuplot. Since you give no screenshots, I'm not sure what you mean when talking about bad linewidth, but here's how it looks for me (on MacOS). This screenshot shows the output of gnuplot's native aquaterm output:
If we create a png using set term png, the lines become "jumpy" and pixellated:
However, there is a version of the png terminal that uses the Cairo libs for rendering, and that makes the output far more smooth and nicer. set term pngcairo gives this result:
You can use set terminal to check whether this terminal version is available for you. If it is, this should save you conversion work and also give better image quality than a JPG (which is not an ideal format for line art).
The default size of the PNG image generated gnuplot with the PNG terminal is 640x480 pixels. This resolution in certain cases may result in "pixelated" graphs which are not as nice as those produced on screen with the default (wxt) terminal.
You can change the resolution of the output image using the size option:
set terminal png size <x,y>
where x and y are the desired numbers of pixels along the horizontal and vertical axis, respectively.
For example:
set terminal png size 1024,768
Please note that, images with larger resolution will result in proportionally larger files on disk. Alternatively you can try to use non-raster terminals like "post eps" or "pdf" if available on your machine, which may give you high quality scalable and (relatively) portable images without a large disk footprint.
Alternatively, if you want professional (publication-ready) quality images with gnuplot, you should have a look at the epslatex terminal. I have used it extensively for my thesis and my papers with very nice results, virtually no pixelation problems, portability when converting images to pdf, and almost all the capabilities of Latex.

How can I create a waveform image of an MP3 in Linux?

Given an MP3 I would like to extract the waveform from the file into an image (.png)
Is there a package that can do what I need ?
Using sox and gnuplot you can create basic waveform images:
sox audio.mp3 audio.dat #create plaintext file of amplitude values
tail -n+3 audio.dat > audio_only.dat #remove comments
# write script file for gnuplot
echo set term png size 320,180 > audio.gpi #set output format
echo set output \"audio.png\" >> audio.gpi #set output file
echo plot \"audio_only.dat\" with lines >> audio.gpi #plot data
gnuplot audio.gpi #run script
To create something simpler/prettier, use the following GNU Plot file as a template (save it as audio.gpi):
#set output format and size
set term png size 320,180
#set output file
set output "audio.png"
# set y range
set yr [-1:1]
# we want just the data
unset key
unset tics
unset border
set lmargin 0
set rmargin 0
set tmargin 0
set bmargin 0
# draw rectangle to change background color
set obj 1 rectangle behind from screen 0,0 to screen 1,1
set obj 1 fillstyle solid 1.0 fillcolor rgbcolor "#222222"
# draw data with foreground color
plot "audio_only.dat" with lines lt rgb 'white'
and just run:
sox audio.mp3 audio.dat #create plaintext file of amplitude values
tail -n+3 audio.dat > audio_only.dat #remove comments
gnuplot audio.gpi #run script
Based on this answer to a similar question that is more general regarding file format but less general in regards to software used.
FFmpeg showwavespic
FFmpeg can do it in a single command as usual:
tutorial on wiki at: https://trac.ffmpeg.org/wiki/Waveform
documentation for the filter: https://ffmpeg.org/ffmpeg-filters.html#showwavespic
Sample command:
sudo apt install ffmpeg
ffmpeg -i in.flac -filter_complex "showwavespic=s=640x320:colors=black" \
-frames:v 1 out.png
You can also set colors in RGB colors=0x0088FF: Using hex colors with ffmpeg's showwaves
Sample test data of me saying "Hello my name is Ciro Santilli" with two identical stereo channels:
wget -O in.flac https://raw.githubusercontent.com/cirosantilli/media/d6e9e8d0b01bccef4958eb8b976c3b0a34870cd3/Hello_my_name_is_Ciro_Santilli.flac
Output:
Background color
The background is transparent by default, but:
the Wiki teaches us how to add a image background: https://trac.ffmpeg.org/wiki/Waveform#Addingabackground
Overlay timelapse video on solid background colour using ffmpeg teaches us how to generate a solid color for an image
and so we reach:
ffmpeg -i in.flac -f lavfi -i color=c=black:s=640x320 -filter_complex \
"[0:a]showwavespic=s=640x320:colors=white[fg];[1:v][fg]overlay=format=auto" \
-frames:v 1 out.png
Added to the Wiki now ;-)
For the uninitiated, that CLI creates a processing graph:
black background (1:v) ------------------------> overlay ----> out.png
^
|
in.flac (0:a) ----> showwavespic ----> (fg) -------+
where e.g. the overlay filter takes two image inputs and produces the desired output, and fg is just a name assigned to an intermediate node.
Split channels
The tutorial also covers other options such as split channels with -filter_complex "showwavespic=s=640x480:colors=black:split_channels=1":
gnuplot plot with axes
OK, I'll admit it, FFmpeg can't do this alone (yet!). But the Wiki already provides a data export method to gnuplot that works:
ffmpeg -i in.flac -ac 1 -filter:a aresample=8000 -map 0:a -c:a pcm_s16le -f data - | \
gnuplot -p -e "set terminal png size 640,360; set output 'out.png'; plot '<cat' binary filetype=bin format='%int16' endian=little array=1:0 with lines;"
Video representations
See: https://superuser.com/questions/843774/create-a-video-file-from-an-audio-file-and-add-visualizations-from-audio
Tested on Ubuntu 20.04, FFmpeg 4.2.4.
If you have a GUI environment you can use the audacity audio editor to load the mp3 and then use the print command to generate a pdf of the waveform. Then convert the pdf to png.
I would do something like this :
find a tool to convert mp3 to PCM, ie binary data with one 8 or 16 bit value
per sample. I guess mplayer can do that
pipe the result to a utility converting binary data to an ascii
representation of the numbers in decimal format
use gnuplot to transform this list of value into a png graph.
And voilĂ , the power of piping between unix tools. Now Step 2 in this list might be optionnal if gnuplot is able to read it's data from a binary format.
You might want to consider audiowaveform from the BBC.
audiowaveform is a C++ command-line application that generates waveform data from either MP3, WAV, or FLAC format audio files. Waveform data can be used to produce a visual rendering of the audio, similar in appearance to audio editing applications.
Waveform data files are saved in either binary format (.dat) or JSON (.json). Given an input waveform data file, audiowaveform can also render the audio waveform as a PNG image at a given time offset and zoom level.
The waveform data is produced from an input stereo audio signal by first combining the left and right channels to produce a mono signal. The next stage is to compute the minimum and maximum sample values over groups of N input samples (where N is controlled by the --zoom command-line option), such that each N input samples produces one pair of minimum and maxmimum points in the output.
https://github.com/bbcrd/audiowaveform
This is a standard function in SoX (command line tool for sound, Windows & Linux)
Check the 'spectrogram' function on http://sox.sourceforge.net/sox.html
"The spectrogram is rendered in a Portable Network Graphic (PNG) file, and shows time in the X-axis, frequency in the Y-axis, and audio signal magnitude in the Z-axis. Z-axis values are represented by the colour (or optionally the intensity) of the pixels in the X-Y plane. If the audio signal contains multiple channels then these are shown from top to bottom starting from channel 1 (which is the left channel for stereo audio)."
Building on the answer of qubodup
# install stuff
apt install gnuplot
apt install sox
apt install libsox-fmt-mp3
#create plaintext file of amplitude values
sox sound.mp3 sound.dat
# run script saved on audio.gpi file
gnuplot audio.gpi
You can also comment the "set output ..." line in the configuration file and do
gnuplot audio.gpi > my_sound.png
The configuration file is audio.gpi in this case and inside it has
#!/usr/bin/env gnuplot
set datafile commentschars ";"
set terminal png #size 800,400
set output "sound.png"
unset border
unset xtics
unset ytics
set key off
plot "sound.dat" with lines
Which produces images like the following
I wanted no axis, no legend, png (much smaller than svg).

GNUplot movie from plots

My program generates 100 plots in GNUplot. I would like to concatenate them into a short little film, where each plot is ~0.1s. How can I do this most efficiently?
The least efficient method I can imagine would be to take a screen shot of each plot, somehow put the frames together, and then crop the movie. Thoughts?
Edit: By movie I mean either an animated GIF or a .mov or something like that. The main problem is getting the images from the plots.
Why use a screenshot? Simply set the terminal to GIF or PNG or whatever, then you get the images. Type "help set terminal" at the gnuplot prompt for a list of which terminals are available to you.
To make an animated gif, you can use Gifsicle or the Gimp.

Resources