You might set DoubleBuffered to true on your control / form. Or you could try using your own Image to create a double buffered effect.
My DoubleBufferedGraphics class:
public class DoubleBufferedGraphics : IDisposable
{
    #region Constructor
    public DoubleBufferedGraphics() : this(0, 0) { }
    public DoubleBufferedGraphics(int width, int height)
    {
        Height = height;
        Width = width;
    }
    #endregion
    #region Private Fields
    private Image _MemoryBitmap;
    #endregion
    #region Public Properties
    public Graphics Graphics { get; private set; }
    public int Height { get; private set; }
    public bool Initialized
    {
        get { return (_MemoryBitmap != null); }
    }
    public int Width { get; private set; }
    #endregion
    #region Public Methods
    public void Dispose()
    {
        if (_MemoryBitmap != null)
        {
            _MemoryBitmap.Dispose();
            _MemoryBitmap = null;
        }
        if (Graphics != null)
        {
            Graphics.Dispose();
            Graphics = null;
        }
    }
    public void Initialize(int width, int height)
    {
        if (height > 0 && width > 0)
        {
            if ((height != Height) || (width != Width))
            {
                Height = height;
                Width = width;
                Reset();
            }
        }
    }
    public void Render(Graphics graphics)
    {
        if (_MemoryBitmap != null)
        {
            graphics.DrawImage(_MemoryBitmap, _MemoryBitmap.GetRectangle(), 0, 0, Width, Height, GraphicsUnit.Pixel);
        }
    }
    public void Reset()
    {
        if (_MemoryBitmap != null)
        {
            _MemoryBitmap.Dispose();
            _MemoryBitmap = null;
        }
        if (Graphics != null)
        {
            Graphics.Dispose();
            Graphics = null;
        }
        _MemoryBitmap = new Bitmap(Width, Height);
        Graphics = Graphics.FromImage(_MemoryBitmap);
    }
    /// <summary>
    /// This method is the preferred method of drawing a background image.
    /// It is *MUCH* faster than any of the Graphics.DrawImage() methods.
    /// Warning: The memory image and the <see cref="Graphics"/> object
    /// will be reset after calling this method. This should be your first
    /// drawing operation.
    /// </summary>
    /// <param name="image">The image to draw.</param>
    public void SetBackgroundImage(Image image)
    {
        if (_MemoryBitmap != null)
        {
            _MemoryBitmap.Dispose();
            _MemoryBitmap = null;
        }
        if (Graphics != null)
        {
            Graphics.Dispose();
            Graphics = null;
        }
        _MemoryBitmap = image.Clone() as Image;
        if (_MemoryBitmap != null)
        {
            Graphics = Graphics.FromImage(_MemoryBitmap);
        }
    }
    #endregion
}
Using it in an OnPaint:
protected override void OnPaint(PaintEventArgs e)
{
    if (!_DoubleBufferedGraphics.Initialized)
    {
        _DoubleBufferedGraphics.Initialize(Width, Height);
    }
    _DoubleBufferedGraphics.Graphics.DrawLine(...);
    _DoubleBufferedGraphics.Render(e.Graphics);
}
ControlStyles I generally set if I'm using it (you may have different needs):
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
Edit:
Ok since the data is static you should paint to an Image (before your OnPaint) and then in the OnPaint use the Graphics.DrawImage() overload to draw the correct region of your source image to the screen. No reason to redraw the lines if the data isn't changing.