def down_click(self, part, event=None):
        """ Process down click over highlighted part
        All highlighted parts elicit a call
        :part: highlighted part
        :event: event if available
        :Returns: True if processing is complete
        if self.down_click_call is not None:
            return self.down_click_call(part, event=event)
        """ Self processing
        if part.is_edge() and not part.is_turned_on():
            SlTrace.lg("turning on %s" % part, "turning_on")
            regions = part.get_adjacents()  # Look if we completed any squares
            for square in regions:
                if square.is_complete():
                    self.complete_square(part, square)

            return True  # Indicate processing is done

        return False
Example #2
 def set_play_level(self, play_level=None):
     """ Set players' level via
     comma separated string
     :play_level: comma separated string of playing player's Labels
     players = self.get_players(all=True)
     play_levels = [x.strip() for x in play_level.split(',')]
     def_level = "2"
     if len(play_levels) == 0:
         SlTrace.lg("Setting to default level: {}".format(def_level)) 
         play_levels = def_level  # Default
     player_idx = -1
     for player in players:
         player_idx += 1
         if player_idx < len(play_levels):
             player_level = play_levels[player_idx]
             player_level = play_levels[-1]  # Use last level
         plevel = int(player_level)
         playing_var = player.ctls_vars["level"]
         player.level = plevel
         SlTrace.lg("Setting {} play level to {:d}".format(player, plevel))
Example #3
    def __init__(self, *args, title=None, control_prefix=None,
                  image_hash=None, select_list_hash=None, **kwargs):
        """ Control players
        self.max_color_len = len("#80ffff")  # For fields which have to contain hex color representation

        if image_hash is None:
            image_hash = ImageHash()    # Create our own
        self.image_hash = image_hash
        if select_list_hash is None:
            select_list_hash = ImageHash()
        self.select_list_hash = select_list_hash
                                        # Protect against early checking
        self.players = {}  # Dictionary of SelectPlayer
        self.playing = []  # Playing, in playing order
        self.cur_pindex = None  # Current player index in self.playing list
        self.controls_frame = None  # Set as no controls
        self.is_players_displayed = False  # Set when displayed
        self.players_frame = None  # Set when initialized
        self.player_field_by_widget = {}    
        if title is None:
            title = "Player Control"
        if control_prefix is None:
            control_prefix = PlayerControl.CONTROL_NAME_PREFIX
                      title=title, control_prefix=control_prefix,
        SlTrace.set_mw(  # Setup for reporting    
        super().control_display()  # Do base work
        self.player_props = PlayerProps(self)        
        self.control_display_base()"WM_DELETE_WINDOW", self.delete_window)
        self.selected_widget = None  # Last applicable field clicked ("<Button-1>", self.button_click) ("<Double-Button-1>", self.double_click)
        self.player_changed = True                  # Tested regularly by game play
        self.score_changed = True                   # Tested regularly by game play
Example #4
    def get_component_val(self, name, comp_name=None, default=None):
        """ Get component value of named control
        If widget is present, get from widget
        else if control is present, get from control
        else if properties is present, get from properties
        :name: - control name
        :comp_name: if present, append with "_" comp_name
        :default: - use if value not found - MANDATORY
                    data type is used if control entry data type is unknown
        if default is None:
            raise SelectError(
                "get_component_val: %s_%s mandatory default parameter missing"
                % (name, comp_name))

        name_comp = name
        if comp_name is not None:
            name_comp += "_" + comp_name
        comp_entry = self.get_ctl_entry(name_comp)
        if comp_entry is None:
            raise SelectError(
                "get_component_value(%s, %s - component NOT FOUD" %
                (name, comp_name))

        if comp_entry is not None:
            if comp_entry.value_type is None:
                comp_entry.value_type = type(default)
            ctl_widget = comp_entry.ctl_widget
            if ctl_widget is not None:
                widget_val = comp_entry.get_input()
                if widget_val is not None:
                    vt = comp_entry.value_type
                    if vt == int:
                        if widget_val == "":
                            widget_val = "0"  # Treat undefined as 0
                        value = int(widget_val)
                    elif vt == float:
                        if widget_val == "":
                            widget_val = "0"  # Treat undefined as 0
                        value = float(widget_val)
                    elif vt == str:
                        value = widget_val
                        value = widget_val  # No change - should we check?
                            "get_component_val: %s ??? value_type(%s) widget_val=%s type(%s)"
                            % (name_comp, vt, widget_val, type(widget_val)))
                        SlTrace.lg("  type(int)=%s comp_entry.value_type=%s" %
                                   (type(int), comp_entry.value_type))
                    return value
                        "get_component_val: %s None return from comp_entry.get_input"
                        % comp_name)
            return comp_entry.value

        return default  # No component entry - return default
Example #5
    def procCmdString(cls, string=None, prefix=None):
        """ Process python code string, with prefix text
        :string: input string
        :prefix: optional string to prefix code string for compile
        :Returns: resulting cls 
        cls.result = False  # Set True if OK
        if string is None:
            string = cls.puzzle_string
        if string is None:
            raise SelectError("string is missing")

        gbls = {
            'version': cls.version,
            'puzzle': cls.puzzle,
            'row': cls.row,
            'end_puzzle': cls.end_puzzle

        compile_str = ""
        if prefix is not None:
            compile_str = prefix
            if not prefix.endswith("\n"):
                compile_str += "\n"  # Insure ending newline
        if SlTrace.trace("puzzle_load"):
            compile_str += test_prefix
        compile_str += string
        compile_str += "\nend_puzzle()\n"  # End puzzle
            exec(compile_str, gbls)
            cls.result = True
            return cls.sudoku_puzzle

        except Exception as e:
            _, _, tb = sys.exc_info()
            tbs = traceback.extract_tb(tb)
                f"Error while executing text from {cls.file_name}\n    {str(e)}"
            inner_cmds = False
            for tbfr in tbs:  # skip bottom (in
                tbfmt = 'File "%s", line %d, in %s' % (tbfr.filename,
                if not inner_cmds and tbfr.filename.endswith(
                    inner_cmds = True
                    SlTrace.lg("    --------------------"
                               )  # show bottom (in
                SlTrace.lg("    %s\n       %s" % (tbfmt, tbfr.line))
            cls.result = False

        raise SelectError("compile error")
 def test_is_covering_but_once():
     good1 = ['g7', 'g8', 'h8', 'h7']
     dgood1 = DisplayedPath(path=good1, disp_board=dboard)
     ctv = ChessTourValidation(locs=good1)
     if ctv.is_covering_but_once(dgood1):
         SlTrace.lg(f"expected: pass of {good1}")
         SlTrace.lg(f"UNEXPECTED FAIL of {good1}")
Example #7
 def remove_props(self):
     """ Remove all properties for 
     base_key = self.get_base_key(include_num=False)
     SlTrace.lg(f"remove_props: base_key={base_key}", "player_prop")
     if self.sect_name is None:
         base_pat = base_key + r'\d+'
         base_match = re.compile(base_pat)
         SlTrace.lg(f"base_pat={base_pat}", "player_prop")
     prop_keys = SlTrace.getPropKeys()
     for prop_key in prop_keys:
         if prop_key.startswith(base_key):
             if self.sect_name is None:
                 m = base_match.match(prop_key)
                 if m is None:
                     continue            # Not base: ...nnn
             SlTrace.lg(f"remove_props: key={prop_key}", "player_prop")
Example #8
    def is_square_complete(self, part, squares=None, ifadd=False):
        """ Determine if this edge completes one or more square(s) region(s)
        :part: - possibly completing edge
        :squares: - any squares completed are appended to this list
                default: no regions are appended
        :ifadd: If part is added
                default: part must already be added
        if part.is_edge():
            SlTrace.lg("complete square testing %s" % part, "square_completion")
            regions = part.get_adjacents()      # Look if we completed any square
            ncomp = 0
            for square in regions:
                if (ifadd and square.is_complete(added=part)
                    ncomp += 1
                    if squares is not None:
            if ncomp > 0:
                return True

        return False
Example #9
 def __init__(self,
              road_length=.05 * 2,
     """ Setup object
     :road_width: road width as a fraction of track's width dimensions'
             e.g. 1,1 with container==None ==> block is whole canvas
     :road_length: road width as a fraction of track's width dimensions'
             e.g. 1,1 with container==None ==> block is whole canvas
     :surface: road surface type - determines look and operation/handeling                                                    collisions)
     SlTrace.lg("RoadTrack: %s" % (self))
     if self.container is None:
         canvas = self.get_canvas()
         if canvas is None:
             self.canvas = Canvas(width=self.cv_width,
     self.roads = []  # List of components    # Parts of track
     self.road_width = road_width
     self.road_length = road_length
     self.surface = surface
     self.background = "lightgreen"
Example #10
def filelist_proc(filename):
    """ Process file containing list of puzzle files
    :filename: filename of file containing list of puzzle files
            Default directory for files in list is dir(filename)
    with open(filename) as f:
        file_list_files[filename] = 1   # Record as being used
        lines = f.readlines()
        filedir = os.path.dirname(filename)
    for i in range(len(lines)):
        line = lines[i]
        ml = re.match(r'^(\.*)#.*$', line)
        if ml:
            line = ml[1]    # Before comment
        line = line.strip()
        if re.match(r'^\s*$', line):
            continue                # Skip blank lines
        name = line
        if not os.path.isabs(name):
            name = os.path.join(filedir, name)
        if name in file_list_files:
            SlTrace.lg(f"file: {file} already used - avoiding recursive use ")
        file_proc(filename=name, run_after_load=True)
Example #11
 def get_component_next_val(self, name,
     """ Next value for this component
     :name: control name
     :nrange: - number of samples for incremental
     :default_value: default value
     cur_value = self.get_current_val(name, 1)
     next_direction = self.get_component_val(name, "next", "same")
     if SlTrace.trace("get_next_val"):
         SlTrace.lg("get_next_val %s cur_val=%s next=%s"
                    % (name, cur_value, next_direction))
     if isinstance(cur_value, str):
         next_value = self.ctl_list_value(name)
         SlTrace.lg("get_value %s str next=%s val=%s"
                     % (name, next_direction, next_value), "get_next_val")
         return next_value
         min_value = float(self.get_component_val(name, "min", cur_value))
         max_value = float(self.get_component_val(name, "max", cur_value))
         inc_value = (max_value-min_value)/nrange            
         if next_direction == "ascend":
             new_value = cur_value + inc_dir * inc_value
         elif next == "descend":
             new_value = cur_value - inc_dir * inc_value
         elif next_direction == "random":
             new_value = random.randint(min_value, max_value)
             new_value = cur_value + inc_value
         if new_value < min_value or new_value > max_value:
             new_value = self.step_end(name, new_value)
         self.set_current_val(name, new_value)
Example #12
    def __init__(self, car_bin):
        """ Setup car bin
        :car_bin: car bin instance
        self.car_bin = car_bin

        SlTrace.lg("CarBinSetup: car_bin pts: %s" %

        car_rot = 0  # HACK
        nentries = 4  # Number of entries (space)
        entry_space = .08  # between entries
        entry_width = 5 * (1. - nentries * entry_space) / nentries
        entry_height = .25 * (1. - 2 * entry_space)  # height of entry
        pos_inc = Pt(0., 1.2 * entry_height)  # to next entry
        pos = Pt(entry_space,
                 entry_space)  # HACK - Add extra  to move to right

        entry = CarSimple(self.car_bin,
        SlTrace.lg("entry pts: %s" % entry.get_absolute_points())

        pos += pos_inc
        entry = CarSimple(self.car_bin,
        SlTrace.lg("entry pts: %s" % entry.get_absolute_points())

        pos += pos_inc
        entry = CarSimple(self.car_bin,
        SlTrace.lg("entry pts: %s" % entry.get_absolute_points())
Example #13
    def get_selected(cls, block=None):
        """ Get selected info, block if selected, else None
        :block:  block to check.
        if block is None:
            raise SelectError("get_selected: with block is None")

        selected = None
        for sid in cls.selects:
            selected = cls.selects[sid]
            if == sid:

        if selected.block is None:
            raise SelectError("selected with None for block")

        if selected.x_coord is None:
            SlTrace.lg("selected with None for x_coord")
            cv_width = cls.get_cv_width()
            cv_height = cls.get_cv_height()
            selected = SelectInfo(block=None,
                                  x_coord=cv_width / 2,
                                  y_coord=cv_height / 2)  # HACK
        return selected
Example #14
 def player_info(self, base_prefix, snapshot=None):
     """ Return current player info, based on properties
     :startswith: each key starts with this
     :returns: snapshot with current state but as if n the stack
     if snapshot is None:
         snapshot = SlTrace.snapshot_properties()
     if not base_prefix.endswith("."):
         base_prefix += "."
     sn = snapshot.snapshot_properties(sn=snapshot,
                                       req_match=re.escape(base_prefix) +
     pp = PlayerProp(self.player_control)
     player_info = pp.get_player_infos(snapshot=sn)
     return player_info[0]
Example #15
    def next_path(self):
        """ Get next path
        1. if necessary, build path to nrow*ncol depth
        2. get list of moves from stack
        :returns: next path, None if none
            if not self.build_path_stack():
                return None

            path = self.path_stack_path()
            return path

        except SelectTimeout:
            t = self.time_limit
            if t is None:
                t = -1
            SlTrace.lg(f"path find timeout({t:.3f} sec)")
            return None

        except BaseException:
            SlTrace.lg("path find exception: {traceback.format_exc()}")
            raise Exception
Example #16
 def test_attr(name):
     """ Test/exercise attribute
     :name: attribute name
     global nrun
     nrun += 1
     SlTrace.lg(f"\n{nrun:3} Testing Attribute: {name}")
     attr = atc.get_attr(name)
     SlTrace.lg(f"  {attr.get_name()}:"
                f"  changes: {attr.get_changes()}"
                f"  index: {attr.get_index()}")
     atc.add_value(name=name, value=f"{name}_test_value_{nrun}")
     values = attr.get_values()
     SlTrace.lg(f"values: {values}")
     for n in range(len(values) * 3):
         SlTrace.lg(f"  {n}: {atc.get_next(name)}"
                    f"  index: {attr.get_index()}")
Example #17
 def next_color(self, colr=None, changing=None):
     """ Get next color based on color_current, color_changing
     :colr: color
             default: use self.color_current
     :changing: is color changing
             default: use self.color_changing
     if colr is None:
         colr = self.color_current
     self.color_current = colr
     if changing is None:
         changing = self.color_changing
     self.color_changing = changing
     if self.color_current == 'w':
         if self.color_changing:
             self.color_index += 1
         if self.color_index >= len(self.colors):
             self.color_index = 0  # wrap around
         new_color = self.colors[self.color_index]
     elif self.color_current == '2':
         if changing:
             self.color_index += 1
         if self.color_index >= len(self.custom_colors):
             self.color_index = 0
         new_color = self.custom_colors[self.color_index]
         new_color = self.color_current
         if type(new_color) != str:
   "new_color:{new_color} not str")
         f" color_current:{self.color_current}"
         f" color_index:{self.color_index}"
         f" color_changing:{self.color_changing}", "color")
     return new_color
Example #18
    def cmd_images(self, keysym):
        """ Create image markers
        replacing previous marker, if one
            j - choose from current group
            k - rotate through animals
            l - rotate through family
            [ (bracketleft) - rotate through princesses
            ] (bracketright)- rotate other
        :keysym: image type
        char2group = {
            'k': "animals",
            'l': "family",
            'bracketleft': "princesses",
            'bracketright': "other_stuff",
        if keysym in char2group:
            group = char2group[keysym]
  "image command {keysym} is not available yet")
            return False

        return self.cmd_do_image(group=group)
Example #19
    def get_part(self, id=None, type=None, sub_type=None, row=None, col=None):
        """ Get basic part
        :id: unique part id
        :type: part type e.g., edge, region, corner default: "edge"
        :sub_type: must match if present e.g. v for vertical, h for horizontal
        :row:  part row
        :col: part column
        :returns: part, None if not found
        if id is not None:
            if id not in self.parts_by_id:
                SlTrace.lg("part not in parts_by_id")
                return None

            part = self.parts_by_id[id]
            return part

        if type is None:
            type = "edge"
        for part in
            if part.part_type == type and (sub_type is None
                                           or part.sub_type() == sub_type):
                if part.row == row and part.col == col:
                    return part
Example #20
 def select_set(self, parts, keep=False):
     """ Select part(s)
     :parts: part/id or list
     :keep: keep previously selected default: False
     parts = copy.copy(parts)
     if not keep:
     if not isinstance(parts, list):
         parts = [parts]
     for part in parts:
         part_id = part.part_id
         self.selects[part_id] = part
     if SlTrace.trace("selected"):
         self.list_selected("select_set AFTER")
Example #21
    def display(self, msg=None):
        display_str = ""
        if msg is None:
            msg = "Data Display"
        display_str += f"{msg}\n"
        if self.vals is None:
            raise SelectError("data gone")

        horiz_grp_divider = " " + "-" * (2 * self.nCol + self.nSubCol -
                                         1) + "\n"
        for nr in range(1, self.nRow + 1):
            if nr % self.nSubRow == 1:
                display_str += horiz_grp_divider
            for nc in range(1, self.nCol + 1):
                if nc == 1:
                    display_str += "|"
                val = self.getCellVal(row=nr, col=nc)
                disp = "  " if self.isEmpty(val) else f"{val} "
                display_str += disp
                if nc % self.nSubCol == 0:
                    display_str += "|"
            display_str += "\n"
        display_str += horiz_grp_divider
Example #22
 def get_image_files(self, file_dir=None, name=None):
     """ Get list of image files given name
     :file_dir: file directory
             default: self.image_path
     :name: selection name
         default: all images
     :returns: list of absolute paths to image files
     if file_dir is None:
         file_dir = self.image_path
     if name is not None:
         file_dir = os.path.join(file_dir, name)
     names = os.listdir(file_dir)
     image_files = []
     for name in sorted(names):
         path = os.path.join(file_dir, name)
         if (os.path.exists(path) and not os.path.isdir(path)):
                 im =
             except IOError:
                 SlTrace.lg(f"Not an image file: {path}")
     return image_files
    def set_check_box(self,
        """ Set up check box for field
        :field: local field name
        :label: button label - default final section of field name
        :value: value to set "string"
        :command: function to call with new value when box changes
                    default: no call
        if frame is None:
            frame = self.base_frame
        if label is None:
            label = field

        if label is not None:
            wlabel = Label(frame, text=label)
        content = BooleanVar()
        full_field = self.field_name(field)
        value = self.get_prop_val(full_field, value)
        cmd = None
        if command is not None:  # HACK - only works for ONE checkbox
            self.check_box_change_content = content
            self.check_box_change_callback = command
            cmd = self.check_box_change
        widget = Checkbutton(frame, variable=content, command=cmd)
        widget.pack(side="left", fill="none", expand=True)
        self.ctls[full_field] = widget
        self.ctls_vars[full_field] = content
        SlTrace.lg(f"set_check_box adding field:{full_field}")
        self.set_prop_val(full_field, value)
    def open(self, src_file=None):
        """ Open command file
        Opens output files, if specified
        :src_file: Source file default, if no extension ext="csrc"
            If no extension: look for .py, then .csrc
            in source_directories
            else look for file in source_directories
        :returns: True iff successful open (note that py type
                flles are are opened when first get_tok is called
        self.lineno = 0  # Src line number
        self.eof = True  # Cleared on open, set on EOF
        if src_file is None:
            if self.src_file_name is None:
                raise SelectError(
                    "open: no src_file and no self.src_file_name")

            src_file = self.src_file_name
        self.src_file_name = src_file
        if not self.check_file(self.src_file_name):
            return False

        self.new_file = False
        if self.file_type == "csrc":
                if self.src_lst or SlTrace.trace("csrc"):
                    SlTrace.lg("Open %s" % self.src_file_path)
                self.in_file = open(self.src_file_path, "r")
            except IOError as e:
                errno, strerror = e.args
                SlTrace.lg("Can't open command source file %s: %d %s" %
                           (self.src_file_path, errno, strerror))
                self.eof = True
                return False
        self.eof = False
        return True
Example #25
    def trace_item(self, rec_id=None, track_no=None, prefix="", begin=-3, end=-1):
        """ Trace(list) entry
        :rec_id: record id
        :trac_no: tracing number
        :begin: start stack list (-99 99 most recent entries)
        :end: end stack list (-1 most recent entry)
        if rec_id is not None:
            if rec_id in self.by_rec_id:
                track = self.by_rec_id[rec_id]
                return          # Ignore if not tracked
        elif track_no is not None:
            if track_no in self.by_track_no:
                track = self.by_track_no[track]
                return          # Ignore if not tracked
            raise("trace_item has neither rec_id nor track_no")
        rec_id = track[0]
        tags = self.gettags(rec_id)
        track_no = track[1]
        stack = track[2]
        entries = traceback.format_list(stack)

        # Remove the last two entries for the call to extract_stack() and to
        # the one before that, this function. Each entry consists of single
        # string with consisting of two lines, the script file path then the
        # line of source code making the call to this function.
        ###del entries[-2:]
        part = self.get_part_from_tags(tags)
        SlTrace.lg("%s%s %s %s" % (prefix, rec_id, tags, part))
        for entry in entries[begin:end]:
            SlTrace.lg("%s" % (entry))
    def get_drawn_line_points(self, p1, p2, width=None, point_resolution=None):
        """ Get drawn line fill points
        Find perimeter of surrounding points of a rectangle
        For  simplicity we consider vertical width
        :p1: beginning point
        :p2: end point
        :width: width of line
            default: self.line_width
        :point_resolution: fill point spacing
            default: self.point_resolution
        :returns: set of fill points
        ###pts = self.get_line_points(p1,p2)
        ###return set(pts)

        if width is None:
            width = self.line_width
        if point_resolution is None:
            point_resolution = self.point_resolution
        pr = point_resolution
            f"get_drawn_Line_points {p1} {p2}"
            f" width: {width} res: {pr}", "xpoint")
        p1x, p1y = p1
        p2x, p2y = p2
        self.set_line_funs(p1, p2)

        dx = self.lfun_unorm_x * width / 2  # draw width offsets
        dy = self.lfun_unorm_y * width / 2
        pp1 = (p1x + dx, p1y + dy)  # upper left corner
        pp2 = (p2x + dx, p2y + dy)  # upper right corner
        pp3 = (p2x - dx, p2y - dy)  # lower right corner
        pp4 = (p1x - dx, p1y - dy)  # lower left corner
        perim_list = [pp1, pp2, pp3, pp4]
        filled_points = self.fill_points(perim_list)
        return filled_points
    def fill_points(self, point_list, point_resolution=None):
        """ Fill surrounding points assuming points are connected
        and enclose an area. - we will, eventualy, do
        "what turtle would do".
        Our initial technique assumes a convex region:
            given every sequential group of points (pn,
            pn+1,pn+2), pn+1 is within the fill region.
        We divide up the fill region into triangles:
            ntriangle = len(point_list)-2
            for i in rage(1,ntriangle):
        :point_list: list (iterable) of surrounding points
        :point_resolution: distance under which cells containing
                each point will cover region with no gaps
                default: self.point_resolution
        :returns: set of points (ix,iy) whose cells
                cover fill region
        if point_resolution is None:
            point_resolution = self.point_resolution
        SlTrace.lg(f"fill_points: {pl(point_list)} res:{point_resolution}",
        fill_point_set = set()
        if len(point_list) < 3:
            return set()

        plist = iter(point_list)
        p1 = point_list[0]
        for i in range(2, len(point_list)):
            p2 = point_list[i]
            p3 = point_list[i - 1]
            points = self.get_points_triangle(
                p1, p2, p3, point_resolution=point_resolution)
        return fill_point_set
Example #28
 def list_selected(self, prefix=None):
     if prefix is None:
         prefix = ""
         prefix = prefix + " "
     part_ids = list(self.parts_by_id)
     n_on = 0
     for part_id in part_ids:
         part = self.get_part(id=part_id)
         if part.is_selected():
             n_on += 1
     SlTrace.lg("%sparts selected on(%d of %d):" % (prefix, n_on, len(part_ids)))
     for part_id in part_ids:
         part = self.get_part(id=part_id)
         if part.is_selected():
             SlTrace.lg("    %s" % (part))
     if SlTrace.trace("selected_selects"):
         selecteds = self.get_selects()
         SlTrace.lg("parts in selecteds:")
         for part_id in selecteds:
             SlTrace.lg("    %s" % self.get_part(part_id))
Example #29
 def displaySetCellList(self, ):
     setCells = self.getSetList()
     SlTrace.lg(f"setCells:", "display")
     for r_set in setCells:
         col = r_set.col
         row = r_set.row
         val = r_set.val
         SlTrace.lg(f"C{col}R{row}:{val}", "display")
Example #30
    def get_transform_inverse(cls, block):
        xtran = BlockBlock.get_transform(block)
        if xtran is None:
            return xtran  # No translation

        SlTrace.lg("xtran = %s" % tran2matrix(xtran))
        ixtran = xtran.inverse()
        SlTrace.lg("ixtran = %s" % tran2matrix(ixtran))
        xtran_ti = xtran * ixtran
        SlTrace.lg("xtran * ixtran=%s" % tran2matrix(xtran_ti))
        return ixtran