2

I have time series data (signal) of different length that I would like to plot without any margins between scale and signal.

Goal: plot each signal so (physical) printing of the plot will show every single data point. The plot shall be saved to a file.

Given:

  1. printer with 600 dpi maximum printing resolution.
  2. signals with different number of data points (from 30000 to 100000).

example of signal:

import numpy as np
Fs = 512
# Create random signal
np.random.seed(1)
data = [np.random.uniform(-10000, 20000) for i in range(5*Fs)]

If I just plot it with matplotlib:

import matplotlib.pyplot as plt
plt.figure(figsize=(len(data)/600,2)) # divide by 600 which is dpi resolution of printer
plt.plot(data, color = "black", linewidth = 1.0)
plt.show()

data plot

I do not want any white space between the first data point and the Y axis or between the last data point and the right border. The label of the Y axis should also not interfere with the plot's size, so its width should also be considered.

How do I accomplish to have every single point printed?

  • To remove the white space set `plt.xlim([...])` and `plt.ylim([...])` to exactly match your data. If you really want every point printed you should probably save the plot in a vector-graphics format, and then print sufficiently large. First, I don't really see why you'd want this. Second, I don't think you can ever be sure, your printer's driver and its software might also influence what is actually printed. – Tom de Geus Oct 20 '17 at 08:31
  • As an alternative to the above comment, `plt.margins(0,0)` to remove the automatic margins – DavidG Oct 20 '17 at 08:32
  • I'm not sure if `margins` solves this problem (probably only part of it). On the other hand its totally unclear what "print every single point" means if you have 100000 points. If you have 100000 points divided 600 dpi = 166 inch = 4.20 meters. There is no paper that measures 4 meters. So in that sense I still think this question is not answerable. – ImportanceOfBeingErnest Oct 20 '17 at 09:03
  • Comment on your figsize: the figsize is including axis labels and everything, so your way of setting the figsize is probably not what you really want. If you have an infinite paper printer, your approach maybe makes sense, but it is hard to see... – Sosel Oct 20 '17 at 09:33
  • Thank you all for your input. I gathered some single channel traces which I want printed sufficiently large to see patterns by eye. Yes, that is an unusual task and yes, the printer I can use is not limited in length of paper. – user7677771 Oct 24 '17 at 09:33

1 Answers1

3

I will neglect the point about more than 30000 points as this is nonsense for printing. So assuming a configuration as implied by the code of some 3000 points or so, you can calculate the figure size needed to show the plot with one point per printable point. You would also need to make sure that the linewidth is actually one dot wide.

import numpy as np
Fs = 512
# Create random signal
np.random.seed(1)
data = [np.random.uniform(-10000, 20000) for i in range(5*Fs)]

import matplotlib.pyplot as plt

dpi = 600
figheight = 4 # inch, some constant number

margin_left  = 1.0  # inch
margin_right = 0.4 # inch

figwidth = (len(data)/float(dpi)) + margin_left + margin_right # inch


plt.figure(figsize=(figwidth,figheight), dpi=dpi) 
plt.margins(x=0) # remove inner-axis padding of data
plt.subplots_adjust(left=margin_left/float(figwidth),
                    right=1.-margin_right/float(figwidth))
 # use 72/dpi for linewidth such that one point is one dot
plt.plot(data, color = "black", linewidth = 72./dpi)
plt.savefig("output.png", dpi="figure")
# note that show() may not make sense, 
# since it readjusts the figure size to maximum screen size
plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Thank you for your excellent answer. Coming back to the unusually large number of data points, this error shows when exceuting with more 70000 points: `ValueError: Image size of 79105x2400 pixels is too large. It must be less than 2^16 in each direction.` What can be done about this (besides splitting the graph into multiple parts and rejoin with another program)? – user7677771 Oct 24 '17 at 09:34