Revision 7c331b1ee58f504e2f77c8ec64224ad3b674463b authored by Ronny Lorenz on 04 May 2015, 13:34:30 UTC, committed by Ronny Lorenz on 04 May 2015, 13:34:30 UTC
1 parent fa00faf
Raw File
plot_layouts.c
/**
 * This file is a container for all plotting layout algorithms
 *
 *  c Ronny Lorenz
 *    The ViennaRNA Package
 */

#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "utils.h"
#include "plot_layouts.h"

#ifdef _OPENMP
#include <omp.h>
#endif

#define PUBLIC
#define PRIVATE static

PUBLIC  int     rna_plot_type = 1;  /* 0 = simple, 1 = naview, 2 = circular plot */

PRIVATE float   *angle;
PRIVATE int     *loop_size, *stack_size;
PRIVATE int     lp, stk;

PRIVATE void  loop(int i, int j, short *pair_table);

#ifdef _OPENMP
/* NOTE: all threadprivate variables are uninitialized when entering a thread! */
#pragma omp threadprivate(angle, loop_size, stack_size, lp, stk)
#endif

/*---------------------------------------------------------------------------*/

PUBLIC int simple_xy_coordinates(short *pair_table, float *x, float *y)
{
  float INIT_ANGLE=0.;     /* initial bending angle */
  float INIT_X = 100.;     /* coordinate of first digit */
  float INIT_Y = 100.;     /* see above */
  float RADIUS =  15.;

  int i, length;
  float  alpha;

  length = pair_table[0];
  angle =      (float*) space( (length+5)*sizeof(float) );
  loop_size  =   (int*) space( 16+(length/5)*sizeof(int) );
  stack_size =   (int*) space( 16+(length/5)*sizeof(int) );
  lp = stk = 0;
  loop(0, length+1, pair_table);
  loop_size[lp] -= 2;     /* correct for cheating with function loop */

  alpha = INIT_ANGLE;
  x[0]  = INIT_X;
  y[0]  = INIT_Y;

  for (i = 1; i <= length; i++) {
    x[i] = x[i-1]+RADIUS*cos(alpha);
    y[i] = y[i-1]+RADIUS*sin(alpha);
    alpha += PI-angle[i+1];
  }
  free(angle);
  free(loop_size);
  free(stack_size);

  return length;

}

/*---------------------------------------------------------------------------*/

PRIVATE void loop(int i, int j, short *pair_table)
             /* i, j are the positions AFTER the last pair of a stack; i.e
                i-1 and j+1 are paired. */
{
  int    count = 2;   /* counts the VERTICES of a loop polygon; that's
                           NOT necessarily the number of unpaired bases!
                           Upon entry the loop has already 2 vertices, namely
                           the pair i-1/j+1.  */

  int    r = 0, bubble = 0; /* bubble counts the unpaired digits in loops */

  int    i_old, partner, k, l, start_k, start_l, fill, ladder;
  int    begin, v, diff;
  float  polygon;

  short *remember;

  remember = (short *) space((1+(j-i)/5)*2*sizeof(short));

  i_old = i-1, j++;         /* j has now been set to the partner of the
                               previous pair for correct while-loop
                               termination.  */
  while (i != j) {
    partner = pair_table[i];
    if ((!partner) || (i==0))
      i++, count++, bubble++;
    else {
      count += 2;
      k = i, l = partner;    /* beginning of stack */
      remember[++r] = k;
      remember[++r] = l;
      i = partner+1;         /* next i for the current loop */

      start_k = k, start_l = l;
      ladder = 0;
      do {
        k++, l--, ladder++;        /* go along the stack region */
      }
      while (pair_table[k] == l);

      fill = ladder-2;
      if (ladder >= 2) {
        angle[start_k+1+fill] += PIHALF;   /*  Loop entries and    */
        angle[start_l-1-fill] += PIHALF;   /*  exits get an        */
        angle[start_k]        += PIHALF;   /*  additional PI/2.    */
        angle[start_l]        += PIHALF;   /*  Why ? (exercise)    */
        if (ladder > 2) {
          for (; fill >= 1; fill--) {
            angle[start_k+fill] = PI;    /*  fill in the angles  */
            angle[start_l-fill] = PI;    /*  for the backbone    */
          }
        }
      }
      stack_size[++stk] = ladder;
      loop(k, l, pair_table);
    }
  }
  polygon = PI*(count-2)/(float)count; /* bending angle in loop polygon */
  remember[++r] = j;
  begin = i_old < 0 ? 0 : i_old;
  for (v = 1; v <= r; v++) {
    diff  = remember[v]-begin;
    for (fill = 0; fill <= diff; fill++)
      angle[begin+fill] += polygon;
    if (v > r)
      break;
    begin = remember[++v];
  }
  loop_size[++lp] = bubble;
  free(remember);
}

/*---------------------------------------------------------------------------*/

PUBLIC int simple_circplot_coordinates(short *pair_table, float *x, float *y){
  unsigned int  length = (unsigned int) pair_table[0];
  unsigned int  i;
  float         d = 2*PI/length;
  for(i=0; i < length; i++){
    x[i] = cos(i * d - PI/2);
    y[i] = sin(i * d - PI/2);
  }
  return length;
}
back to top