### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
##                    308-522 -- Modelling and Simulation
##                                  Fall 2002
##                             --- ASSIGNMENT 1 ---
##
## EXPORT_LaTeX.py
##
## last modified: 09/26/02
### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###

import Traversal  # Traversal of the model
import tkFileDialog  # For browser dialog

## MODIFIED: the function in the original code is completely rewritten:
def exportLaTeX(parentApp, model):

  # List of all blocks:
  blocks = model.listNodes["Block"]
  # Mark all blocks as unvisited:
  for b in blocks:
    b.visited = 0

  # List of all integrator blocks:
  intBlocks = filter( lambda x : x.block_type.getValue()[1] == 6, blocks )
  if len(intBlocks) == 0:
    raise NotImplementedError, "model is not an ODE"

  # "outStr" is used to store the representation of the ordinary differential
  # equations themselves. "tmpStr" is used to store the algebraic equations.
  outStr = ""
  tmpStr = ""

  # Loop over all Integrator blocks:
  for iBlock in intBlocks:
#    iBlock.visited = 1  # Mark the block as visited
    # Get integrator's IC port and input port:
    icPort = iBlock.block_IC_port[0]
    inPort = filter( lambda x : x != icPort, iBlock.in_connections_)[0]
    var = iBlock.block_name.getValue()  # integrator's name
    if var == "":
      raise SyntaxError, "missing integrator name"
    # LEFT-HAND SIDE OF THE ODE:
    outStr += "      \\dot{" + var + "} = "
    # RIGHT-HAND SIDE OF THE ODE
    outStr += Traversal.traverse(inPort, 0)
    # INITIAL CONDITION
    outStr += ", & " + var + "(t_0) = " + Traversal.traverse(icPort, 0)

    outStr += "\\\\\n"

    # For those blocks with a name that were met in the above traversals, the
    # names were used to construct the string. Those blocks have been stored
    # in "Traversal.blockList".
    while len( Traversal.blockList ) > 0:

      gBlock = Traversal.blockList[0]  # block to be processed

      # Don't process a block that has already been processed!
      if gBlock.visited != 1:
        gBlock.visited = 1  # Mark the block as visited
        strList = []
        # Loop over nodes connecting to the block:
        for node in gBlock.in_connections_:
          strList.append( Traversal.traverse(node, 0) )

        # Append algebraic equation to main string:
        tmpStr += "      " + gBlock.block_name.getValue() + " = " +           \
              Traversal.stringRepres( gBlock, strList, 0 )  + "\\\\\n"

      Traversal.blockList = Traversal.blockList[1:]


  # Get a filename:
  filename = tkFileDialog.asksaveasfilename()
  if not filename:
    return

  # Make sure the name is valid:
  assert (filename[-4:] == ".tex"), "invalid name"


  # Build whole string:
  outStr = "\\documentclass[12pt]{article}\n" +                               \
           "\\begin{document}\n\n" +                                          \
           "\\[\n" +                                                          \
           "  \\left\\{\n" +                                                  \
           "    \\begin{array}{ll}\n" + outStr
  outStr += "      \\\\\n" + tmpStr
  outStr += "    \\end{array}\n" +                                            \
            "  \\right.\n" +                                                  \
            "\\]\n\n" +                                                       \
            "\\end{document}\n"

  #  Print "outStr" in file:
  fd = open(filename, 'w')
  fd.write(outStr)
  fd.close()


