Пример #1
0
def getYearLabels(userOptions={}):
    global items
    cfg = {}
    options = {"y": 0.667}
    options.update(userOptions)
    yearCol = "year"
    if yearCol not in items[0]:
        # print("`dateColumn` needs to be set in config yml to support timelineTracks layout")
        return (None, None)

    years = [item[yearCol] for item in items]
    minYear = min(years)
    maxYear = max(years) + 1
    nUnit = 1.0 / (maxYear - minYear)

    labels = []
    for i in range(maxYear - minYear):
        x = 0.5
        y = options["y"]
        year = minYear + i
        z = mu.norm(year, (minYear, maxYear)) + nUnit * 0.5  # center
        labels += [
            round(x, PRECISION),
            round(y, PRECISION),
            round(z, PRECISION), year
        ]

    return (cfg, labels)
Пример #2
0
def getYearSounds(spriteData, userOptions={}):
    global items
    cfg = {
        "dimension": 2 # use z-axis
    }

    yearCol = "year"
    if yearCol not in items[0]:
        print("Could not find column %s in items, please add this column to metadata cols with 'type' = 'int'" % yearCol)
        sys.exit()

    sprites = spriteCount = None
    if spriteData is not None:
        sprites = spriteData["sprites"]
        spriteCount = len(sprites)

    years = [item[yearCol] for item in items]
    minYear = min(years)
    maxYear = max(years) + 1
    nUnit = 1.0 / (maxYear-minYear)

    sounds = []
    for i in range(maxYear-minYear):
        x = y = 0.5
        year = minYear + i
        z = mu.norm(year, (minYear, maxYear)) + nUnit*0.5 # center
        sounds += [round(x, PRECISION), round(y, PRECISION), round(z, PRECISION)]
        if sprites is not None:
            spriteIndex = mu.roundInt(1.0 * z * (spriteCount-1))
            sprite = sprites[spriteIndex]
            sounds += [sprite["start"], sprite["dur"]]

    return (cfg, sounds)
Пример #3
0
def getCountryLabels(userOptions={}):
    global items

    cfg = {}
    options = {"y": 0.5}
    options.update(userOptions)

    countryCol = "country"
    latCol = "lat"
    lonCol = "lon"
    if countryCol not in items[0]:
        print(
            "`countryColumn` needs to be set in config yml to support country labels; they will not show otherwise."
        )
        return (None, None)

    if latCol not in items[0] or lonCol not in items[0]:
        # print("`latitudeColumn` and `latitudeColumn` need to be set in config yml to support country labels; they will not show otherwise.")
        return (None, None)

    latRange = (90.0, -90.0)
    lonRange = (-180.0, 180.0)
    groups = lu.groupList(items, countryCol)  # group by country
    counts = [group["count"] for group in groups]
    minCount, maxCount = (min(counts), max(counts))
    labels = []
    for group in groups:
        firstItem = group["items"][0]
        label = firstItem[countryCol]
        lon = firstItem[lonCol]
        lat = firstItem[latCol]
        y = options["y"]
        x = 1.0 - mu.norm(lon, lonRange)
        z = 1.0 - mu.norm(lat, latRange)
        # HACK: offset z slightly to acommodate size of bar
        w = mu.norm(group["count"], (minCount, maxCount))
        w = mu.lerp((0.01, 1.0), w)
        # assume height is half the depth; divide by 6 for radius calculation (see geometry.js)
        radius = 0.5 / 6.0 * w + 0.005
        z = z - radius
        labels += [
            round(x, PRECISION),
            round(y, PRECISION),
            round(z, PRECISION), label
        ]

    return (cfg, labels)
def getGeographyBarsLayout(userOptions={}):
    global items
    cfg = {
        "layout": "bars"
    }

    latCol = "lat"
    lonCol = "lon"
    if latCol not in items[0] or lonCol not in items[0]:
        print("`latitudeColumn` and `latitudeColumn` need to be set in config yml to support geographyBars layout")
        return (False, False)

    # create unique key for lat lon
    for i, item in enumerate(items):
        items[i]["lonLatKey"] = (mu.roundInt(item[lonCol]*PRECISION), mu.roundInt(item[latCol]*PRECISION))

    latRange = (90.0, -90.0)
    lonRange = (-180.0, 180.0)
    dimensions = 3
    groups = lu.groupList(items, "lonLatKey") # group by lat lon
    counts = [group["count"] for group in groups]
    minCount, maxCount = (min(counts), max(counts))

    # assign position values
    values = np.zeros(len(items) * dimensions)
    for group in groups:
        y = mu.norm(group["count"], (minCount, maxCount))
        y = mu.lerp((0.01, 1.0), y)
        for item in group["items"]:
            itemIndex = item["index"]
            x = 1.0 - mu.norm(item[lonCol], lonRange)
            z = 1.0 - mu.norm(item[latCol], latRange)
            itemY = y
            # a bit of a hack to ensure highighted items are visible
            if itemHasStory(item):
                itemY = y + 1.05
            values[itemIndex*dimensions] = round(x, PRECISION)
            values[itemIndex*dimensions+1] = round(itemY, PRECISION)
            values[itemIndex*dimensions+2] = round(z, PRECISION)

    values = values.tolist()
    return (cfg, values)
Пример #5
0
def getCategoryTimelineHotspot(view, content):
    global items
    global sets

    year = None

    if "year" in content:
        year = content["year"]
    elif "visibleTimeRange" in content:
        year = mu.roundInt(mu.lerp(tuple(content["visibleTimeRange"]), 0.5))

    if year is None:
        print("Need to set year or time range in content")
        return None

    yearCol = "year"
    if yearCol not in items[0]:
        print(
            "Could not find column %s in items, please add this column to metadata cols with 'type' = 'int'"
            % yearCol)
        return None
    years = [item[yearCol] for item in items]
    minYear = min(years)
    maxYear = max(years) + 1
    nUnit = 1.0 / (maxYear - minYear)

    if "category" not in sets:
        print("Could not find column 'category' in sets")
        return None

    categories = sets["category"]
    if "category" not in content:
        print("Could not find column 'category' in content")
        return None
    if content["category"] not in categories:
        print("Could not find %s in categories" % content["category"])
        return None

    categoryCount = len(categories)
    categoryIndex = categories.index(content["category"])

    # place at in the center of the year
    z = mu.norm(year, (minYear, maxYear)) + nUnit * 0.5
    # place at center of region
    x = 1.0 - 1.0 * categoryIndex / (categoryCount - 1)
    # place at top of bounds
    y = 0.0
    return {
        "x": round(x, PRECISION),
        "y": round(y, PRECISION),
        "z": round(z, PRECISION)
    }
Пример #6
0
def getGeographyBarsLayout(userOptions={}):
    global items
    cfg = {"layout": "bars"}

    latCol = "lat"
    lonCol = "lon"
    if latCol not in items[0] or lonCol not in items[0]:
        print(
            "Could not find column (%s, %s) in items, please add these columns to metadata cols with 'type' = 'float'"
            % (lonCol, latCol))
        sys.exit()

    # create unique key for lat lon
    for i, item in enumerate(items):
        items[i]["lonLatKey"] = (mu.roundInt(item[lonCol] * PRECISION),
                                 mu.roundInt(item[latCol] * PRECISION))

    latRange = (90.0, -90.0)
    lonRange = (-180.0, 180.0)
    dimensions = 3
    groups = lu.groupList(items, "lonLatKey")  # group by lat lon
    counts = [group["count"] for group in groups]
    minCount, maxCount = (min(counts), max(counts))

    # assign position values
    values = np.zeros(len(items) * dimensions)
    for group in groups:
        y = mu.norm(group["count"], (minCount, maxCount))
        y = mu.lerp((0.01, 1.0), y)
        for item in group["items"]:
            itemIndex = item["index"]
            x = 1.0 - mu.norm(item[lonCol], lonRange)
            z = 1.0 - mu.norm(item[latCol], latRange)
            values[itemIndex * dimensions] = round(x, PRECISION)
            values[itemIndex * dimensions + 1] = round(y, PRECISION)
            values[itemIndex * dimensions + 2] = round(z, PRECISION)

    values = values.tolist()
    return (cfg, values)
def getTimelineTunnelLayout(userOptions={}):
    global items

    options = {
        "thickness": 0.2
    }
    options.update(userOptions)

    cfg = {}
    yearCol = "year"
    dimensions = 3

    if yearCol not in items[0]:
        print("`dateColumn` needs to be set in config yml to support timelineTunnel layout")
        return (False, False)

    years = [item[yearCol] for item in items]
    minYear = min(years)
    maxYear = max(years) + 1
    nUnit = 1.0 / (maxYear-minYear)
    groups = lu.groupList(items, yearCol) # group by year
    groups = sorted(groups, key=lambda group: group[yearCol])
    nThickness = options["thickness"]
    minDistance = 0.5-nThickness
    maxDistance = 0.5
    count = 0
    values = np.zeros(len(items) * dimensions)

    for i, group in enumerate(groups):
        minZ = mu.norm(group[yearCol], (minYear, maxYear))
        maxZ = minZ + nUnit
        for j, item in enumerate(group["items"]):
            index = item["index"]
            x = y = 0.5
            z = mu.randomUniform(minZ, maxZ, seed=count+5)
            # angle =  mu.randomUniform(0, 360, seed=count+7)
            angle =  mu.randomUniform(-240, 60, seed=count+7)

            distance =  mu.randomUniform(minDistance, maxDistance, seed=count+9)
            # ensure story items are visible
            if itemHasStory(item):
                distance = minDistance * 0.8
            x, y =  mu.translatePoint(x, y, distance, angle)
            values[index*dimensions] = round(x, PRECISION)
            values[index*dimensions+1] = round(y, PRECISION)
            values[index*dimensions+2] = round(z, PRECISION)
            count += 1
    values = values.tolist()
    return (cfg, values)
Пример #8
0
def getTimelineTunnelLayout(userOptions={}):
    global items

    options = {"thickness": 0.2}
    options.update(userOptions)

    cfg = {}
    yearCol = "year"
    dimensions = 3

    if yearCol not in items[0]:
        print(
            "Could not find column %s in items, please add this column to metadata cols with 'type' = 'int'"
            % yearCol)
        sys.exit()

    years = [item[yearCol] for item in items]
    minYear = min(years)
    maxYear = max(years) + 1
    nUnit = 1.0 / (maxYear - minYear)
    groups = lu.groupList(items, yearCol)  # group by year
    groups = sorted(groups, key=lambda group: group[yearCol])
    nThickness = options["thickness"]
    count = 0
    values = np.zeros(len(items) * dimensions)

    for i, group in enumerate(groups):
        minZ = mu.norm(group[yearCol], (minYear, maxYear))
        maxZ = minZ + nUnit
        for j, item in enumerate(group["items"]):
            index = item["index"]
            x = y = 0.5
            z = mu.randomUniform(minZ, maxZ, seed=count + 5)
            # angle =  mu.randomUniform(0, 360, seed=count+7)
            angle = mu.randomUniform(-240, 60, seed=count + 7)
            distance = mu.randomUniform(0.5 - nThickness, 0.5, seed=count + 9)
            x, y = mu.translatePoint(x, y, distance, angle)
            values[index * dimensions] = round(x, PRECISION)
            values[index * dimensions + 1] = round(y, PRECISION)
            values[index * dimensions + 2] = round(z, PRECISION)
            count += 1
    values = values.tolist()
    return (cfg, values)
Пример #9
0
def getCategoryYearLabels(userOptions={}):
    global items
    global categories

    cfg = {}
    options = {"y": 0.667, "labelEveryYearUnit": 5}
    options.update(userOptions)
    yearCol = "year"
    categoryCol = "category"
    if yearCol not in items[0]:
        # print("`dateColumn` needs to be set in config yml to support timelineTracks layout")
        return (None, None)

    if categoryCol not in items[0]:
        # print("`groupByColumn` needs to be set in config yml to support timelineTracks layout")
        return (None, None)

    categoryCount = len(categories)

    years = [item[yearCol] for item in items]
    minYear = min(years)
    maxYear = max(years) + 1
    nUnit = 1.0 / (maxYear - minYear)

    labels = []
    for i in range(maxYear - minYear):
        year = minYear + i
        if year % options["labelEveryYearUnit"] > 0:
            continue

        y = options["y"]
        z = mu.norm(year, (minYear, maxYear))  # beginning of year

        for j, category in enumerate(categories):
            x = 1.0 - 1.0 * j / (categoryCount - 1)
            labels += [
                round(x, PRECISION),
                round(y, PRECISION),
                round(z, PRECISION), category["text"]
            ]

    return (cfg, labels)
Пример #10
0
def getSphereCategoryTimelineLayout(userOptions={}):
    global items
    global sets
    cfg = {"layout": "spheres"}

    categoryCol = "category"
    yearCol = "year"
    if yearCol not in items[0]:
        print(
            "Could not find column %s in items, please add this column to metadata cols with 'type' = 'int'"
            % yearCol)
        sys.exit()
    if categoryCol not in sets:
        print(
            "Could not find column %s in sets, please add this column to metadata cols with 'asIndex' = true"
            % categoryCol)
        sys.exit()

    categorySet = sets[categoryCol]
    categoryCount = len(categorySet)
    dimensions = 3
    groups = lu.groupList(items, yearCol)  # group by year
    groups = sorted(groups, key=lambda group: group[yearCol])
    years = [item[yearCol] for item in items]
    minYear = min(years)
    maxYear = max(years) + 1
    nUnit = 1.0 / (maxYear - minYear)

    # determine category sphere count range
    minCount = 9999999999
    maxCount = 0
    for i, group in enumerate(groups):
        subgroups = lu.groupList(group["items"],
                                 categoryCol)  # group by category
        for subgroup in subgroups:
            minCount = min(minCount, subgroup["count"])
            maxCount = max(maxCount, subgroup["count"])
        groups[i]["categoryGroups"] = subgroups

    # assign position values
    values = np.zeros(len(items) * dimensions)
    for i, group in enumerate(groups):
        z = mu.norm(
            group[yearCol],
            (minYear,
             maxYear)) + nUnit * 0.5  # place spheres in the center of the year
        subgroups = group["categoryGroups"]
        subgroupLookup = lu.createLookup(subgroups, categoryCol)
        for j, category in enumerate(categorySet):
            x = 1.0 - 1.0 * j / (categoryCount - 1)
            categoryKey = str(j)
            if categoryKey in subgroupLookup:
                subgroup = subgroupLookup[categoryKey]
                y = mu.norm(subgroup["count"], (minCount, maxCount))
                y = mu.lerp((0.01, 1.0), y)
                for catItem in subgroup["items"]:
                    itemIndex = catItem["index"]
                    values[itemIndex * dimensions] = round(x, PRECISION)
                    values[itemIndex * dimensions + 1] = round(y, PRECISION)
                    values[itemIndex * dimensions + 2] = round(z, PRECISION)

    values = values.tolist()
    return (cfg, values)
def getSphereCategoryTimelineLayout(userOptions={}):
    global items
    global categories
    cfg = {
        "layout": "spheres"
    }

    categoryCol = "category"
    yearCol = "year"
    if yearCol not in items[0]:
        print("`dateColumn` needs to be set in config yml to support timelineTracks layout")
        return (False, False)

    if categoryCol not in items[0]:
        print("`groupByColumn` needs to be set in config yml to support timelineTracks layout")
        return (False, False)

    categoryCount = len(categories)
    dimensions = 3
    groups = lu.groupList(items, yearCol) # group by year
    groups = sorted(groups, key=lambda group: group[yearCol])
    years = [item[yearCol] for item in items]
    minYear = min(years)
    maxYear = max(years) + 1
    nUnit = 1.0 / (maxYear-minYear)

    # determine category sphere count range
    minCount = 9999999999
    maxCount = 0
    for i, group in enumerate(groups):
        subgroups = lu.groupList(group["items"], categoryCol) # group by category
        for subgroup in subgroups:
            minCount = min(minCount, subgroup["count"])
            maxCount = max(maxCount, subgroup["count"])
        groups[i]["categoryGroups"] = subgroups

    # assign position values
    values = np.zeros(len(items) * dimensions)
    for i, group in enumerate(groups):
        z = mu.norm(group[yearCol], (minYear, maxYear)) + nUnit*0.5 # place spheres in the center of the year
        subgroups = group["categoryGroups"]
        subgroupLookup = lu.createLookup(subgroups, categoryCol)
        for j, category in enumerate(categories):
            x = 1.0 - 1.0 * j / (categoryCount-1)
            categoryKey = category["text"]
            if categoryKey in subgroupLookup:
                subgroup = subgroupLookup[categoryKey]
                y = mu.norm(subgroup["count"], (minCount, maxCount))
                y = mu.lerp((0.01, 1.0), y)
                for catItem in subgroup["items"]:
                    itemIndex = catItem["index"]
                    cy = y
                    # a bit of a hack to ensure highighted items are visible
                    if itemHasStory(catItem):
                        cy = y + 1.25
                    values[itemIndex*dimensions] = round(x, PRECISION)
                    values[itemIndex*dimensions+1] = round(cy, PRECISION)
                    values[itemIndex*dimensions+2] = round(z, PRECISION)

    values = values.tolist()

    return (cfg, values)