class_docstr: TransformSystem encapsulates information about the coordinate
  systems needed to draw a Visual.
  
  Visual rendering operates in six coordinate systems:
  
  * **Visual** - arbitrary local coordinate frame of the visual. Vertex
    buffers used by the visual are usually specified in this coordinate
    system.
  
  * **Scene** - This is an isometric coordinate system used mainly for 
    lighting calculations.
  
  * **Document** - This coordinate system has units of _logical_ pixels, and
    should usually represent the pixel coordinates of the canvas being drawn
    to. Visuals use this coordinate system to make measurements for font
    size, line width, and in general anything that is specified in physical
    units (px, pt, mm, in, etc.). In most circumstances, this is exactly the
    same as the canvas coordinate system.
  
  * **Canvas** - This coordinate system represents the logical pixel
    coordinates of the canvas. It has its origin in the top-left corner of
    the canvas, and is typically the coordinate system that mouse and touch 
    events are reported in. Note that, by convention, _logical_ pixels
    are not necessarily the same size as the _physical_ pixels in the
    framebuffer that is being rendered to.
  
  * **Framebuffer** - The buffer coordinate system has units of _physical_ 
    pixels, and should usually represent the coordinates of the current 
    framebuffer (on the canvas or an FBO) being rendered to. Visuals use this
    coordinate system primarily for antialiasing calculations. It is also the
    coorinate system used by glFragCoord. In most cases,
    this will have the same scale as the document and canvas coordinate 
    systems because the active framebuffer is the
    back buffer of the canvas, and the canvas will have _logical_ and
    _physical_ pixels of the same size. However, the scale may be different
    in the case of high-resolution displays, or when rendering to an 
    off-screen framebuffer with different scaling or boundaries than the
    canvas.
  
  * **Render** - This coordinate system is the obligatory system for
    vertices returned by a vertex shader. It has coordinates (-1, -1) to
    (1, 1) across the current glViewport. In OpenGL terminology, this is
    called clip coordinates.
  
  Parameters
  ----------
  canvas : Canvas
      The canvas being drawn to.
  dpi : float
      The dot-per-inch resolution of the document coordinate system. By
      default this is set to the resolution of the canvas.
  
  Notes
  -----
  By default, TransformSystems are configured such that the document
  coordinate system matches the logical pixels of the canvas,
  
  Examples
  --------
  1. To convert local vertex coordinates to normalized device coordinates in
  the vertex shader, we first need a vertex shader that supports configurable
  transformations::
  
      vec4 a_position;
      void main() {
          gl_Position = $transform(a_position);
      }
  
  Next, we supply the complete chain of transforms when drawing the visual:
  
      def draw(tr_sys):
          tr = tr_sys.get_full_transform()
          self.program['transform'] = tr.shader_map()
          self.program['a_position'] = self.vertex_buffer
          self.program.draw('triangles')
  
  2. Draw a line whose width is given in mm. To start, we need normal vectors
  for each vertex, which tell us the direction the vertex should move in
  order to set the line width::
  
      vec4 a_position;
      vec4 a_normal;
      float u_line_width;
      float u_dpi;
      void main() {
          // map vertex position and normal vector to the document cs
          vec4 doc_pos = $visual_to_doc(a_position);
          vec4 doc_normal = $visual_to_doc(a_position + a_normal) - doc_pos;
  
          // Use DPI to convert mm line width to logical pixels
          float px_width = (u_line_width / 25.4) * dpi;
  
          // expand by line width
          doc_pos += normalize(doc_normal) * px_width;
  
          // finally, map the remainder of the way to normalized device
          // coordinates.
          gl_Position = $doc_to_render(a_position);
      }
  
  In this case, we need to access
  the transforms independently, so ``get_full_transform()`` is not useful
  here::
  
      def draw(tr_sys):
          # Send two parts of the full transform separately
          self.program['visual_to_doc'] = tr_sys.visual_to_doc.shader_map()
          doc_to_render = (tr_sys.framebuffer_transform *
                           tr_sys.document_transform)
          self.program['visual_to_doc'] = doc_to_render.shader_map()
  
          self.program['u_line_width'] = self.line_width
          self.program['u_dpi'] = tr_sys.dpi
          self.program['a_position'] = self.vertex_buffer
          self.program['a_normal'] = self.normal_buffer
          self.program.draw('triangles')
  
  3. Draw a triangle with antialiasing at the edge.
  
  4. Using inverse transforms in the fragment shader
class_docstr_tok: ["TransformSystem","encapsulates","information","about","the","coordinate","systems","needed","to","draw","a","Visual",".","Visual","rendering","operates","in","six","coordinate","systems",":","*","*","*","Visual","*","*","-","arbitrary","local","coordinate","frame","of","the","visual",".","Vertex","buffers","used","by","the","visual","are","usually","specified","in","this","coordinate","system",".","*","*","*","Scene","*","*","-","This","is","an","isometric","coordinate","system","used","mainly","for","lighting","calculations",".","*","*","*","Document","*","*","-","This","coordinate","system","has","units","of","_logical_","pixels",",","and","should","usually","represent","the","pixel","coordinates","of","the","canvas","being","drawn","to",".","Visuals","use","this","coordinate","system","to","make","measurements","for","font","size",",","line","width",",","and","in","general","anything","that","is","specified","in","physical","units","(","px",",","pt",",","mm",",","in",",","etc.",")",".","In","most","circumstances",",","this","is","exactly","the","same","as","the","canvas","coordinate","system",".","*","*","*","Canvas","*","*","-","This","coordinate","system","represents","the","logical","pixel","coordinates","of","the","canvas",".","It","has","its","origin","in","the","top-left","corner","of","the","canvas",",","and","is","typically","the","coordinate","system","that","mouse","and","touch","events","are","reported","in",".","Note","that",",","by","convention",",","_logical_","pixels","are","not","necessarily","the","same","size","as","the","_physical_","pixels","in","the","framebuffer","that","is","being","rendered","to",".","*","*","*","Framebuffer","*","*","-","The","buffer","coordinate","system","has","units","of","_physical_","pixels",",","and","should","usually","represent","the","coordinates","of","the","current","framebuffer","(","on","the","canvas","or","an","FBO",")","being","rendered","to",".","Visuals","use","this","coordinate","system","primarily","for","antialiasing","calculations",".","It","is","also","the","coorinate","system","used","by","glFragCoord",".","In","most","cases",",","this","will","have","the","same","scale","as","the","document","and","canvas","coordinate","systems","because","the","active","framebuffer","is","the","back","buffer","of","the","canvas",",","and","the","canvas","will","have","_logical_","and","_physical_","pixels","of","the","same","size",".","However",",","the","scale","may","be","different","in","the","case","of","high-resolution","displays",",","or","when","rendering","to","an","off-screen","framebuffer","with","different","scaling","or","boundaries","than","the","canvas",".","*","*","*","Render","*","*","-","This","coordinate","system","is","the","obligatory","system","for","vertices","returned","by","a","vertex","shader",".","It","has","coordinates","(","-1",",","-1",")","to","(","1",",","1",")","across","the","current","glViewport",".","In","OpenGL","terminology",",","this","is","called","clip","coordinates",".","Parameters","--","--","--","--","--","canvas",":","Canvas","The","canvas","being","drawn","to",".","dpi",":","float","The","dot-per-inch","resolution","of","the","document","coordinate","system",".","By","default","this","is","set","to","the","resolution","of","the","canvas",".","Notes","--","--","-","By","default",",","TransformSystems","are","configured","such","that","the","document","coordinate","system","matches","the","logical","pixels","of","the","canvas",",","Examples","--","--","--","--","1",".","To","convert","local","vertex","coordinates","to","normalized","device","coordinates","in","the","vertex","shader",",","we","first","need","a","vertex","shader","that","supports","configurable","transformations",":",":","vec4","a_position",";","void","main","(",")","{","gl_Position","=","$","transform","(","a_position",")",";","}","Next",",","we","supply","the","complete","chain","of","transforms","when","drawing","the","visual",":","def","draw","(","tr_sys",")",":","tr","=","tr_sys.get_full_transform","(",")","self.program","[","'transform","'","]","=","tr.shader_map","(",")","self.program","[","'a_position","'","]","=","self.vertex_buffer","self.program.draw","(","'triangles","'",")","2",".","Draw","a","line","whose","width","is","given","in","mm",".","To","start",",","we","need","normal","vectors","for","each","vertex",",","which","tell","us","the","direction","the","vertex","should","move","in","order","to","set","the","line","width",":",":","vec4","a_position",";","vec4","a_normal",";","float","u_line_width",";","float","u_dpi",";","void","main","(",")","{","\/\/","map","vertex","position","and","normal","vector","to","the","document","cs","vec4","doc_pos","=","$","visual_to_doc","(","a_position",")",";","vec4","doc_normal","=","$","visual_to_doc","(","a_position","+","a_normal",")","-","doc_pos",";","\/\/","Use","DPI","to","convert","mm","line","width","to","logical","pixels","float","px_width","=","(","u_line_width","\/","25.4",")","*","dpi",";","\/\/","expand","by","line","width","doc_pos","+=","normalize","(","doc_normal",")","*","px_width",";","\/\/","finally",",","map","the","remainder","of","the","way","to","normalized","device","\/\/","coordinates",".","gl_Position","=","$","doc_to_render","(","a_position",")",";","}","In","this","case",",","we","need","to","access","the","transforms","independently",",","so","``","get_full_transform","(",")","``","is","not","useful","here",":",":","def","draw","(","tr_sys",")",":","#","Send","two","parts","of","the","full","transform","separately","self.program","[","'visual_to_doc","'","]","=","tr_sys.visual_to_doc.shader_map","(",")","doc_to_render","=","(","tr_sys.framebuffer_transform","*","tr_sys.document_transform",")","self.program","[","'visual_to_doc","'","]","=","doc_to_render.shader_map","(",")","self.program","[","'u_line_width","'","]","=","self.line_width","self.program","[","'u_dpi","'","]","=","tr_sys.dpi","self.program","[","'a_position","'","]","=","self.vertex_buffer","self.program","[","'a_normal","'","]","=","self.normal_buffer","self.program.draw","(","'triangles","'",")","3",".","Draw","a","triangle","with","antialiasing","at","the","edge",".","4",".","Using","inverse","transforms","in","the","fragment","shader"]
code: def visual_transform(self, tr):
      self._visual_transform.transforms = tr
  
imports: from __future__ import division
  from .linear import STTransform, NullTransform
  from .chain import ChainTransform
  from ._util import TransformCache
  from ...util.event import EventEmitter
  import numpy
label_desc: Use image node_id 9 for calling the TransformSystem obj's underlying member method code with example usage: obj.visual_transform(tr) without return types