Click here to Skip to main content
13,802,240 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

3.6K views
Posted 14 Nov 2015
Licenced LGPL3

Generate Color Mappings on Circos plot for prokaryote comparative genomics

Rate this:
Please Sign up or sign in to vote.
Recently I was drawing a virus genome circos plot apply in a Ebolavirus comparative genomics study.

Editorial Note

This Review is from our sponsors at CodeProject. These reviews are intended to provide you with information on products and services that we consider useful and of value to developers.

Recently I was drawing a virus genome circos[1] plot apply in a Ebolavirus comparative genomics study. Following on the description on the literature[2], I was try to drawing the variation of each nt base on the genome sequence, and the drawing base color was mapping as a gradient color to the site conservative. But sorry for my failure on my mathematics in the university, I could not figure out how to generates the color mapping from nt base conservation to the actually circos color in RBG, by Google search and I finally found out a perfect solution on MSDN today.

Atlas of the genome of ebolavirus KJ660347

Atlas of the genome of ebolavirus KJ660347[2], showing, from the outer ring inwards, variations within 84 other ebolavirus genomes, structural cruciforms and palindromes (van Noort et al. 2003), the coding sequences, local inverted repeats, palindromic hexamers, simple repeats and AT content. The conservation percentage (%) is defined as the number of genomes with the same letter on amultiple sequence alignment normalized to range from0 to 100% for each site along the chromosome of Ebola KJ660347.

The original post can be found at here: <Generate Color Sequences Using RGB Color Cube in VB.Net>

 

Source Code can be download at here:  ColorCube.vb

Introduction

Sometimes when you are designing a form, or creating some other kind of visual output, you’d like to generate an array of colors which may be shades of a single color or a discernible sequence of individual colors such as the spectrum of a rainbow.  This can be useful for coloring bars in a graph or generating a gradient around some specified color.  Unfortunately the .Net framework does not give us any sophisticated solution for this.

While any number of complex code solutions could be created to attempt to address this problem, if we think of the RGB color space spatially, we can construct a three-dimensional cube which represents all possible colors and can easily be traversed mathematically.

The RGB Color Cube

This is a RGB Color Cube:

1817.RgbColorCube

A color value in the RGB color space has three components; the Red, Green and Blue intensity values.  These values are expressed as Bytes and are therefore limited in range to 0 through 255.  We can think of these R, G, and B values as being the axis of a three dimensional space; in other words, the x, y, and z axis of a grid.  So we can define the RGB color space as a cube, 255 units on a side, with an origin at [0,0,0] which represents the color Black.  If we are facing the cube then, the red axis runs to the left, the blue axis to the right, and the green axis points upward from black.  The furthest corner from black would be [255,255,255], or White.

1832.RgbColorCubeAxis

The primary RGB colors (red, greed, blue, yellow, cyan, magenta, black, and white) exist at each corner of the cube:

0763.RgbColorCubePrimaryColors.jpg-550x0

The spectrum of full intensity colors (that is, the rainbow) is represented by following the outside edges of the cube from red, to yellow, to green and around to magenta.

0116.RgbColorCubeSpectrum

And since we have defined a three dimensional space we can find any sequence of colors between two colors by measuring angles and distances.

3122.RgbColorCubeDetail.jpg-550x0

Coding a ColorCube Class

Creating a class to represent this concept of a RGB Color Cube is really little more than a collection of functions.  There is no data-set to work with as, truly, the entire color cube concept is represented in the diagrams above.  Once we have decided to think of a color as a location within a predefined three-dimensional space, there is little more to do than math in order to generate various color sequences.  So rather than walk though writing the whole class step-by-step, we will just look at a few interesting properties of the cube and the related code.  A complete class example will be provided at the end of the article.

Brightness is Distance from Black

One interesting feature of the cube is that we can quickly determine the overall brightness of a color by measuring the distance from black using a basic distance formula:

Public Function GetDistance(ByVal source As Color, ByVal target As Color) As Double
    Dim squareR As Double = CDbl(target.R) - CDbl(source.R)
    squareR *= squareR
    Dim squareG As Double = CDbl(target.G) - CDbl(source.G)
    squareG *= squareG
    Dim squareB As Double = CDbl(target.B) - CDbl(source.B)
    squareB *= squareB
    Return System.Math.Sqrt(squareR + squareG + squareB)
End Function

 

While searching the net for some other related information, I came across some code to calculate a similar value in terms which can be represented by a Byte.  A translation of that code is included in the class below.

Colors can be compared by brightness as part of determining similarity or to ensure sufficient visible difference in a series of similar colors.

Public Function Compare(source As Color, target As Color) As Integer
    Dim delta1 As Double = GetDistance(Color.Black, source)
    Dim delta2 As Double = GetDistance(Color.Black, target)
    Return delta1.CompareTo(delta2)
End Function

 

Walking the Edges of the Cube

There is an algorithm used to move around the edges of the cube when generating a rainbow spectrum sequence which may be worth looking at for a moment.  The most basic color cube could be implemented with just this routine:

Public Function GetColorSpectrum(increment As Integer) As Color()
    Dim result As New List(Of Color)
    Dim rgb(2) As Integer
    Dim idx As Integer = 1
    Dim inc As Integer = increment
    Dim cmp As Func(Of Integer, Integer, Boolean)
 
    rgb(0) = 255
    cmp = AddressOf CompareLess
    Do
        result.Add(Color.FromArgb(rgb(0), rgb(1), rgb(2)))
        If cmp(rgb(idx), inc) Then
            rgb(idx) += inc
        Else
            Select Case idx
                Case 1
                    If rgb(2) < 255 Then

                        rgb(idx) = 255

                        idx = 0

                        cmp = AddressOf CompareGreater

                    Else

                        rgb(idx) = 0

                        idx = 0

                        cmp = AddressOf CompareLess

                    End If

                Case 2

                    rgb(idx) = 255

                    idx = 1

                    cmp = AddressOf CompareGreater

                Case 0

                    If rgb(2) < 255 Then

                        rgb(idx) = 0

                        idx = 2

                        cmp = AddressOf CompareLess

                    Else

                        rgb(idx) = 255

                        Exit Do

                    End If

            End Select

            inc *= -1

        End If

    Loop

    result.Add(Color.FromArgb(rgb(0), rgb(1), rgb(2)))

    Return result.ToArray

End Function

 

Public Function CompareLess(value As Integer, inc As Integer) As Boolean

    Return value < 255 - Math.Abs(inc)

End Function

 

Public Function CompareGreater(value As Integer, inc As Integer) As Boolean

    Return value > Math.Abs(inc)
End Function

 

This code is utilizing two helper methods making it easier to change functionality between moving from 0 to 255 and from 255 to 0 through the color component values.  This allows a relatively simple loop to walk around the edges of the cube as depicted in the image above.

Getting a Range of Colors

By organizing the RGB color space into a cube, generating a sequence of colors is little more than picking a starting color, a direction to move, and an increment of movement and then calculating a series of points along that line.  The following function will return a color which is at a given angle and distance from the specified color.  The angle is expressed in terms of azimuth (red to blue) and elevation (no green to full green).

Public Function GetColorFrom(source As Color, azimuth As Double, elevation As Double, distance As Double) As Color
    Dim a, e, r, g, b As Double
    a = azimuth
    e = elevation
    r = distance * Math.Cos(a) * Math.Cos(e)
    b = distance * Math.Sin(a) * Math.Cos(e)
    g = distance * Math.Sin(e)
    If Double.IsNaN(r) Then r = 0
    If Double.IsNaN(g) Then g = 0
    If Double.IsNaN(b) Then b = 0
    Return Color.FromArgb(Math.Max(Math.Min(source.R + r, 255), 0), Math.Max(Math.Min(source.G + g, 255), 0), Math.Max(Math.Min(source.B + b, 255), 0))
End Function

 

This allows us, for example, to create a function which can return a selection of colors taken from a sphere surrounding a target color:

Public Function GetColorsAround(target As Color, distance As Integer, increment As Integer)As Color()
    Dim result As New List(Of Color)
    For a As Integer = 0 To 359 Step increment
        For e As Integer = 0 To 359 Step increment
            Dim c As Color = GetColorFrom(target, a, e, distance)
            If Not result.Contains(c) Then
                result.Add(c)
            End If
        Next
    Next
    result.Sort(AddressOf Compare)
    Return result.ToArray
End Function

 

Or, with some additional helper methods, a function which can get the series of colors on a line between two given colors:

Public Function GetColorSequence(source As Color, target As Color, increment As Integer) AsColor()
    Dim result As New List(Of Color)
    Dim a As Double = GetAzimuthTo(source, target)
    Dim e As Double = GetElevationTo(source, target)
    Dim d As Double = GetDistance(source, target)
    For i As Integer = 0 To d Step increment
        result.Add(GetColorFrom(source, a, e, i, True))
    Next
    Return result.ToArray
End Function
Public Function GetAzimuthTo(ByVal source As Color, ByVal target As Color) As Double

    Return WrapAngle(Math.Atan2(CDbl(target.B) - CDbl(source.B), CDbl(target.R) -CDbl(source.R)))
End Function
 
Public Function GetElevationTo(ByVal source As Color, ByVal target As Color) As Double
    Return WrapAngle(Math.Atan2(CDbl(target.G) - CDbl(source.G), 255))
End Function
 
Public Function WrapAngle(ByVal radians As Double) As Double
    While radians < -Math.PI

        radians += Math.PI * 2

    End While

    While radians > Math.PI
        radians -= Math.PI * 2
    End While
    Return radians
End Function

 

As you can see these are mostly simple functions performing some minor trigonometry.  There’s no magic in the code… the magic is in the concept of the color cube.

Summary

By visualizing the RGB color space as a three-dimensional cube, it becomes possible to generate arrays of Color instances representing a spectrum or other sequence using relatively simple mathematical calculations.  Simple functions can be written to generate a series of colors for a number of different sequences.

References

  1. M. Krzywinski, J. Schein, I. Birol, J. Connors, R. Gascoyne, D. Horsman, S.J. Jones, and M.A. Marra, "Circos: An information aesthetic for comparative genomics", Genome Research, vol. 19, pp. 1639-1645, 2009. http://dx.doi.org/10.1101/gr.092759.109
  2. S. Jun, M.R. Leuze, I. Nookaew, E.C. Uberbacher, M. Land, Q. Zhang, V. Wanchai, J. Chai, M. Nielsen, T. Trolle, O. Lund, G.S. Buzard, T.D. Pedersen, T.M. Wassenaar, and D.W. Ussery, " Ebolavirus comparative genomics ", FEMS Microbiology Reviews, vol. 39, pp. 764-778, 2015. http://dx.doi.org/10.1093/femsre/fuv031
<!-- kcite-section 82 -->

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

Share

About the Author

Mr. xieguigang 谢桂纲
Student 中国南方微生物资源利用中心(SMRUCC)
China China
He is good and loves VisualBasic!



github: https://github.com/xieguigang

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02 | 2.8.181215.1 | Last Updated 14 Nov 2015
Article Copyright 2015 by Mr. xieguigang 谢桂纲
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid