Logo Search packages:      
Sourcecode: raster3d version File versions  Download package

rods.f

      PROGRAM RODS
*------------------------------------------------------------------------------
*       Program to set up input for RENDER with CYLINDERs drawn between
*     each pair of atoms lying closer than 0.6 * (sum of VanderWaals radii). 
*     This program is the same as SETUP, except for what is generated.
*     Input matrix or angles are taken from setup.matrix or setup.angles
*     (NB: same files as setup)
*
* Eric Swanson   Oct 1991
*     Modified to generate cylinders with half bond colors, where needed.
* EAM Feb 1997
*     -radius XX to set cylinder radius
* EAM Sep 1997
*     -default colors; option for coloring by B-value
*     -more generous output formats (FORMATs 130 and 140)
* EAM Jun 1999
*     -brad XX to set ball radius as fraction of Van der Waals radius
* EAM Jul 1999
*     don't draw bonds across alternate chain locations
*
*------------------------------------------------------------------------------
      INCLUDE 'VERSION.incl'
*
*     I/O units for colour/co-ordinate input, specs output, user output
      INTEGER INPUT, OUTPUT, NOISE
      PARAMETER (INPUT=5, OUTPUT=6, NOISE=0)
      PARAMETER (MAXCOL=5000, MAXATM=100000)
      REAL RGB(3,MAXCOL),VDW(MAXCOL)
      REAL SPAM(6,MAXATM)
      REAL CEN(3)
      CHARACTER*24 MASK(MAXCOL),TEST
      CHARACTER*80 ATOM(MAXATM),CARD
      LOGICAL MATCH
C
C     flags include 
C           -b (ball and stick)
C           -h (suppress header records in output)
C           -radius XX (set cylinder radius)
C           -brad XX (set ball radius as fraction of VdW)
C
      character*64 options
      logical      bflag, hflag, bcflag, brflag
      real     cylrad, ballrad
c
c     Read in 3x3 view matrix from file setup.matrix.  
c     Matrix is applied before finding translation, center, and scale.  
c     Afterwards the input matrix to RENDER is therefore the identity matrix.
C                                                     
      common /matrix/ matrix, coords
      real        matrix(3,3), coords(3)
C
C     Default to CPK colors and VDW radii
      character*60 defcol(7)
      data defcol /
     & 'COLOUR#######C################   0.625   0.625   0.625  1.70',
     & 'COLOUR#######N################   0.125   0.125   1.000  1.60',
     & 'COLOUR#######O################   0.750   0.050   0.050  1.50',
     & 'COLOUR#######S################   1.000   1.000   0.025  1.85',
     & 'COLOUR#######H################   1.000   1.000   1.000  1.20',
     & 'COLOUR#######P################   0.400   1.000   0.400  1.80',
     & 'COLOUR########################   1.000   0.000   1.000  2.00'
     &            /
c
    3 format(a,a)
c
      bflag  = .FALSE.
      bcflag = .FALSE.
      hflag  = .FALSE.
      brflag = .FALSE.
      cylrad = 0.2
      ballrad= 0.2
      narg  = iargc()
      i = 1
  500 continue
            call getarg( i, options )
            if (options(1:2) .eq. '-h') hflag = .true.
            if (options(1:5) .eq. '-Bcol') then
                bcflag = .true.
                i = i + 1
                if (i.gt.narg) goto 701
                call getarg( i, options )
                read (options,*,err=701) Bmin
                i = i + 1
                if (i.gt.narg) goto 701
                call getarg( i, options )
                read (options,*,err=701) Bmax
            endif
            if (options(1:2) .eq. '-b') bflag = .true.
          if (options(1:2) .eq. '-r') then
            i = i + 1
            if (i.gt.narg) goto 701
            call getarg( i, options )
            read (options,*,err=701) cylrad
            if (cylrad.le.0) stop 'illegal radius value'
          end if
          if (options(1:3) .eq. '-br') then
            i = i + 1
            if (i.gt.narg) goto 701
            call getarg( i, options )
            read (options,*,err=701) ballrad
            if (ballrad.le.0) stop 'illegal ball radius value'
            bflag = .true.
          end if
      i = i + 1
      if (i.le.narg) goto 500
c
      goto 799
  701 write (noise,'(A)')
     &      'syntax: rods [-h] [-b] [-Bcolor Bmin Bmax] [-radius R]'
      call exit(-1)
  799 continue
c
      write (noise,*) 'Raster3D rods program ',VERSION
      if (bcflag) then
        write (noise,*) 'Atom colors will be assigned based on Biso'
        write (noise,*) '    from dark blue = Bmin =', Bmin
        write (noise,*) '      to light red = Bmax =', Bmax
      endif
c
C
      do i=1,3
      do j=1,3
          matrix(i,j)=0.
      enddo
      matrix(i,i)=1.
      enddo
      call view_matrix
c
      if (.not. hflag) then
      WRITE(OUTPUT,'(A,A)') 'rods ',VERSION
      WRITE(OUTPUT,'(A)') '80  64    tiles in x,y'
      WRITE(OUTPUT,'(A)') ' 8   8    pixels (x,y) per tile'
      WRITE(OUTPUT,'(A)') '4         anti-aliasing'
      WRITE(OUTPUT,'(A)') '0 0 0     black background'
      WRITE(OUTPUT,'(A)') 'F         no, shadowed rods look funny'
      WRITE(OUTPUT,'(A)') '25        Phong power'
      WRITE(OUTPUT,'(A)') '0.15      secondary light contribution'
      WRITE(OUTPUT,'(A)') '0.05      ambient light contribution'
      WRITE(OUTPUT,'(A)') '0.25      specular reflection component'
      WRITE(OUTPUT,'(A)') '4.0       eye position'
      WRITE(OUTPUT,'(A)') '1 1 1     main light source position'
      end if
c
      ASPECT = 1280./1024.
      NCOL = 0
      NATM = 0
10    CONTINUE
        READ(INPUT,'(A80)',END=50) CARD
        IF (CARD(1:4).EQ.'COLO') THEN
          NCOL = NCOL + 1
          IF (NCOL.GT.MAXCOL) THEN
            WRITE(NOISE,*) 'Colour table overflow.  Increase ',
     &                     'MAXCOL and recompile.'
            STOP 10
          ENDIF
          READ(CARD,'(6X,A24,3F8.3,F6.2)',ERR=49) 
     &             MASK(NCOL), (RGB(I,NCOL),I=1,3),VDW(NCOL)
        ELSEIF (CARD(1:4).EQ.'ATOM'.OR.CARD(1:4).EQ.'HETA') THEN
          NATM = NATM + 1
          IF (NATM.GT.MAXATM) THEN
            WRITE(NOISE,*) 'Atom array overflow.  Increase ',
     &                     'MAXATM and recompile.'
            STOP 20
          ENDIF
          ATOM(NATM) = CARD
        ELSEIF (CARD(1:3).EQ.'END') THEN
          GO TO 50
        ENDIF
        GO TO 10
*     Problems reading input record
49    continue
      write(noise,*) 'rods: Cannot parse input record ',CARD
      call exit(-1)
*     Come here when EOF or 'END' record is reached
50    CONTINUE
      IF (NATM.EQ.0) THEN
        WRITE(NOISE,*) 'No atoms in input.'
        STOP 30
      ENDIF
*     Load default colors after any that were read in
      IF (NCOL.LT.MAXCOL-8) THEN
        DO i = 1,7
          NCOL = NCOL + 1
          READ(defcol(i),'(6X,A24,3F8.3,F6.2)') MASK(NCOL),
     &          (RGB(J,NCOL),J=1,3), VDW(NCOL)
        ENDDO
      ENDIF
*
      IF (NCOL.EQ.0) THEN
        WRITE(NOISE,*) 'No colours in input.'
        STOP 40
      ENDIF
      XMAX = -1E20
      XMIN =  1E20
      YMAX = -1E20
      YMIN =  1E20
      ZMAX = -1E20
      ZMIN =  1E20
      DO 100 IATM=1,NATM
        CARD = ATOM(IATM)
        TEST = CARD(7:30)
        DO 80 ICOL=1,NCOL
          IF (MATCH(TEST,MASK(ICOL))) THEN
c           READ(CARD,'(30X,3F8.3)',err=49) X,Y,Z
c EAM Oct88
            READ(CARD,'(30X,3F8.3,6X,F8.2)',err=49) coords, Biso
            x = coords(1)*matrix(1,1) + coords(2)*matrix(2,1) 
     1        + coords(3)*matrix(3,1)
            y = coords(1)*matrix(1,2) + coords(2)*matrix(2,2) 
     1        + coords(3)*matrix(3,2)
            z = coords(1)*matrix(1,3) + coords(2)*matrix(2,3)
     1        + coords(3)*matrix(3,3)
c EAM Oct88
            RAD = VDW(ICOL)
            SPAM(1,IATM) = X
            SPAM(2,IATM) = Y
            SPAM(3,IATM) = Z
            SPAM(4,IATM) = RAD
            SPAM(5,IATM) = ICOL
          SPAM(6,IATM) = Biso
            XMAX = MAX(XMAX,X+RAD)
            XMIN = MIN(XMIN,X-RAD)
            YMAX = MAX(YMAX,Y+RAD)
            YMIN = MIN(YMIN,Y-RAD)
            ZMAX = MAX(ZMAX,Z+RAD)
            ZMIN = MIN(ZMIN,Z-RAD)
            GO TO 100
          ENDIF
80      CONTINUE
        WRITE(NOISE,*) 'No colour table mask matches this atom:'
        WRITE(NOISE,*) ATOM(IATM)
        STOP 90
100   CONTINUE
      XMID = (XMAX+XMIN)/2.
      YMID = (YMAX+YMIN)/2.
      ZMID = (ZMAX+ZMIN)/2.
      TX = -XMID
      TY = -YMID
      TZ = -ZMID
      IF (ASPECT.GE.1.) THEN
*       The X direction is wider than the Y
        XROOM = ASPECT
        YROOM = 1.
        ZROOM = 2.
      ELSE
        XROOM = 1.
        YROOM = ASPECT
        ZROOM = 2.
      ENDIF
      XSPAN = XMAX-XMIN
      YSPAN = YMAX-YMIN
      ZSPAN = ZMAX-ZMIN
      SCALE = MAX(XSPAN/XROOM,YSPAN/YROOM,ZSPAN/ZROOM)
*     Leave a little extra room as a border:
      SCALE = SCALE / 0.90
c
      if (.not. hflag) then
      WRITE(OUTPUT,120) TX,TY,TZ,SCALE
120   FORMAT('1 0 0 0   input co-ordinate + radius transformation'/
     &       '0 1 0 0'/
     &       '0 0 1 0'/
     &       4F10.3)
      WRITE(OUTPUT,'(A)') '3         mixed object types'
      WRITE(OUTPUT,'(A)') '*'
      WRITE(OUTPUT,'(A)') '*'
      WRITE(OUTPUT,'(A)') '*'
      end if
C
C     Here's the real loop.  
C     Look for pairs closer to each other than 0.60 times the
C     sum of the vanderWaals radii.
C     Draw all cylinders with 0.2A cylindrical radius.
C     For ball and stick pictures, shrink vanderWaals radius
C     of balls by 0.20
C     If two atoms of different colors are bonded, make half-bond
C     cylinders with each color.
C
      CLOSE = 1.6 * 1.6
C
      IF (BFLAG) THEN
      DO 135 IATM=1,NATM
      RAD  = SPAM(4,IATM) * ballrad
      ICOL = SPAM(5,IATM)
      if (bcflag) then
          call B2RGB( SPAM(6,IATM), Bmin, Bmax, RED, GREEN, BLUE )
          RED   = RED*RED
          GREEN = GREEN*GREEN
          BLUE  = BLUE*BLUE
      else
          RED   = RGB(1,ICOL)
          GREEN = RGB(2,ICOL)
          BLUE  = RGB(3,ICOL)
      endif
      WRITE(OUTPUT,130)
     2         SPAM(1,IATM),SPAM(2,IATM),SPAM(3,IATM),RAD,
     3         RED,GREEN,BLUE
C130  FORMAT(1H2,/,7f8.3)
130   FORMAT(1H2,/,7(1X,F8.3))
135   CONTINUE
      ENDIF
C
      DO 160 IATM=1,NATM
      DO 150 JATM=IATM+1,NATM
      DX = SPAM(1,IATM) - SPAM(1,JATM)
      DY = SPAM(2,IATM) - SPAM(2,JATM)
      DZ = SPAM(3,IATM) - SPAM(3,JATM)
      DIST  = DX*DX + DY*DY + DZ*DZ
      CLOSE = 0.6 * (SPAM(4,IATM) + SPAM(4,JATM)) 
      CLOSE = CLOSE**2
      IF (ATOM(IATM)(17:17).NE.' ' .AND. ATOM(JATM)(17:17).NE.' '
     &     .AND. ATOM(IATM)(17:17).NE.ATOM(JATM)(17:17)) GOTO 150
c
c 4-Feb-2000      also force chain ID's to be the same
c
      IF (ATOM(IATM)(22:22).NE.' ' .AND. ATOM(JATM)(22:22).NE.' '
     &     .AND. ATOM(IATM)(22:22).NE.ATOM(JATM)(22:22)) GOTO 150
      IF (DIST .LE. CLOSE) THEN
        if (bcflag) then
          ICOL = 1
          JCOL = 2
          call B2RGB( SPAM(6,IATM), Bmin, Bmax, RED, GREEN, BLUE )
          RGB(1,ICOL) = RED*RED
          RGB(2,ICOL) = GREEN*GREEN
          RGB(3,ICOL) = BLUE*BLUE
          call B2RGB( SPAM(6,JATM), Bmin, Bmax, RED, GREEN, BLUE )
          RGB(1,JCOL) = RED*RED
          RGB(2,JCOL) = GREEN*GREEN
          RGB(3,JCOL) = BLUE*BLUE
        else
          ICOL = SPAM(5,IATM)
          JCOL = SPAM(5,JATM)
        endif
        IF(ICOL.EQ.JCOL) THEN
          WRITE(OUTPUT,140)
     1         SPAM(1,IATM),SPAM(2,IATM),SPAM(3,IATM),CYLRAD,
     2         SPAM(1,JATM),SPAM(2,JATM),SPAM(3,JATM),CYLRAD,
     3         RGB(1,ICOL),RGB(2,ICOL),RGB(3,ICOL)
        else if (bcflag) then
          write(output,140)
     1         SPAM(1,IATM),SPAM(2,IATM),SPAM(3,IATM),CYLRAD,
     2         SPAM(1,JATM),SPAM(2,JATM),SPAM(3,JATM),CYLRAD,
     3         RGB(1,ICOL),RGB(2,ICOL),RGB(3,ICOL)
          write(output,141)
     1             RGB(1,ICOL),RGB(2,ICOL),RGB(3,ICOL),
     2             RGB(1,JCOL),RGB(2,JCOL),RGB(3,JCOL),
     3         0, 0, 0
        ELSE
          DO 136 K=1,3
136       CEN(K) = (SPAM(K,IATM)+SPAM(K,JATM))/2
          WRITE(OUTPUT,140)
     1         SPAM(1,IATM),SPAM(2,IATM),SPAM(3,IATM),CYLRAD,
     2         CEN(1),CEN(2),CEN(3),CYLRAD,
     3         RGB(1,ICOL),RGB(2,ICOL),RGB(3,ICOL)
          WRITE(OUTPUT,140)
     1         CEN(1),CEN(2),CEN(3),CYLRAD,
     2         SPAM(1,JATM),SPAM(2,JATM),SPAM(3,JATM),CYLRAD,
     3         RGB(1,JCOL),RGB(2,JCOL),RGB(3,JCOL)
        ENDIF
      ENDIF

C140   FORMAT(1H3,/,11f8.3)
140   FORMAT(1H3,/,2(1X,F8.3,1X,F8.3,1X,F8.3,1X,F7.3),3F7.3)
141   format(2H17,/3(1X,3F6.3))
150   CONTINUE
160   CONTINUE
C
C
C
      write (noise,'(/)')
      write (noise,156) 'X  min max:', XMIN, XMAX
      write (noise,156) 'Y  min max:', YMIN, YMAX
      write (noise,156) 'Z  min max:', ZMIN, ZMAX
      write (noise,156) '     scale:', SCALE
  156 format(1x,a,3f8.2)
      END
      LOGICAL FUNCTION MATCH (SUBJ, MASK)
      CHARACTER*24 SUBJ,MASK
      MATCH = .FALSE.
      DO 10 I = 1, 24
        IF (SUBJ(I:I).NE.MASK(I:I) .AND. MASK(I:I).NE.'#') RETURN
10    CONTINUE
      MATCH = .TRUE.
      RETURN
      END

      subroutine view_matrix
c
      common /matrix/ matrix, coords
      real        matrix(3,3), coords(3)
c
      real        phiX, phiY, phiZ
      integer    noise
      parameter (noise = 0)
      parameter (R2D = 180./3.1415927)

      open (unit=3, file='setup.matrix', status='OLD', err=100)
            read (3,*) ((matrix(i,j),i=1,3),j=1,3)
            write (noise,'(1x,3f9.5)') ((matrix(i,j),i=1,3),j=1,3)
            close (3)

            det = matrix(1,1) * matrix(2,2) * matrix(3,3)
     1          + matrix(1,2) * matrix(2,3) * matrix(3,1)
     2          + matrix(2,1) * matrix(3,2) * matrix(1,3)
     3          - matrix(1,3) * matrix(2,2) * matrix(3,1)
     4          - matrix(1,2) * matrix(2,1) * matrix(3,3)
     5          - matrix(1,1) * matrix(2,3) * matrix(3,2)
            write (noise,'(''       determinant ='',f8.3)') det

            phiX = atan2( -matrix(3,2), matrix(3,3) )
            phiY = atan2(  matrix(3,1), matrix(3,3) / cos(phiX) )
            phiZ = atan2( -matrix(2,1), matrix(1,1) )
            write (noise,3) ' View Angles from matrix',' '
            write (noise,2) phiZ*R2D, phiY*R2D, phiX*R2D
            return
  100 continue

      open (unit=3, file='setup.angles', status='OLD', err=200)
            read (3,*) phiZ, phiY, phiX
            close (3)
            write (noise,2) phiZ, phiY, phiX
            cx = cos(phiX/R2D)
            sx = sin(phiX/R2D)
            cy = cos(phiY/R2D)
            sy = sin(phiY/R2D)
            cz = cos(phiZ/R2D)
            sz = sin(phiZ/R2D)
            matrix(1,1) = cz*cy
            matrix(1,2) = sz*cx + cz*sy*sx
            matrix(1,3) = sz*sx - cz*sy*cx
            matrix(2,1) = -sz*cy
            matrix(2,2) = cz*cx - sx*sy*sz
            matrix(2,3) = cz*sx + sz*sy*cx
            matrix(3,1) = sy
            matrix(3,2) = -sx*cy
            matrix(3,3) = cx*cy
            write (noise,3) ' View Matrix from angles',' '
            write (noise,'(1x,3f9.5)') ((matrix(i,j),i=1,3),j=1,3)
            return
  200 continue

    2       format(1x,'   phiZ =',f8.2,'   phiY =',f8.2,'   phiX =',f8.2)
    3 format(/a,a)

      write (noise,*) ' No view matrix or angles provided'
      return
      end

CCC     Return RGB triple that runs from dark blue at Bmin
CC      to light red at Bmax
C
      subroutine B2RGB( Biso, Bmin, Bmax, R, G, B )
      real              Biso, Bmin, Bmax, R, G, B
c
      real fraction, h, s, v
c
      fraction = (Biso-Bmin) / (Bmax-Bmin)
      if (fraction.lt.0.) fraction = 0.
      if (fraction.gt.1.) fraction = 1.
        h = 240. * (1.-fraction)
        s = 0.8
        v = 0.5 + fraction/2.
        call hsv2rgb( h, s, v, r, g, b )
        return
      end


CCC   Color format conversion from Hue/Saturation/Value to Red/Green/Blue
CC    minimal (i.e. NO) error checking
C
      subroutine hsv2rgb( h, s, v, r, g, b )
      real                h, s, v, r, g, b
c
      real    f, p, q, t
      integer i
c
      i = h /60.
      f = h/60. - float(i)
      p = v * (1. - s)
      q = v * (1. - s*f)
      t = v * (1. - s*(1. - f))
      if (i.eq.5) then
          r = v
          g = p
          b = q
      else if (i.eq.4) then
          r = t
          g = p
          b = v
      else if (i.eq.3) then
          r = p
          g = q
          b = v
      else if (i.eq.2) then
          r = p
          g = v
          b = t
      else if (i.eq.1) then
          r = q
          g = v
          b = p
      else
          r = v
          g = t
          b = p
      endif
      return 
      end

Generated by  Doxygen 1.6.0   Back to index