Skip to content

Commit

Permalink
Fixes Python2 compatibility issues in new workspace/reports. Cleans u…
Browse files Browse the repository at this point in the history
…p factory.py.

Adds a new "compattools.py" file with "isstr" and "isint" function to
properly check if something is an integer or string in Python2 or Python3
(the issues involved are that Python2 has a 'long' type that Python3
doesn't, and in Python3 the default string type is unicode).  These new
functions have been added throughout pyGSTi to replace isinstance(x, int)
and isinstance(x, str) and variants thereof to give better Python2
compatibility across the board.  Such comparisons are especially relevant
to the reporting code.

Fixes a bug with using the 'exec' statement within Python2 -- (you can't
use 'exec' in a function which contains nested functions unless you specify
the locals).

Consolidates code within factory.py, adding some internal subroutines and
making _merge_template do more processing (e.g. inlining CSS files).
Additional linlogPercentage and errgen_type parameters added to factory
functions, so start moving away from having "display options" contained
in a Results object.

Adds precision argument to WorkspaceTable's render() function, which
 should later get plumbed up to an argument of the factory functions.

All of the recently added tutorials now run using a python2 kernel,
which is the closest thing we have to a python2 test at this point.
  • Loading branch information
Erik Nielsen committed Apr 3, 2017
1 parent 0949285 commit 1a98c84
Show file tree
Hide file tree
Showing 23 changed files with 337 additions and 295 deletions.
5 changes: 3 additions & 2 deletions packages/pygsti/construction/gatestringconstruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import numpy.random as _rndm

from ..tools import listtools as _lt
from ..tools import compattools as _compat
from ..objects import gatestring as _gs
from .spamspecconstruction import get_spam_strs as _get_spam_strs

Expand Down Expand Up @@ -91,7 +92,7 @@ def create_gatestring_list(*args,**kwargs):
gateStr = result
elif isinstance(result,list) or isinstance(result,tuple):
gateStr = _gs.GateString(result)
elif isinstance(result,str):
elif _compat.isstr(result):
gateStr = _gs.GateString(None, result)
lst.append(gateStr)

Expand Down Expand Up @@ -514,7 +515,7 @@ def gatestring_list( listOfGateLabelTuplesOrStrings ):
ret.append(x)
elif isinstance(x,tuple) or isinstance(x,list):
ret.append( _gs.GateString(x) )
elif isinstance(x,str):
elif _compat.isstr(x):
ret.append( _gs.GateString(None, x) )
else:
raise ValueError("Cannot convert type %s into a GateString" % str(type(x)))
Expand Down
13 changes: 7 additions & 6 deletions packages/pygsti/drivers/longsequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .. import construction as _construction
from .. import objects as _objs
from .. import io as _io
from ..tools import compattools as _compat

def do_long_sequence_gst(dataFilenameOrSet, targetGateFilenameOrSet,
prepStrsListOrFilename, effectStrsListOrFilename,
Expand Down Expand Up @@ -189,24 +190,24 @@ def do_long_sequence_gst(dataFilenameOrSet, targetGateFilenameOrSet,
if advancedOptions is None: advancedOptions = {}

#Get/load fiducials
if isinstance(prepStrsListOrFilename, str):
if _compat.isstr(prepStrsListOrFilename):
prepStrs = _io.load_gatestring_list(prepStrsListOrFilename)
else: prepStrs = prepStrsListOrFilename

if effectStrsListOrFilename is None:
effectStrs = prepStrs #use same strings for effectStrs if effectStrsListOrFilename is None
else:
if isinstance(effectStrsListOrFilename, str):
if _compat.isstr(effectStrsListOrFilename):
effectStrs = _io.load_gatestring_list(effectStrsListOrFilename)
else: effectStrs = effectStrsListOrFilename

#Get/load germs
if isinstance(germsListOrFilename, str):
if _compat.isstr(germsListOrFilename):
germs = _io.load_gatestring_list(germsListOrFilename)
else: germs = germsListOrFilename

#Get/load target gateset
if isinstance(targetGateFilenameOrSet, str):
if _compat.isstr(targetGateFilenameOrSet):
gs_target = _io.load_gateset(targetGateFilenameOrSet)
else:
gs_target = targetGateFilenameOrSet #assume a GateSet object
Expand Down Expand Up @@ -340,13 +341,13 @@ def do_long_sequence_gst_base(dataFilenameOrSet, targetGateFilenameOrSet,
printer = _objs.VerbosityPrinter.build_printer(verbosity, comm)

#Get/load target gateset
if isinstance(targetGateFilenameOrSet, str):
if _compat.isstr(targetGateFilenameOrSet):
gs_target = _io.load_gateset(targetGateFilenameOrSet)
else:
gs_target = targetGateFilenameOrSet #assume a GateSet object

#Get/load dataset
if isinstance(dataFilenameOrSet, str):
if _compat.isstr(dataFilenameOrSet):
ds = _io.load_dataset(dataFilenameOrSet, True, "aggregate", printer)
default_dir = _os.path.dirname(dataFilenameOrSet) #default directory for reports, etc
default_base = _os.path.splitext( _os.path.basename(dataFilenameOrSet) )[0]
Expand Down
3 changes: 2 additions & 1 deletion packages/pygsti/objects/gatecalc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from ..tools import gatetools as _gt
from ..tools import mpitools as _mpit
from ..tools import slicetools as _slct
from ..tools import compattools as _compat
from .profiler import DummyProfiler as _DummyProfiler
_dummy_profiler = _DummyProfiler()

Expand Down Expand Up @@ -99,7 +100,7 @@ def _is_remainder_spamlabel(self, label):
probabilities such that all SPAM label probabilities
sum exactly to 1.0.
"""
if not isinstance(label,str): return False #b/c label could be a custom (rho,E) pair
if not _compat.isstr(label): return False #b/c label could be a custom (rho,E) pair
return bool(self.spamdefs[label] == (self._remainderLabel, self._remainderLabel))

def _get_remainder_row_index(self, spam_label_rows):
Expand Down
3 changes: 2 additions & 1 deletion packages/pygsti/objects/gatemapcalc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from ..tools import gatetools as _gt
from ..tools import mpitools as _mpit
from ..tools import slicetools as _slct
from ..tools import compattools as _compat
from .profiler import DummyProfiler as _DummyProfiler
from .verbosityprinter import VerbosityPrinter as _VerbosityPrinter
from .mapevaltree import MapEvalTree as _MapEvalTree
Expand Down Expand Up @@ -80,7 +81,7 @@ def __init__(self, dim, gates, preps, effects, povm_identity, spamdefs,

#Same as GateMatrixCalc, but not general enough to be in base class
def _rhoE_from_spamLabel(self, spamLabel):
if isinstance(spamLabel,str):
if _compat.isstr(spamLabel):
(rholabel,elabel) = self.spamdefs[spamLabel]
rho = self.preps[rholabel]
E = _np.conjugate(_np.transpose(self._get_evec(elabel)))
Expand Down
3 changes: 2 additions & 1 deletion packages/pygsti/objects/gatematrixcalc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from ..tools import gatetools as _gt
from ..tools import mpitools as _mpit
from ..tools import slicetools as _slct
from ..tools import compattools as _compat
from .profiler import DummyProfiler as _DummyProfiler
from .verbosityprinter import VerbosityPrinter as _VerbosityPrinter
from .matrixevaltree import MatrixEvalTree as _MatrixEvalTree
Expand Down Expand Up @@ -1561,7 +1562,7 @@ def _scaleExp(self, scaleExps):


def _rhoE_from_spamLabel(self, spamLabel):
if isinstance(spamLabel,str):
if _compat.isstr(spamLabel):
(rholabel,elabel) = self.spamdefs[spamLabel]
rho = self.preps[rholabel]
E = _np.conjugate(_np.transpose(self._get_evec(elabel)))
Expand Down
3 changes: 2 additions & 1 deletion packages/pygsti/objects/gateset.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from ..tools import gatetools as _gt
from ..tools import likelihoodfns as _lf
from ..tools import jamiolkowski as _jt
from ..tools import compattools as _compat

from . import evaltree as _evaltree
from . import gate as _gate
Expand Down Expand Up @@ -2787,7 +2788,7 @@ def rotate(self, rotate=None, max_rotate=None, seed=None):
newGateset.gates[label].rotate(rot, myBasis)

elif rotate is not None:
assert(isinstance(rotate,float) or isinstance(rotate,int) or len(rotate) == dim-1), "Invalid 'rotate' argument"
assert(isinstance(rotate,float) or _compat.isint(rotate) or len(rotate) == dim-1), "Invalid 'rotate' argument"
for (i,label) in enumerate(self.gates):
newGateset.gates[label].rotate(rotate, myBasis)

Expand Down
3 changes: 2 additions & 1 deletion packages/pygsti/objects/gatestring.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
""" Defines the GateString class and derived classes which represent gate strings."""

import numpy as _np
from ..tools import compattools as _compat

def _gateSeqToStr(seq):
if len(seq) == 0: return "{}" #special case of empty gate string
Expand Down Expand Up @@ -161,7 +162,7 @@ def __add__(self,x):
return GateString(self.tup + x.tup, s, bCheck=False)

def __mul__(self,x):
assert( (isinstance(x,int) or _np.issubdtype(x,int)) and x >= 0)
assert( (_compat.isint(x) or _np.issubdtype(x,int)) and x >= 0)
if x > 1: s = "(%s)^%d" % (self.str,x)
elif x == 1: s = "(%s)" % self.str
else: s = "{}"
Expand Down
3 changes: 2 additions & 1 deletion packages/pygsti/objects/labeldicts.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from . import spamvec as _sv
from . import gate as _gate
from ..tools import compattools as _compat

class PrefixOrderedDict(_collections.OrderedDict):
def __init__(self, prefix, items=[]):
Expand Down Expand Up @@ -203,7 +204,7 @@ def __init__(self, remainderLabel, items=[]):
super(OrderedSPAMLabelDict,self).__init__(items)

def __setitem__(self, key, val):
if not isinstance(key, str):
if not _compat.isstr(key):
key = str(key)
if type(val) != tuple or len(val) != 2:
raise KeyError("SPAM label values must be 2-tuples!")
Expand Down
7 changes: 4 additions & 3 deletions packages/pygsti/objects/protectedarray.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import division, print_function, absolute_import, unicode_literals
import numpy as _np
from ..tools import compattools as _compat

class ProtectedArray(object):
"""
Expand All @@ -21,7 +22,7 @@ def __init__(self, input_array, indicesToProtect=None):
for ky,L in zip(indicesToProtect,self.base.shape):
if isinstance( ky, slice ):
pindices = range(*ky.indices(L))
elif isinstance( ky, int ):
elif _compat.isint( ky ):
i = ky+L if ky<0 else ky
if i < 0 or i > L:
raise IndexError("index (%d) is out of range." % ky)
Expand Down Expand Up @@ -109,7 +110,7 @@ def __getitem__( self, key ) :
nTotalInDim = len(indices)
nUnprotectedInCurDim = (len(indices) - len(new_pindices))

elif isinstance( ky, int ):
elif _compat.isint( ky ):
i = ky+L if ky<0 else ky
if i > L:
raise IndexError("The index (%d) is out of range." % ky)
Expand Down Expand Up @@ -177,7 +178,7 @@ def __setitem__( self, key, val ) :
protectionViolation.append(True)
else: protectionViolation.append(False)

elif isinstance( ky, int ):
elif _compat.isint( ky ):
i = ky+L if ky<0 else ky
if i > L:
raise IndexError("The index (%d) is out of range." % ky)
Expand Down
5 changes: 3 additions & 2 deletions packages/pygsti/objects/spamvec.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .. import optimize as _opt
from ..tools import matrixtools as _mt
from ..tools import gatetools as _gt
from ..tools import compattools as _compat
from .protectedarray import ProtectedArray as _ProtectedArray


Expand Down Expand Up @@ -537,7 +538,7 @@ def depolarize(self, amount):
-------
None
"""
if isinstance(amount,float) or isinstance(amount,int):
if isinstance(amount,float) or _compat.isint(amount):
D = _np.diag( [1]+[1-amount]*(self.dim-1) )
else:
assert(len(amount) == self.dim-1)
Expand Down Expand Up @@ -748,7 +749,7 @@ def depolarize(self, amount):
-------
None
"""
if isinstance(amount,float) or isinstance(amount,int):
if isinstance(amount,float) or _compat.isint(amount):
D = _np.diag( [1]+[1-amount]*(self.dim-1) )
else:
assert(len(amount) == self.dim-1)
Expand Down
5 changes: 3 additions & 2 deletions packages/pygsti/objects/verbosityprinter.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from __future__ import division, print_function, absolute_import, unicode_literals
import numbers as _numbers
from contextlib import contextmanager as _contextmanager
from copy import deepcopy as _dc
import sys as _sys
import math as _math # used for digit formatting

from ..tools import compattools as _compat

def _num_digits(n):
return int(_math.log10(n)) + 1 if n > 0 else 1

Expand Down Expand Up @@ -183,7 +184,7 @@ def build_printer(verbosity, comm=None):
The printer object, constructed from either an integer or another printer
'''
if isinstance(verbosity, _numbers.Integral):
if _compat.isint(verbosity):
printer = VerbosityPrinter(verbosity, comm=comm)
else:
printer = verbosity.clone() # deepcopy the printer object if it has been passed as a verbosity
Expand Down
4 changes: 2 additions & 2 deletions packages/pygsti/report/colormaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def normalize(self, value):
#vmin, vmax, midpoint = self.vmin, self.vmax, self.midpoint
#
#is_scalar = False
#if isinstance(value, float) or isinstance(value, int):
#if isinstance(value, float) or _compat.isint(value, int):
# is_scalar = True
#result = _np.ma.array(value)
#
Expand Down Expand Up @@ -223,7 +223,7 @@ def normalize(self, value):
return value

#is_scalar = False
#if isinstance(value, float) or isinstance(value, int):
#if isinstance(value, float) or _compat.isint(value, int):
# is_scalar = True
#
#result = _np.ma.array(value)
Expand Down
Loading

0 comments on commit 1a98c84

Please sign in to comment.