docstr: As the Python virtual machine executes lines of code, generate a
  visualization for tensor-related expressions using from numpy, pytorch,
  and tensorflow. The shape of tensors referenced by the code are displayed.
  
  Visualizations pop up in a separate window unless running from a notebook,
  in which case the visualization appears as part of the cell execution output.
  
  There is heavy runtime overhead associated with explain() as every line
  is executed twice: once by explain() and then another time by the interpreter
  as part of normal execution.
  
  Expressions with side effects can easily generate incorrect results. Due to
  this and the overhead, you should limit the use of this to code you're trying
  to debug.  Assignments are not evaluated by explain so code `x = ...` causes
  an assignment to x just once, during normal execution. This explainer
  knows the value of x and will display it but does not assign to it.
  
  Upon exception, execution will stop as usual but, like clarify(), explain()
  will augment the exception to indicate the offending sub expression. Further,
  the visualization will deemphasize code not associated with the offending
  sub expression. The sizes of relevant tensor values are still visualized.
  
  Example:
  
  import numpy as np
  import tsensor
  
  b = np.array([9, 10]).reshape(2, 1)
  with tsensor.explain():
      b + b # tensor code or call to a function with tensor code
  
  See examples.ipynb for more examples.
  
  :param fontname: The name of the font used to display Python code
  :param fontsize: The font size used to display Python code; default is 13.
                   Also use this to increase the size of the generated figure;
                   larger font size means larger image.
  :param dimfontname:  The name of the font used to display the dimensions on the matrix and vector boxes
  :param dimfontsize: The  size of the font used to display the dimensions on the matrix and vector boxes
  :param char_sep_scale: It is notoriously difficult to discover how wide and tall
                         text is when plotted in matplotlib. In fact there's probably,
                         no hope to discover this information accurately in all cases.
                         Certainly, I gave up after spending huge effort. We have a
                         situation here where the font should be constant width, so
                         we can just use a simple scaler times the font size  to get
                         a reasonable approximation to the width and height of a
                         character box; the default of 1.8 seems to work reasonably
                         well for a wide range of fonts, but you might have to tweak it
                         when you change the font size.
  :param fontcolor:  The color of the Python code.
  :param underline_color:  The color of the lines that underscore tensor subexpressions; default is grey
  :param ignored_color: The de-highlighted color for deemphasizing code not involved in an erroneous sub expression
  :param error_op_color: The color to use for characters associated with the erroneous operator
  :param ax: If not none, this is the matplotlib drawing region in which to draw the visualization
  :param dpi: This library tries to generate SVG files, which are vector graphics not
              2D arrays of pixels like PNG files. However, it needs to know how to
              compute the exact figure size to remove padding around the visualization.
              Matplotlib uses inches for its figure size and so we must convert
              from pixels or data units to inches, which means we have to know what the
              dots per inch, dpi, is for the image.
  :param hush_errors: Normally, error messages from true syntax errors but also
                      unhandled code caught by my parser are ignored. Turn this off
                      to see what the error messages are coming from my parser.
  :param savefig: A string indicating where to save the visualization; don't save
                  a file if None.
  :param dtype_colors: map from dtype w/o precision like 'int' to color
  :param dtype_precisions: list of bit precisions to colorize, such as [32,64,128]
  :param dtype_alpha_range: all tensors of the same type are drawn to the same color,
                            and the alpha channel is used to show precision; the
                            smaller the bit size, the lower the alpha channel. You
                            can play with the range to get better visual dynamic range
                            depending on how many precisions you want to display.
docstr_tok: ["As","the","Python","virtual","machine","executes","lines","of","code",",","generate","a","visualization","for","tensor-related","expressions","using","from","numpy",",","pytorch",",","and","tensorflow",".","The","shape","of","tensors","referenced","by","the","code","are","displayed",".","Visualizations","pop","up","in","a","separate","window","unless","running","from","a","notebook",",","in","which","case","the","visualization","appears","as","part","of","the","cell","execution","output",".","There","is","heavy","runtime","overhead","associated","with","explain","(",")","as","every","line","is","executed","twice",":","once","by","explain","(",")","and","then","another","time","by","the","interpreter","as","part","of","normal","execution",".","Expressions","with","side","effects","can","easily","generate","incorrect","results",".","Due","to","this","and","the","overhead",",","you","should","limit","the","use","of","this","to","code","you","'re","trying","to","debug",".","Assignments","are","not","evaluated","by","explain","so","code","`","x","=","...","`","causes","an","assignment","to","x","just","once",",","during","normal","execution",".","This","explainer","knows","the","value","of","x","and","will","display","it","but","does","not","assign","to","it",".","Upon","exception",",","execution","will","stop","as","usual","but",",","like","clarify","(",")",",","explain","(",")","will","augment","the","exception","to","indicate","the","offending","sub","expression",".","Further",",","the","visualization","will","deemphasize","code","not","associated","with","the","offending","sub","expression",".","The","sizes","of","relevant","tensor","values","are","still","visualized",".","Example",":","import","numpy","as","np","import","tsensor","b","=","np.array","(","[","9",",","10","]",")",".reshape","(","2",",","1",")","with","tsensor.explain","(",")",":","b","+","b","#","tensor","code","or","call","to","a","function","with","tensor","code","See","examples.ipynb","for","more","examples",".",":","param","fontname",":","The","name","of","the","font","used","to","display","Python","code",":","param","fontsize",":","The","font","size","used","to","display","Python","code",";","default","is","13",".","Also","use","this","to","increase","the","size","of","the","generated","figure",";","larger","font","size","means","larger","image",".",":","param","dimfontname",":","The","name","of","the","font","used","to","display","the","dimensions","on","the","matrix","and","vector","boxes",":","param","dimfontsize",":","The","size","of","the","font","used","to","display","the","dimensions","on","the","matrix","and","vector","boxes",":","param","char_sep_scale",":","It","is","notoriously","difficult","to","discover","how","wide","and","tall","text","is","when","plotted","in","matplotlib",".","In","fact","there","'s","probably",",","no","hope","to","discover","this","information","accurately","in","all","cases",".","Certainly",",","I","gave","up","after","spending","huge","effort",".","We","have","a","situation","here","where","the","font","should","be","constant","width",",","so","we","can","just","use","a","simple","scaler","times","the","font","size","to","get","a","reasonable","approximation","to","the","width","and","height","of","a","character","box",";","the","default","of","1.8","seems","to","work","reasonably","well","for","a","wide","range","of","fonts",",","but","you","might","have","to","tweak","it","when","you","change","the","font","size",".",":","param","fontcolor",":","The","color","of","the","Python","code",".",":","param","underline_color",":","The","color","of","the","lines","that","underscore","tensor","subexpressions",";","default","is","grey",":","param","ignored_color",":","The","de-highlighted","color","for","deemphasizing","code","not","involved","in","an","erroneous","sub","expression",":","param","error_op_color",":","The","color","to","use","for","characters","associated","with","the","erroneous","operator",":","param","ax",":","If","not","none",",","this","is","the","matplotlib","drawing","region","in","which","to","draw","the","visualization",":","param","dpi",":","This","library","tries","to","generate","SVG","files",",","which","are","vector","graphics","not","2D","arrays","of","pixels","like","PNG","files",".","However",",","it","needs","to","know","how","to","compute","the","exact","figure","size","to","remove","padding","around","the","visualization",".","Matplotlib","uses","inches","for","its","figure","size","and","so","we","must","convert","from","pixels","or","data","units","to","inches",",","which","means","we","have","to","know","what","the","dots","per","inch",",","dpi",",","is","for","the","image",".",":","param","hush_errors",":","Normally",",","error","messages","from","true","syntax","errors","but","also","unhandled","code","caught","by","my","parser","are","ignored",".","Turn","this","off","to","see","what","the","error","messages","are","coming","from","my","parser",".",":","param","savefig",":","A","string","indicating","where","to","save","the","visualization",";","do","n't","save","a","file","if","None",".",":","param","dtype_colors",":","map","from","dtype","w\/o","precision","like","'int","'","to","color",":","param","dtype_precisions",":","list","of","bit","precisions","to","colorize",",","such","as","[","32,64,128","]",":","param","dtype_alpha_range",":","all","tensors","of","the","same","type","are","drawn","to","the","same","color",",","and","the","alpha","channel","is","used","to","show","precision",";","the","smaller","the","bit","size",",","the","lower","the","alpha","channel",".","You","can","play","with","the","range","to","get","better","visual","dynamic","range","depending","on","how","many","precisions","you","want","to","display","."]
code: def __init__(
      self,
      fontname=("Consolas", "DejaVu Sans Mono"),
      fontsize=13,
      dimfontname="Arial",
      dimfontsize=9,
      char_sep_scale=1.8,
      fontcolor="#444443",
      underline_color="#C2C2C2",
      ignored_color="#B4B4B4",
      error_op_color="#A40227",
      savefig=None,
      hush_errors=True,
      dtype_colors=None,
      dtype_precisions=None,
      dtype_alpha_range=None,
  ):
      """
      As the Python virtual machine executes lines of code, generate a
      visualization for tensor-related expressions using from numpy, pytorch,
      and tensorflow. The shape of tensors referenced by the code are displayed.
  
      Visualizations pop up in a separate window unless running from a notebook,
      in which case the visualization appears as part of the cell execution output.
  
      There is heavy runtime overhead associated with explain() as every line
      is executed twice: once by explain() and then another time by the interpreter
      as part of normal execution.
  
      Expressions with side effects can easily generate incorrect results. Due to
      this and the overhead, you should limit the use of this to code you're trying
      to debug.  Assignments are not evaluated by explain so code `x = ...` causes
      an assignment to x just once, during normal execution. This explainer
      knows the value of x and will display it but does not assign to it.
  
      Upon exception, execution will stop as usual but, like clarify(), explain()
      will augment the exception to indicate the offending sub expression. Further,
      the visualization will deemphasize code not associated with the offending
      sub expression. The sizes of relevant tensor values are still visualized.
  
      Example:
  
      import numpy as np
      import tsensor
  
      b = np.array([9, 10]).reshape(2, 1)
      with tsensor.explain():
          b + b # tensor code or call to a function with tensor code
  
      See examples.ipynb for more examples.
  
      :param fontname: The name of the font used to display Python code
      :param fontsize: The font size used to display Python code; default is 13.
                       Also use this to increase the size of the generated figure;
                       larger font size means larger image.
      :param dimfontname:  The name of the font used to display the dimensions on the matrix and vector boxes
      :param dimfontsize: The  size of the font used to display the dimensions on the matrix and vector boxes
      :param char_sep_scale: It is notoriously difficult to discover how wide and tall
                             text is when plotted in matplotlib. In fact there's probably,
                             no hope to discover this information accurately in all cases.
                             Certainly, I gave up after spending huge effort. We have a
                             situation here where the font should be constant width, so
                             we can just use a simple scaler times the font size  to get
                             a reasonable approximation to the width and height of a
                             character box; the default of 1.8 seems to work reasonably
                             well for a wide range of fonts, but you might have to tweak it
                             when you change the font size.
      :param fontcolor:  The color of the Python code.
      :param underline_color:  The color of the lines that underscore tensor subexpressions; default is grey
      :param ignored_color: The de-highlighted color for deemphasizing code not involved in an erroneous sub expression
      :param error_op_color: The color to use for characters associated with the erroneous operator
      :param ax: If not none, this is the matplotlib drawing region in which to draw the visualization
      :param dpi: This library tries to generate SVG files, which are vector graphics not
                  2D arrays of pixels like PNG files. However, it needs to know how to
                  compute the exact figure size to remove padding around the visualization.
                  Matplotlib uses inches for its figure size and so we must convert
                  from pixels or data units to inches, which means we have to know what the
                  dots per inch, dpi, is for the image.
      :param hush_errors: Normally, error messages from true syntax errors but also
                          unhandled code caught by my parser are ignored. Turn this off
                          to see what the error messages are coming from my parser.
      :param savefig: A string indicating where to save the visualization; don't save
                      a file if None.
      :param dtype_colors: map from dtype w/o precision like 'int' to color
      :param dtype_precisions: list of bit precisions to colorize, such as [32,64,128]
      :param dtype_alpha_range: all tensors of the same type are drawn to the same color,
                                and the alpha channel is used to show precision; the
                                smaller the bit size, the lower the alpha channel. You
                                can play with the range to get better visual dynamic range
                                depending on how many precisions you want to display.
      """
      (
          self.savefig,
          self.fontname,
          self.fontsize,
          self.dimfontname,
          self.dimfontsize,
          self.char_sep_scale,
          self.fontcolor,
          self.underline_color,
          self.ignored_color,
          self.error_op_color,
          self.hush_errors,
          self.dtype_colors,
          self.dtype_precisions,
          self.dtype_alpha_range,
      ) = (
          savefig,
          fontname,
          fontsize,
          dimfontname,
          dimfontsize,
          char_sep_scale,
          fontcolor,
          underline_color,
          ignored_color,
          error_op_color,
          hush_errors,
          dtype_colors,
          dtype_precisions,
          dtype_alpha_range,
      )
  
imports: import os
  import sys
  import traceback
  import inspect
  import hashlib
  from pathlib import Path
  import matplotlib.pyplot
  import tsensor
label_desc: Use image node_id 1 to create a new explain object  with example: obj = explain(fontname, fontsize, dimfontname, dimfontsize, char_sep_scale, fontcolor, underline_color, ignored_color, error_op_color, savefig, hush_errors, dtype_colors, dtype_precisions, dtype_alpha_range)