Home | History | Annotate | Download | only in script
      1 // draw.h
      2 
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 //
     15 // Copyright 2005-2010 Google, Inc.
     16 // Author: allauzen (at) google.com (Cyril Allauzen)
     17 //
     18 // \file
     19 // Class to draw a binary FST by producing a text file in dot format,
     20 // helper class to fstdraw.cc
     21 
     22 #ifndef FST_SCRIPT_DRAW_IMPL_H_
     23 #define FST_SCRIPT_DRAW_IMPL_H_
     24 
     25 #include <sstream>
     26 #include <string>
     27 
     28 #include <fst/script/fst-class.h>
     29 #include <fst/fst.h>
     30 #include <fst/util.h>
     31 
     32 namespace fst {
     33 
     34 // Print a binary Fst in the dot textual format, helper class for fstdraw.cc
     35 // WARNING: Stand-alone use not recommend.
     36 template <class A> class FstDrawer {
     37  public:
     38   typedef A Arc;
     39   typedef typename A::StateId StateId;
     40   typedef typename A::Label Label;
     41   typedef typename A::Weight Weight;
     42 
     43   FstDrawer(const Fst<A> &fst,
     44             const SymbolTable *isyms,
     45             const SymbolTable *osyms,
     46             const SymbolTable *ssyms,
     47             bool accep,
     48             string title,
     49             float width,
     50             float height,
     51             bool portrait,
     52             bool vertical,
     53             float ranksep,
     54             float nodesep,
     55             int fontsize,
     56             int precision,
     57             bool show_weight_one)
     58       : fst_(fst), isyms_(isyms), osyms_(osyms), ssyms_(ssyms),
     59         accep_(accep && fst.Properties(kAcceptor, true)), ostrm_(0),
     60         title_(title), width_(width), height_(height), portrait_(portrait),
     61         vertical_(vertical), ranksep_(ranksep), nodesep_(nodesep),
     62         fontsize_(fontsize), precision_(precision),
     63         show_weight_one_(show_weight_one) {}
     64 
     65   // Draw Fst to an output buffer (or stdout if buf = 0)
     66   void Draw(ostream *strm, const string &dest) {
     67     ostrm_ = strm;
     68     dest_ = dest;
     69     StateId start = fst_.Start();
     70     if (start == kNoStateId)
     71       return;
     72 
     73     PrintString("digraph FST {\n");
     74     if (vertical_)
     75       PrintString("rankdir = BT;\n");
     76     else
     77       PrintString("rankdir = LR;\n");
     78     PrintString("size = \"");
     79     Print(width_);
     80     PrintString(",");
     81     Print(height_);
     82     PrintString("\";\n");
     83     if (!dest_.empty())
     84       PrintString("label = \"" + title_ + "\";\n");
     85     PrintString("center = 1;\n");
     86     if (portrait_)
     87       PrintString("orientation = Portrait;\n");
     88     else
     89       PrintString("orientation = Landscape;\n");
     90     PrintString("ranksep = \"");
     91     Print(ranksep_);
     92     PrintString("\";\n");
     93     PrintString("nodesep = \"");
     94     Print(nodesep_);
     95     PrintString("\";\n");
     96     // initial state first
     97     DrawState(start);
     98     for (StateIterator< Fst<A> > siter(fst_);
     99          !siter.Done();
    100          siter.Next()) {
    101       StateId s = siter.Value();
    102       if (s != start)
    103         DrawState(s);
    104     }
    105     PrintString("}\n");
    106   }
    107 
    108  private:
    109   // Maximum line length in text file.
    110   static const int kLineLen = 8096;
    111 
    112   void PrintString(const string &s) const {
    113     *ostrm_ << s;
    114   }
    115 
    116   // Escapes backslash and double quote if these occur in the string. Dot will
    117   // not deal gracefully with these if they are not escaped.
    118   inline void EscapeChars(const string &s, string* ns) const {
    119     const char* c = s.c_str();
    120     while (*c) {
    121       if (*c == '\\' || *c == '"') ns->push_back('\\');
    122       ns->push_back(*c);
    123       ++c;
    124     }
    125   }
    126 
    127   void PrintId(int64 id, const SymbolTable *syms,
    128                const char *name) const {
    129     if (syms) {
    130       string symbol = syms->Find(id);
    131       if (symbol == "") {
    132         FSTERROR() << "FstDrawer: Integer " << id
    133                    << " is not mapped to any textual symbol"
    134                    << ", symbol table = " << syms->Name()
    135                    << ", destination = " << dest_;
    136         symbol = "?";
    137       }
    138       string nsymbol;
    139       EscapeChars(symbol, &nsymbol);
    140       PrintString(nsymbol);
    141     } else {
    142       string idstr;
    143       Int64ToStr(id, &idstr);
    144       PrintString(idstr);
    145     }
    146   }
    147 
    148   void PrintStateId(StateId s) const {
    149      PrintId(s, ssyms_, "state ID");
    150   }
    151 
    152   void PrintILabel(Label l) const {
    153      PrintId(l, isyms_, "arc input label");
    154   }
    155 
    156   void PrintOLabel(Label l) const {
    157      PrintId(l, osyms_, "arc output label");
    158   }
    159 
    160   template <class T>
    161   void Print(T t) const {
    162     *ostrm_ << t;
    163   }
    164 
    165   void DrawState(StateId s) const {
    166     Print(s);
    167     PrintString(" [label = \"");
    168     PrintStateId(s);
    169     Weight final = fst_.Final(s);
    170     if (final != Weight::Zero()) {
    171       if (show_weight_one_ || (final != Weight::One())) {
    172         PrintString("/");
    173         Print(final);
    174       }
    175       PrintString("\", shape = doublecircle,");
    176     } else {
    177       PrintString("\", shape = circle,");
    178     }
    179     if (s == fst_.Start())
    180       PrintString(" style = bold,");
    181     else
    182       PrintString(" style = solid,");
    183     PrintString(" fontsize = ");
    184     Print(fontsize_);
    185     PrintString("]\n");
    186     for (ArcIterator< Fst<A> > aiter(fst_, s);
    187          !aiter.Done();
    188          aiter.Next()) {
    189       Arc arc = aiter.Value();
    190       PrintString("\t");
    191       Print(s);
    192       PrintString(" -> ");
    193       Print(arc.nextstate);
    194       PrintString(" [label = \"");
    195       PrintILabel(arc.ilabel);
    196       if (!accep_) {
    197         PrintString(":");
    198         PrintOLabel(arc.olabel);
    199       }
    200       if (show_weight_one_ || (arc.weight != Weight::One())) {
    201         PrintString("/");
    202         Print(arc.weight);
    203       }
    204       PrintString("\", fontsize = ");
    205       Print(fontsize_);
    206       PrintString("];\n");
    207     }
    208   }
    209 
    210   const Fst<A> &fst_;
    211   const SymbolTable *isyms_;     // ilabel symbol table
    212   const SymbolTable *osyms_;     // olabel symbol table
    213   const SymbolTable *ssyms_;     // slabel symbol table
    214   bool accep_;                   // print as acceptor when possible
    215   ostream *ostrm_;               // drawn FST destination
    216   string dest_;                  // drawn FST destination name
    217 
    218   string title_;
    219   float width_;
    220   float height_;
    221   bool portrait_;
    222   bool vertical_;
    223   float ranksep_;
    224   float nodesep_;
    225   int fontsize_;
    226   int precision_;
    227   bool show_weight_one_;
    228 
    229   DISALLOW_COPY_AND_ASSIGN(FstDrawer);
    230 };
    231 
    232 }  // namespace fst
    233 
    234 #endif  // FST_SCRIPT_DRAW_IMPL_H_
    235