def test_normalise1():
    # normalisation of anisotropic locations, clipping
    doc = DesignSpaceDocument()
    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = -1000
    a1.maximum = 1000
    a1.default = 0
    a1.name = "axisName_a"
    a1.tag = "TAGA"
    doc.addAxis(a1)
    assert doc.normalizeLocation(dict(axisName_a=0)) == {'axisName_a': 0.0}
    assert doc.normalizeLocation(dict(axisName_a=1000)) == {'axisName_a': 1.0}
    # clipping beyond max values:
    assert doc.normalizeLocation(dict(axisName_a=1001)) == {'axisName_a': 1.0}
    assert doc.normalizeLocation(dict(axisName_a=500)) == {'axisName_a': 0.5}
    assert doc.normalizeLocation(dict(axisName_a=-1000)) == {'axisName_a': -1.0}
    assert doc.normalizeLocation(dict(axisName_a=-1001)) == {'axisName_a': -1.0}
    # anisotropic coordinates normalise to isotropic
    assert doc.normalizeLocation(dict(axisName_a=(1000, -1000))) == {'axisName_a': 1.0}
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.minimum, axis.default, axis.maximum))
    r.sort()
    assert r == [('axisName_a', -1.0, 0.0, 1.0)]
def test_normalise2():
    # normalisation with minimum > 0
    doc = DesignSpaceDocument()
    # write some axes
    a2 = AxisDescriptor()
    a2.minimum = 100
    a2.maximum = 1000
    a2.default = 100
    a2.name = "axisName_b"
    doc.addAxis(a2)
    assert doc.normalizeLocation(dict(axisName_b=0)) == {'axisName_b': 0.0}
    assert doc.normalizeLocation(dict(axisName_b=1000)) == {'axisName_b': 1.0}
    # clipping beyond max values:
    assert doc.normalizeLocation(dict(axisName_b=1001)) == {'axisName_b': 1.0}
    assert doc.normalizeLocation(dict(axisName_b=500)) == {'axisName_b': 0.4444444444444444}
    assert doc.normalizeLocation(dict(axisName_b=-1000)) == {'axisName_b': 0.0}
    assert doc.normalizeLocation(dict(axisName_b=-1001)) == {'axisName_b': 0.0}
    # anisotropic coordinates normalise to isotropic
    assert doc.normalizeLocation(dict(axisName_b=(1000,-1000))) == {'axisName_b': 1.0}
    assert doc.normalizeLocation(dict(axisName_b=1001)) == {'axisName_b': 1.0}
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.minimum, axis.default, axis.maximum))
    r.sort()
    assert r == [('axisName_b', 0.0, 0.0, 1.0)]
def test_normalise1():
    # normalisation of anisotropic locations, clipping
    doc = DesignSpaceDocument()
    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = -1000
    a1.maximum = 1000
    a1.default = 0
    a1.name = "axisName_a"
    a1.tag = "TAGA"
    doc.addAxis(a1)
    assert doc.normalizeLocation(dict(axisName_a=0)) == {'axisName_a': 0.0}
    assert doc.normalizeLocation(dict(axisName_a=1000)) == {'axisName_a': 1.0}
    # clipping beyond max values:
    assert doc.normalizeLocation(dict(axisName_a=1001)) == {'axisName_a': 1.0}
    assert doc.normalizeLocation(dict(axisName_a=500)) == {'axisName_a': 0.5}
    assert doc.normalizeLocation(dict(axisName_a=-1000)) == {'axisName_a': -1.0}
    assert doc.normalizeLocation(dict(axisName_a=-1001)) == {'axisName_a': -1.0}
    # anisotropic coordinates normalise to isotropic
    assert doc.normalizeLocation(dict(axisName_a=(1000, -1000))) == {'axisName_a': 1.0}
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.minimum, axis.default, axis.maximum))
    r.sort()
    assert r == [('axisName_a', -1.0, 0.0, 1.0)]
def test_normalise2():
    # normalisation with minimum > 0
    doc = DesignSpaceDocument()
    # write some axes
    a2 = AxisDescriptor()
    a2.minimum = 100
    a2.maximum = 1000
    a2.default = 100
    a2.name = "axisName_b"
    doc.addAxis(a2)
    assert doc.normalizeLocation(dict(axisName_b=0)) == {'axisName_b': 0.0}
    assert doc.normalizeLocation(dict(axisName_b=1000)) == {'axisName_b': 1.0}
    # clipping beyond max values:
    assert doc.normalizeLocation(dict(axisName_b=1001)) == {'axisName_b': 1.0}
    assert doc.normalizeLocation(dict(axisName_b=500)) == {'axisName_b': 0.4444444444444444}
    assert doc.normalizeLocation(dict(axisName_b=-1000)) == {'axisName_b': 0.0}
    assert doc.normalizeLocation(dict(axisName_b=-1001)) == {'axisName_b': 0.0}
    # anisotropic coordinates normalise to isotropic
    assert doc.normalizeLocation(dict(axisName_b=(1000,-1000))) == {'axisName_b': 1.0}
    assert doc.normalizeLocation(dict(axisName_b=1001)) == {'axisName_b': 1.0}
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.minimum, axis.default, axis.maximum))
    r.sort()
    assert r == [('axisName_b', 0.0, 0.0, 1.0)]
Exemple #5
0
def main(args):
	from fontTools import configLogger

	args = args[1:]

	# TODO: allow user to configure logging via command-line options
	configLogger(level="INFO")

	if len(args) < 1:
		print("usage: fonttools varLib.models source.designspace", file=sys.stderr)
		print("  or")
		print("usage: fonttools varLib.models location1 location2 ...", file=sys.stderr)
		sys.exit(1)

	from pprint import pprint

	if len(args) == 1 and args[0].endswith('.designspace'):
		from fontTools.designspaceLib import DesignSpaceDocument
		doc = DesignSpaceDocument()
		doc.read(args[0])
		locs = [s.location for s in doc.sources]
		print("Original locations:")
		pprint(locs)
		doc.normalize()
		print("Normalized locations:")
		pprint(locs)
	else:
		axes = [chr(c) for c in range(ord('A'), ord('Z')+1)]
		locs = [dict(zip(axes, (float(v) for v in s.split(',')))) for s in args]

	model = VariationModel(locs)
	print("Sorted locations:")
	pprint(model.locations)
	print("Supports:")
	pprint(model.supports)
Exemple #6
0
def main(args):
	from fontTools import configLogger

	args = args[1:]

	# TODO: allow user to configure logging via command-line options
	configLogger(level="INFO")

	if len(args) < 1:
		print("usage: fonttools varLib.models source.designspace", file=sys.stderr)
		print("  or")
		print("usage: fonttools varLib.models location1 location2 ...", file=sys.stderr)
		sys.exit(1)

	from pprint import pprint

	if len(args) == 1 and args[0].endswith('.designspace'):
		from fontTools.designspaceLib import DesignSpaceDocument
		doc = DesignSpaceDocument()
		doc.read(args[0])
		locs = [s.location for s in doc.sources]
		print("Original locations:")
		pprint(locs)
		doc.normalize()
		print("Normalized locations:")
		pprint(locs)
	else:
		axes = [chr(c) for c in range(ord('A'), ord('Z')+1)]
		locs = [dict(zip(axes, (float(v) for v in s.split(',')))) for s in args]

	model = VariationModel(locs)
	print("Sorted locations:")
	pprint(model.locations)
	print("Supports:")
	pprint(model.supports)
def test_rulesDocument(tmpdir):
    # tests of rules in a document, roundtripping.
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir, "testRules.designspace")
    testDocPath2 = os.path.join(tmpdir, "testRules_roundtrip.designspace")
    doc = DesignSpaceDocument()
    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    a1.name = "axisName_a"
    a1.tag = "TAGA"
    b1 = AxisDescriptor()
    b1.minimum = 2000
    b1.maximum = 3000
    b1.default = 2000
    b1.name = "axisName_b"
    b1.tag = "TAGB"
    doc.addAxis(a1)
    doc.addAxis(b1)
    r1 = RuleDescriptor()
    r1.name = "named.rule.1"
    r1.conditionSets.append([
        dict(name='axisName_a', minimum=0, maximum=1000),
        dict(name='axisName_b', minimum=0, maximum=3000)
    ])
    r1.subs.append(("a", "a.alt"))
    # rule with minium and maximum
    doc.addRule(r1)
    assert len(doc.rules) == 1
    assert len(doc.rules[0].conditionSets) == 1
    assert len(doc.rules[0].conditionSets[0]) == 2
    assert _axesAsDict(doc.axes) == {'axisName_a': {'map': [], 'name': 'axisName_a', 'default': 0, 'minimum': 0, 'maximum': 1000, 'tag': 'TAGA'}, 'axisName_b': {'map': [], 'name': 'axisName_b', 'default': 2000, 'minimum': 2000, 'maximum': 3000, 'tag': 'TAGB'}}
    assert doc.rules[0].conditionSets == [[
        {'minimum': 0, 'maximum': 1000, 'name': 'axisName_a'},
        {'minimum': 0, 'maximum': 3000, 'name': 'axisName_b'}]]
    assert doc.rules[0].subs == [('a', 'a.alt')]
    doc.normalize()
    assert doc.rules[0].name == 'named.rule.1'
    assert doc.rules[0].conditionSets == [[
        {'minimum': 0.0, 'maximum': 1.0, 'name': 'axisName_a'},
        {'minimum': 0.0, 'maximum': 1.0, 'name': 'axisName_b'}]]
    # still one conditionset
    assert len(doc.rules[0].conditionSets) == 1
    doc.write(testDocPath)
    # add a stray conditionset
    _addUnwrappedCondition(testDocPath)
    doc2 = DesignSpaceDocument()
    doc2.read(testDocPath)
    assert len(doc2.axes) == 2
    assert len(doc2.rules) == 1
    assert len(doc2.rules[0].conditionSets) == 2
    doc2.write(testDocPath2)
    # verify these results
    # make sure the stray condition is now neatly wrapped in a conditionset.
    doc3 = DesignSpaceDocument()
    doc3.read(testDocPath2)
    assert len(doc3.rules) == 1
    assert len(doc3.rules[0].conditionSets) == 2
def test_rulesDocument(tmpdir):
    # tests of rules in a document, roundtripping.
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir, "testRules.designspace")
    testDocPath2 = os.path.join(tmpdir, "testRules_roundtrip.designspace")
    doc = DesignSpaceDocument()
    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    a1.name = "axisName_a"
    a1.tag = "TAGA"
    b1 = AxisDescriptor()
    b1.minimum = 2000
    b1.maximum = 3000
    b1.default = 2000
    b1.name = "axisName_b"
    b1.tag = "TAGB"
    doc.addAxis(a1)
    doc.addAxis(b1)
    r1 = RuleDescriptor()
    r1.name = "named.rule.1"
    r1.conditionSets.append([
        dict(name='axisName_a', minimum=0, maximum=1000),
        dict(name='axisName_b', minimum=0, maximum=3000)
    ])
    r1.subs.append(("a", "a.alt"))
    # rule with minium and maximum
    doc.addRule(r1)
    assert len(doc.rules) == 1
    assert len(doc.rules[0].conditionSets) == 1
    assert len(doc.rules[0].conditionSets[0]) == 2
    assert _axesAsDict(doc.axes) == {'axisName_a': {'map': [], 'name': 'axisName_a', 'default': 0, 'minimum': 0, 'maximum': 1000, 'tag': 'TAGA'}, 'axisName_b': {'map': [], 'name': 'axisName_b', 'default': 2000, 'minimum': 2000, 'maximum': 3000, 'tag': 'TAGB'}}
    assert doc.rules[0].conditionSets == [[
        {'minimum': 0, 'maximum': 1000, 'name': 'axisName_a'},
        {'minimum': 0, 'maximum': 3000, 'name': 'axisName_b'}]]
    assert doc.rules[0].subs == [('a', 'a.alt')]
    doc.normalize()
    assert doc.rules[0].name == 'named.rule.1'
    assert doc.rules[0].conditionSets == [[
        {'minimum': 0.0, 'maximum': 1.0, 'name': 'axisName_a'},
        {'minimum': 0.0, 'maximum': 1.0, 'name': 'axisName_b'}]]
    # still one conditionset
    assert len(doc.rules[0].conditionSets) == 1
    doc.write(testDocPath)
    # add a stray conditionset
    _addUnwrappedCondition(testDocPath)
    doc2 = DesignSpaceDocument()
    doc2.read(testDocPath)
    assert len(doc2.axes) == 2
    assert len(doc2.rules) == 1
    assert len(doc2.rules[0].conditionSets) == 2
    doc2.write(testDocPath2)
    # verify these results
    # make sure the stray condition is now neatly wrapped in a conditionset.
    doc3 = DesignSpaceDocument()
    doc3.read(testDocPath2)
    assert len(doc3.rules) == 1
    assert len(doc3.rules[0].conditionSets) == 2
Exemple #9
0
def main(args=None):
    """Normalize locations on a given designspace"""
    from fontTools import configLogger
    import argparse

    parser = argparse.ArgumentParser(
        "fonttools varLib.models",
        description=main.__doc__,
    )
    parser.add_argument(
        "--loglevel",
        metavar="LEVEL",
        default="INFO",
        help="Logging level (defaults to INFO)",
    )

    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument("-d", "--designspace", metavar="DESIGNSPACE", type=str)
    group.add_argument(
        "-l",
        "--locations",
        metavar="LOCATION",
        nargs="+",
        help=
        "Master locations as comma-separate coordinates. One must be all zeros.",
    )

    args = parser.parse_args(args)

    configLogger(level=args.loglevel)
    from pprint import pprint

    if args.designspace:
        from fontTools.designspaceLib import DesignSpaceDocument

        doc = DesignSpaceDocument()
        doc.read(args.designspace)
        locs = [s.location for s in doc.sources]
        print("Original locations:")
        pprint(locs)
        doc.normalize()
        print("Normalized locations:")
        locs = [s.location for s in doc.sources]
        pprint(locs)
    else:
        axes = [chr(c) for c in range(ord("A"), ord("Z") + 1)]
        locs = [
            dict(zip(axes, (float(v) for v in s.split(","))))
            for s in args.locations
        ]

    model = VariationModel(locs)
    print("Sorted locations:")
    pprint(model.locations)
    print("Supports:")
    pprint(model.supports)
def test_normalise4():
    # normalisation with a map
    doc = DesignSpaceDocument()
    # write some axes
    a4 = AxisDescriptor()
    a4.minimum = 0
    a4.maximum = 1000
    a4.default = 0
    a4.name = "ddd"
    a4.map = [(0,100), (300, 500), (600, 500), (1000,900)]
    doc.addAxis(a4)
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.map))
    r.sort()
    assert r == [('ddd', [(0, 0.0), (300, 0.5), (600, 0.5), (1000, 1.0)])]
def test_normalise4():
    # normalisation with a map
    doc = DesignSpaceDocument()
    # write some axes
    a4 = AxisDescriptor()
    a4.minimum = 0
    a4.maximum = 1000
    a4.default = 0
    a4.name = "ddd"
    a4.map = [(0,100), (300, 500), (600, 500), (1000,900)]
    doc.addAxis(a4)
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.map))
    r.sort()
    assert r == [('ddd', [(0, 0.1), (300, 0.5), (600, 0.5), (1000, 0.9)])]
def test_axisMapping():
    # note: because designspance lib does not do any actual
    # processing of the mapping data, we can only check if there data is there.
    doc = DesignSpaceDocument()
    # write some axes
    a4 = AxisDescriptor()
    a4.minimum = 0
    a4.maximum = 1000
    a4.default = 0
    a4.name = "ddd"
    a4.map = [(0,100), (300, 500), (600, 500), (1000,900)]
    doc.addAxis(a4)
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.map))
    r.sort()
    assert r == [('ddd', [(0, 0.0), (300, 0.5), (600, 0.5), (1000, 1.0)])]
def test_axisMapping():
    # note: because designspance lib does not do any actual
    # processing of the mapping data, we can only check if there data is there.
    doc = DesignSpaceDocument()
    # write some axes
    a4 = AxisDescriptor()
    a4.minimum = 0
    a4.maximum = 1000
    a4.default = 0
    a4.name = "ddd"
    a4.map = [(0,100), (300, 500), (600, 500), (1000,900)]
    doc.addAxis(a4)
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.map))
    r.sort()
    assert r == [('ddd', [(0, 0.1), (300, 0.5), (600, 0.5), (1000, 0.9)])]
def test_normalise3():
    # normalisation of negative values, with default == maximum
    doc = DesignSpaceDocument()
    # write some axes
    a3 = AxisDescriptor()
    a3.minimum = -1000
    a3.maximum = 0
    a3.default = 0
    a3.name = "ccc"
    doc.addAxis(a3)
    assert doc.normalizeLocation(dict(ccc=0)) == {'ccc': 0.0}
    assert doc.normalizeLocation(dict(ccc=1)) == {'ccc': 0.0}
    assert doc.normalizeLocation(dict(ccc=-1000)) == {'ccc': -1.0}
    assert doc.normalizeLocation(dict(ccc=-1001)) == {'ccc': -1.0}
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.minimum, axis.default, axis.maximum))
    r.sort()
    assert r == [('ccc', -1.0, 0.0, 0.0)]
def test_normalise3():
    # normalisation of negative values, with default == maximum
    doc = DesignSpaceDocument()
    # write some axes
    a3 = AxisDescriptor()
    a3.minimum = -1000
    a3.maximum = 0
    a3.default = 0
    a3.name = "ccc"
    doc.addAxis(a3)
    assert doc.normalizeLocation(dict(ccc=0)) == {'ccc': 0.0}
    assert doc.normalizeLocation(dict(ccc=1)) == {'ccc': 0.0}
    assert doc.normalizeLocation(dict(ccc=-1000)) == {'ccc': -1.0}
    assert doc.normalizeLocation(dict(ccc=-1001)) == {'ccc': -1.0}
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.minimum, axis.default, axis.maximum))
    r.sort()
    assert r == [('ccc', -1.0, 0.0, 0.0)]
Exemple #16
0
def test_rules(tmpdir):
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir, "testRules.designspace")
    testDocPath2 = os.path.join(tmpdir, "testRules_roundtrip.designspace")
    doc = DesignSpaceDocument()
    # write some axes
    a1 = AxisDescriptor()
    a1.tag = "taga"
    a1.name = "aaaa"
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    doc.addAxis(a1)
    a2 = AxisDescriptor()
    a2.tag = "tagb"
    a2.name = "bbbb"
    a2.minimum = 0
    a2.maximum = 3000
    a2.default = 0
    doc.addAxis(a2)

    r1 = RuleDescriptor()
    r1.name = "named.rule.1"
    r1.conditions.append(dict(name='aaaa', minimum=0, maximum=1000))
    r1.conditions.append(dict(name='bbbb', minimum=0, maximum=3000))
    r1.subs.append(("a", "a.alt"))

    # rule with minium and maximum
    doc.addRule(r1)
    assert len(doc.rules) == 1
    assert len(doc.rules[0].conditions) == 2
    assert evaluateRule(r1, dict(aaaa=500, bbbb=0)) == True
    assert evaluateRule(r1, dict(aaaa=0, bbbb=0)) == True
    assert evaluateRule(r1, dict(aaaa=1000, bbbb=0)) == True
    assert evaluateRule(r1, dict(aaaa=1000, bbbb=-100)) == False
    assert evaluateRule(r1, dict(aaaa=1000.0001, bbbb=0)) == False
    assert evaluateRule(r1, dict(aaaa=-0.0001, bbbb=0)) == False
    assert evaluateRule(r1, dict(aaaa=-100, bbbb=0)) == False
    assert processRules([r1], dict(aaaa=500),
                        ["a", "b", "c"]) == ['a.alt', 'b', 'c']
    assert processRules([r1], dict(aaaa=500),
                        ["a.alt", "b", "c"]) == ['a.alt', 'b', 'c']
    assert processRules([r1], dict(aaaa=2000),
                        ["a", "b", "c"]) == ['a', 'b', 'c']

    # rule with only a maximum
    r2 = RuleDescriptor()
    r2.name = "named.rule.2"
    r2.conditions.append(dict(name='aaaa', maximum=500))
    r2.subs.append(("b", "b.alt"))

    assert evaluateRule(r2, dict(aaaa=0)) == True
    assert evaluateRule(r2, dict(aaaa=-500)) == True
    assert evaluateRule(r2, dict(aaaa=1000)) == False

    # rule with only a minimum
    r3 = RuleDescriptor()
    r3.name = "named.rule.3"
    r3.conditions.append(dict(name='aaaa', minimum=500))
    r3.subs.append(("c", "c.alt"))

    assert evaluateRule(r3, dict(aaaa=0)) == False
    assert evaluateRule(r3, dict(aaaa=1000)) == True
    assert evaluateRule(r3, dict(bbbb=1000)) == True

    # rule with only a minimum, maximum in separate conditions
    r4 = RuleDescriptor()
    r4.name = "named.rule.4"
    r4.conditions.append(dict(name='aaaa', minimum=500))
    r4.conditions.append(dict(name='bbbb', maximum=500))
    r4.subs.append(("c", "c.alt"))

    assert evaluateRule(r4, dict()) == True  # is this what we expect though?
    assert evaluateRule(r4, dict(aaaa=1000, bbbb=0)) == True
    assert evaluateRule(r4, dict(aaaa=0, bbbb=0)) == False
    assert evaluateRule(r4, dict(aaaa=1000, bbbb=1000)) == False

    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    a1.name = "aaaa"
    a1.tag = "aaaa"
    b1 = AxisDescriptor()
    b1.minimum = 2000
    b1.maximum = 3000
    b1.default = 2000
    b1.name = "bbbb"
    b1.tag = "bbbb"
    doc.addAxis(a1)
    doc.addAxis(b1)
    assert doc._prepAxesForBender() == {
        'aaaa': {
            'map': [],
            'name': 'aaaa',
            'default': 0,
            'minimum': 0,
            'maximum': 1000,
            'tag': 'aaaa'
        },
        'bbbb': {
            'map': [],
            'name': 'bbbb',
            'default': 2000,
            'minimum': 2000,
            'maximum': 3000,
            'tag': 'bbbb'
        }
    }

    assert doc.rules[0].conditions == [{
        'minimum': 0,
        'maximum': 1000,
        'name': 'aaaa'
    }, {
        'minimum': 0,
        'maximum': 3000,
        'name': 'bbbb'
    }]

    assert doc.rules[0].subs == [('a', 'a.alt')]

    doc.normalize()
    assert doc.rules[0].name == 'named.rule.1'
    assert doc.rules[0].conditions == [{
        'minimum': 0.0,
        'maximum': 1.0,
        'name': 'aaaa'
    }, {
        'minimum': 0.0,
        'maximum': 1.0,
        'name': 'bbbb'
    }]

    doc.write(testDocPath)
    new = DesignSpaceDocument()

    new.read(testDocPath)
    assert len(new.axes) == 4
    assert len(new.rules) == 1
    new.write(testDocPath2)
Exemple #17
0
def test_normalise():
    doc = DesignSpaceDocument()
    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = -1000
    a1.maximum = 1000
    a1.default = 0
    a1.name = "aaa"
    a1.tag = "aaaa"
    doc.addAxis(a1)

    assert doc.normalizeLocation(dict(aaa=0)) == {'aaa': 0.0}
    assert doc.normalizeLocation(dict(aaa=1000)) == {'aaa': 1.0}

    # clipping beyond max values:
    assert doc.normalizeLocation(dict(aaa=1001)) == {'aaa': 1.0}
    assert doc.normalizeLocation(dict(aaa=500)) == {'aaa': 0.5}
    assert doc.normalizeLocation(dict(aaa=-1000)) == {'aaa': -1.0}
    assert doc.normalizeLocation(dict(aaa=-1001)) == {'aaa': -1.0}
    # anisotropic coordinates normalise to isotropic
    assert doc.normalizeLocation(dict(aaa=(1000, -1000))) == {'aaa': 1.0}
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.minimum, axis.default, axis.maximum))
    r.sort()
    assert r == [('aaa', -1.0, 0.0, 1.0)]

    doc = DesignSpaceDocument()
    # write some axes
    a2 = AxisDescriptor()
    a2.minimum = 100
    a2.maximum = 1000
    a2.default = 100
    a2.name = "bbb"
    doc.addAxis(a2)
    assert doc.normalizeLocation(dict(bbb=0)) == {'bbb': 0.0}
    assert doc.normalizeLocation(dict(bbb=1000)) == {'bbb': 1.0}
    # clipping beyond max values:
    assert doc.normalizeLocation(dict(bbb=1001)) == {'bbb': 1.0}
    assert doc.normalizeLocation(dict(bbb=500)) == {'bbb': 0.4444444444444444}
    assert doc.normalizeLocation(dict(bbb=-1000)) == {'bbb': 0.0}
    assert doc.normalizeLocation(dict(bbb=-1001)) == {'bbb': 0.0}
    # anisotropic coordinates normalise to isotropic
    assert doc.normalizeLocation(dict(bbb=(1000, -1000))) == {'bbb': 1.0}
    assert doc.normalizeLocation(dict(bbb=1001)) == {'bbb': 1.0}
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.minimum, axis.default, axis.maximum))
    r.sort()
    assert r == [('bbb', 0.0, 0.0, 1.0)]

    doc = DesignSpaceDocument()
    # write some axes
    a3 = AxisDescriptor()
    a3.minimum = -1000
    a3.maximum = 0
    a3.default = 0
    a3.name = "ccc"
    doc.addAxis(a3)
    assert doc.normalizeLocation(dict(ccc=0)) == {'ccc': 0.0}
    assert doc.normalizeLocation(dict(ccc=1)) == {'ccc': 0.0}
    assert doc.normalizeLocation(dict(ccc=-1000)) == {'ccc': -1.0}
    assert doc.normalizeLocation(dict(ccc=-1001)) == {'ccc': -1.0}

    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.minimum, axis.default, axis.maximum))
    r.sort()
    assert r == [('ccc', -1.0, 0.0, 0.0)]

    doc = DesignSpaceDocument()
    # write some axes
    a3 = AxisDescriptor()
    a3.minimum = 2000
    a3.maximum = 3000
    a3.default = 2000
    a3.name = "ccc"
    doc.addAxis(a3)
    assert doc.normalizeLocation(dict(ccc=0)) == {'ccc': 0.0}
    assert doc.normalizeLocation(dict(ccc=1)) == {'ccc': 0.0}
    assert doc.normalizeLocation(dict(ccc=-1000)) == {'ccc': 0.0}
    assert doc.normalizeLocation(dict(ccc=-1001)) == {'ccc': 0.0}

    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.minimum, axis.default, axis.maximum))
    r.sort()
    assert r == [('ccc', 0.0, 0.0, 1.0)]

    doc = DesignSpaceDocument()
    # write some axes
    a4 = AxisDescriptor()
    a4.minimum = 0
    a4.maximum = 1000
    a4.default = 0
    a4.name = "ddd"
    a4.map = [(0, 100), (300, 500), (600, 500), (1000, 900)]
    doc.addAxis(a4)
    doc.normalize()
    r = []
    for axis in doc.axes:
        r.append((axis.name, axis.map))
    r.sort()
    assert r == [('ddd', [(0, 0.1), (300, 0.5), (600, 0.5), (1000, 0.9)])]