Пример #1
0
    def name(self, **kwargs):
        """str: The attribute name """

        if "id" in kwargs and "attr" in kwargs:
            attr = fetch(kwargs["id"], kwargs["attr"])
        elif "dataset" in kwargs:
            attr = fetch(self.id(**kwargs), self.attr_type)
        else:
            attr = self.attr

        long_version = kwargs.get("long")

        if long_version:
            name = attr["name_long"]
        else:
            name = attr["display_name"] if "display_name" in attr else attr[
                "name"]
        text_only = kwargs.get("text_only", False)
        if not text_only and attr["id"] != self.attr["id"]:
            url_name = attr["url_name"] if "url_name" in attr and attr[
                "url_name"] else attr["id"]
            name = u"<a href='{}'>{}</a>".format(
                url_for("profile.profile",
                        attr_type=self.attr_type,
                        attr_id=url_name), name)
        return name
Пример #2
0
def get_img(attr_kind, attr_id, mode="thumb"):

    attr = fetch(attr_id, attr_kind)

    def formatImage(attr, attr_type):
        image_attr = False
        if "image_link" in attr and attr["image_link"]:
            image_attr = attr
        else:
            parents = [
                fetch(p["id"], attr_type)
                for p in get_parents(attr["id"], attr_type)
            ]
            for p in reversed(parents):
                if "image_link" in p and p["image_link"]:
                    image_attr = p
                    break
        if image_attr:
            return image_attr["id"]

    if attr_kind == "university" and not attr["image_link"]:
        if "msa" in attr and attr["msa"]:
            my_id = formatImage(fetch(attr["msa"], "geo"), "geo")
            attr_kind = "geo"
        else:
            my_id = formatImage(fetch("250000", "soc"), "soc")
            attr_kind = "soc"
    else:
        my_id = formatImage(attr, attr_kind)

    img_url = SPLASH_IMG_DIR.format(mode, attr_kind) + "{}.jpg".format(my_id)

    return redirect(img_url)
Пример #3
0
    def image(self, **kwargs):
        attr_id = kwargs.get("attr_id", self.id(**kwargs))
        attr = fetch(attr_id, self.attr_type)

        def formatImage(attr, attr_type):
            url = "/static/img/splash/{}/".format(attr_type)
            image_attr = False
            if "image_link" in attr and attr["image_link"]:
                image_attr = attr
            else:
                parents = [
                    fetch(p["id"], attr_type)
                    for p in get_parents(attr["id"], attr_type)
                ]
                for p in reversed(parents):
                    if "image_link" in p and p["image_link"]:
                        image_attr = p
                        break
            if image_attr:
                return {
                    "url": "{}{}.jpg".format(url, image_attr["id"]),
                    "link": image_attr["image_link"],
                    "author": image_attr["image_author"],
                    "meta": image_attr.get("image_meta", False)
                }

        if "image_link" in attr:
            if self.attr_type == "university" and attr["image_link"] == None:
                if "msa" in attr and attr["msa"] != None:
                    return formatImage(fetch(attr["msa"], "geo"), "geo")
                else:
                    return formatImage(fetch("250000", "soc"), "soc")
            return formatImage(attr, self.attr_type)
        return None
Пример #4
0
    def sub(self, **kwargs):
        substitution = False
        key = kwargs.pop("key", "name")
        attr_id = self.id(**kwargs)
        attr_type = kwargs.get("attr_type", self.attr_type)

        if kwargs.get("dataset", False):
            if self.attr["id"] != attr_id:
                substitution = fetch(attr_id, self.attr_type)
        else:
            kwargs["data_only"] = True
            attrs = kwargs.pop("attrs", attr_type)
            subs = self.top(**kwargs)
            if "subs" in subs:
                subs = subs["subs"]
                if attr_type in subs and subs[attr_type] != attr_id:
                    substitution = fetch(subs[attr_type], attrs)

        if key == "name":
            if substitution:
                return u"Based on data from {}".format(substitution[key])
            else:
                return ""
        else:
            if substitution:
                return substitution[key]
            else:
                if "_iocode" in attr_type:
                    return fetch(attr_id, attr_type)[key]
                return self.attr[key]
Пример #5
0
    def sub(self, **kwargs):
        substitution = False
        key = kwargs.pop("key", "name")
        attr_id = self.id(**kwargs)
        attr_type = kwargs.get("attr_type", self.attr_type)

        if kwargs.get("dataset", False):
            if self.attr["id"] != attr_id:
                substitution = fetch(attr_id, self.attr_type)
        else:
            kwargs["data_only"] = True
            attrs = kwargs.pop("attrs", attr_type)
            subs = self.top(**kwargs)
            if "subs" in subs:
                subs = subs["subs"]
                if attr_type in subs and subs[attr_type] != attr_id:
                    substitution = fetch(subs[attr_type], attrs)

        if key == "name":
            if substitution:
                return u"Based on data from {}".format(substitution[key])
            else:
                return ""
        else:
            if substitution:
                return substitution[key]
            else:
                if "_iocode" in attr_type:
                    return fetch(attr_id, attr_type)[key]
                return self.attr[key]
Пример #6
0
    def __init__(self, attr_id, attr_type):
        self._id = attr_id
        self.attr_type = attr_type
        self.attr = {"id": "01000US", "name": "United States"}

        # read and update
        file_obj = self.open_file(attr_id)
        story_conf = yaml.load(file_obj)
        self.title = story_conf['title'] if 'title' in story_conf else ''
        self.description = story_conf['description'] if 'description' in story_conf else ''
        self.footnotes = story_conf['footnotes'] if 'footnotes' in story_conf else None
        self.date = story_conf['date'] if 'date' in story_conf else ''
        if not self.date:
            self.date = date_from_filename(attr_id)
        self._date_obj = parser.parse(self.date)
        self.date = self._date_obj.strftime("%B %-d, %Y")
        self.authors = story_conf['authors'] if 'authors' in story_conf else []
        self.background_image = story_conf['background_image'] if 'background_image' in story_conf else None

        if self.background_image and "splash" in self.background_image:
            image_array = self.background_image.split("/")
            attr_type = image_array[4]
            attr_id = image_array[5].split(".")[0]
            attr = fetch(attr_id, attr_type)
            self.attr = fetch(attr_id, attr_type)

        tmp_obj = {"topics": story_conf['topics']}
        for i, t in enumerate(tmp_obj["topics"]):
            if "viz_url" in t:
                t["viz"] = Story.grab(t["viz_url"])
            if "topic_url" in t:
                tmp_obj["topics"][i] = Story.grab(t["topic_url"], True)
        section = Section(self.load_yaml(tmp_obj), self)
        self.topics = section.topics
Пример #7
0
def get_img(attr_kind, attr_id, mode="thumb"):
    gobj = fetch(attr_id, attr_kind)
    my_id = gobj['id']
    if 'image_link' not in gobj or not gobj['image_link']:
        parents = get_parents(attr_id, attr_kind)
        for p in reversed(parents):
            p = fetch(p["id"], attr_kind)
            if "image_link" in p and p['image_link']:
                my_id = p['id']
                break
    static_root_url = SPLASH_IMG_DIR.format(mode, attr_kind)
    img_url = static_root_url.format(mode, attr_kind) + "{}.jpg".format(my_id)
    return redirect(img_url)
Пример #8
0
def get_img(attr_kind, attr_id, mode="thumb"):
    gobj = fetch(attr_id, attr_kind)
    my_id = gobj['id']
    if 'image_link' not in gobj or not gobj['image_link']:
        parents = get_parents(attr_id, attr_kind)
        for p in reversed(parents):
            p = fetch(p["id"], attr_kind)
            if "image_link" in p and p['image_link']:
                my_id = p['id']
                break
    static_root_url = SPLASH_IMG_DIR.format(mode, attr_kind)
    img_url = static_root_url.format(mode, attr_kind) + "{}.jpg".format(my_id)
    return redirect(img_url)
Пример #9
0
    def sub(self, **kwargs):
        substitution = False
        key = kwargs.pop("key", "name")
        attr_id = self.id(**kwargs)
        attr_type = kwargs.get("attr_type", self.attr_type)
        original = fetch(self.attr["id"], self.attr_type)

        if kwargs.get("dataset", False):
            if self.attr["id"] != attr_id:
                substitution = fetch(attr_id, self.attr_type)
        else:
            kwargs["data_only"] = True
            attrs = kwargs.pop("attrs", attr_type)
            subs = self.top(**kwargs)
            if "subs" in subs:
                subs = subs["subs"]
                if attr_type in subs and subs[attr_type] != attr_id:
                    substitution = fetch(subs[attr_type], attrs)

        if key == "name":
            if substitution:
                if original:
                    if self.attr_type in SUMLEVELS and attr_type in SUMLEVELS:
                        if "sumlevel" in original:
                            origLevel = SUMLEVELS[self.attr_type][original["sumlevel"]]["label"]
                        elif isinstance(original["level"], basestring):
                            origLevel = "{} {} Group".format(original["level"].title(), DICTIONARY[self.attr_type])
                        else:
                            level = str((original["level"] + 1) * 2) if self.attr_type == "cip" else str(original["level"])
                            origLevel = SUMLEVELS[self.attr_type][level]["label"]
                        if "sumlevel" in substitution:
                            subLevel = SUMLEVELS[attr_type][substitution["sumlevel"]]["label"]
                        elif isinstance(substitution["level"], basestring):
                            subLevel = "{} {} Group".format(substitution["level"].title(), DICTIONARY[attr_type])
                        else:
                            level = str((substitution["level"] + 1) * 2) if attr_type == "cip" else str(substitution["level"])
                            subLevel = SUMLEVELS[attr_type][level]["label"]
                        return u"The closest comparable data for the {0}{4}{1} is from the {2}{4}{3}.".format(origLevel, original["display_name"] if "display_name" in original else original[key], subLevel, substitution["display_name"] if "display_name" in substitution else substitution[key], " of " if attr_type == "geo" else " ")
                    else:
                        return u"The closest comparable data for {} is from {}.".format(original["display_name"] if "display_name" in original else original[key], substitution["display_name"] if "display_name" in substitution else substitution[key])
                else:
                    return u"Using data from {}.".format(substitution["display_name"] if "display_name" in substitution else substitution[key])
            else:
                return ""
        else:
            if substitution:
                return substitution[key]
            else:
                if "_iocode" in attr_type:
                    return fetch(attr_id, attr_type)[key]
                return self.attr[key]
Пример #10
0
def render_col(my_data, headers, col, url=False, dataset=False):
    value = my_data[headers.index(col)]
    if not value:
        return {"raw": None, "pretty": "N/A", "name": "N/A"}

    attr_type = col
    if "_iocode" in col:
        attr_type = "iocode"

    if dataset:
        alt_type = "{}_{}".format(dataset, attr_type)
        if alt_type in attr_cache:
            attr_type = alt_type

    if attr_type not in attr_cache:
        if isinstance(value, basestring):
            return_value = value
        else:
            # do simple number formating
            return_value = num_format(value, col)
        name = return_value
    else:
        # lookup the attr object and get the name
        attr = fetch(value, attr_type)
        url_name = attr["url_name"] if "url_name" in attr and attr["url_name"] else attr["id"]
        attr = attr["display_name"] if "display_name" in attr else attr["name"]
        name = attr
        if attr_type in PROFILES or attr_type in CROSSWALKS:
            attr = u"<a href='{}'>{}</a>".format(url_for("profile.profile", attr_type=attr_type, attr_id=url_name), attr)
        return_value = attr

    if url:
        return_value = u"<span class='stat-span' data-url='{}'>{}</span>".format(url, return_value)
    return {"raw": value, "pretty": return_value, "name": name}
Пример #11
0
def render_col(my_data, headers, col, url=False, dataset=False):
    value = my_data[headers.index(col)]
    if not value:
        return {"raw": None, "pretty": "N/A", "name": "N/A"}

    attr_type = col
    if "_iocode" in col:
        attr_type = "iocode"

    if dataset:
        alt_type = "{}_{}".format(dataset, attr_type)
        if alt_type in attr_cache:
            attr_type = alt_type

    if attr_type not in attr_cache:
        if isinstance(value, basestring):
            return_value = value
        else:
            # do simple number formating
            return_value = num_format(value, col)
        name = return_value
    else:
        # lookup the attr object and get the name
        attr = fetch(value, attr_type)
        url_name = attr["url_name"] if "url_name" in attr and attr["url_name"] else attr["id"]
        attr = attr["display_name"] if "display_name" in attr else attr["name"]
        name = attr
        if attr_type in PROFILES or attr_type in CROSSWALKS:
            attr = u"<a href='{}'>{}</a>".format(url_for("profile.profile", attr_type=attr_type, attr_id=url_name), attr)
        return_value = attr

    if url:
        return_value = u"<span class='stat-span' data-url='{}'>{}</span>".format(url, return_value)
    return {"raw": value, "pretty": return_value, "name": name}
Пример #12
0
    def sumlevel(self, **kwargs):
        """str: A string representation of the depth type. """
        attr_type = kwargs.get("attr_type", self.attr_type)
        attr_id = kwargs.get("attr_id", self.id(**kwargs))
        requested_prefix = kwargs.get("prefix", False)

        if attr_type == "geo":
            if requested_prefix:
                name = SUMLEVELS["geo"][requested_prefix]["sumlevel"]
            else:
                prefix = attr_id[:3]
                if kwargs.get("dataset", False) == "chr" and prefix not in ["010", "040"]:
                    prefix = "040"
                if kwargs.get("child", False) and "children" in SUMLEVELS["geo"][prefix]:
                    prefix = SUMLEVELS["geo"][prefix]["children"]
                name = SUMLEVELS["geo"][prefix]["sumlevel"]

            if "plural" in kwargs:
                name = u"{}ies".format(name[:-1]) if name[-1] == "y" else u"{}s".format(name)

            return name

        elif attr_type == "cip":
            return str(len(attr_id))

        else:
            return str(fetch(attr_id, attr_type)["level"])
Пример #13
0
    def sumlevel(self, **kwargs):
        """str: A string representation of the depth type. """
        attr_type = kwargs.get("attr_type", self.attr_type)
        attr_id = kwargs.get("attr_id", self.id(**kwargs))
        requested_prefix = kwargs.get("prefix", False)

        if attr_type == "geo":
            if requested_prefix:
                name = SUMLEVELS["geo"][requested_prefix]["sumlevel"]
            else:
                prefix = attr_id[:3]
                if kwargs.get("dataset", False) == "chr" and prefix not in ["010", "040"]:
                    prefix = "040"
                if kwargs.get("child", False) and "children" in SUMLEVELS["geo"][prefix]:
                    prefix = SUMLEVELS["geo"][prefix]["children"]
                name = SUMLEVELS["geo"][prefix]["sumlevel"]

            if "plural" in kwargs:
                name = u"{}ies".format(name[:-1]) if name[-1] == "y" else u"{}s".format(name)

            return name

        elif attr_type == "cip":
            return str(len(attr_id))

        else:
            return str(fetch(attr_id, attr_type)["level"])
Пример #14
0
def embed_view(attr_type, attr_id, section, topic):
    viz_only = request.args.get("viz", False)
    if not attr_type in PROFILES:
        abort(404)

    g.page_class = "{} embed".format(attr_type)

    topics = topic.split(",")
    required_namespaces = Profile.compute_namespaces(attr_type, section,
                                                     topics)
    p = Profile(attr_id, attr_type, required_namespaces)
    section = p.section_by_topic(section, topics)

    if not section or not section.topics:
        abort(404)

    if "description" in section.topics[0]:
        section.meta = section.topics[0]["description"][0]
    else:
        section.meta = ""

    for t in section.topics:
        if viz_only:
            if "description" in t:
                del t["description"]
            if "stat" in t:
                del t["stat"]
        if "category" in t:
            del t["category"]

    g.compare = request.args.get("compare", False)
    if g.compare:
        g.compare = fetch(g.compare, attr_type)

    return render_template("profile/embed.html", profile=p, section=section)
Пример #15
0
def embed_view(attr_type, attr_id, section, topic):
    viz_only = request.args.get("viz", False)
    if not attr_type in PROFILES:
        abort(404)

    g.page_class = "{} embed".format(attr_type)

    topics = topic.split(",")
    required_namespaces = Profile.compute_namespaces(attr_type, section, topics)
    p = Profile(attr_id, attr_type, required_namespaces)
    section = p.section_by_topic(section, topics)

    if not section or not section.topics:
        abort(404)

    for t in section.topics:
        if viz_only:
            if "description" in t:
                del t["description"]
            if "stat" in t:
                del t["stat"]
        if "category" in t:
            del t["category"]

    g.compare = request.args.get("compare", False)
    if g.compare:
        g.compare = fetch(g.compare, attr_type)

    return render_template("profile/embed.html", profile = p, section = section)
Пример #16
0
def home():
    g.page_type = "home"

    feed = [copy.copy(f) for f in HOMEFEED]
    for box in feed:
        if "featured" not in box:
            box["featured"] = False
        if "/profile/" in box["link"]:
            attr_type = box["link"].split("/")[2]
            attr_id = box["link"].split("/")[3]
            attr = fetch(attr_id, attr_type)
            box["subtitle"] = attr[
                "display_name"] if "display_name" in attr else attr["name"]
            section = [
                s for s in profile_cache[attr_type]["sections"]
                if s["anchor"] == box["section"]
            ][0]
            box["section"] = {
                "title": section["title"],
                "icon": "/static/img/icons/{}.svg".format(box["section"])
            }
            sumlevel = attr["sumlevel"] if "sumlevel" in attr else attr["level"]
            if attr_type == "cip":
                sumlevel = (sumlevel + 1) * 2
            sumlevel = str(sumlevel)
            sumlevel = SUMLEVELS[attr_type][sumlevel]
            sumlevel = sumlevel[
                "shortlabel"] if "shortlabel" in sumlevel else sumlevel["label"]
            box["type"] = {
                "icon": "/static/img/icons/{}.svg".format(attr_type),
                "title": "Profile",
                "type": TYPEMAP[attr_type],
                "depth": sumlevel.replace("_", " ")
            }
            img_type = "feature" if box["featured"] else "thumb"
            box["image"] = "/static/img/{}/{}".format(img_type,
                                                      attr["image_path"])
        elif "/story/" in box["link"]:
            box["type"] = {
                "icon": "/static/img/icons/about.svg",
                "title": TYPEMAP["story"],
                "type": "story"
            }
            story = [
                s for s in story_cache
                if s["story_id"] == box["link"].split("/")[2]
            ][0]
            box["image"] = story["background_image"]
            box["title"] = story["title"]
            box["subtitle"] = story["description"]
            box["author"] = "By {}".format(story["authors"][0]["name"])
        elif "/map/" in box["link"]:
            box["type"] = {
                "icon": "/static/img/icons/demographics.svg",
                "title": TYPEMAP["map"],
                "type": "map"
            }
            box["viz"] = "geo_map"

    return render_template("general/home.html", feed=feed)
Пример #17
0
 def attribute(self, **kwargs):
     key = kwargs.get("key")
     val = self.attr[key]
     if key == "opeid8":
         val = val[:-2]
     attr = kwargs.get("attr", False)
     if attr:
         val = self.make_links([fetch(val, attr)], attr)
     return val
Пример #18
0
    def name(self, **kwargs):
        """str: The attribute name """

        if "id" in kwargs and "attr" in kwargs:
            attr = fetch(kwargs["id"], kwargs["attr"])
        elif "dataset" in kwargs:
            attr = fetch(self.id(**kwargs), self.attr_type)
        else:
            attr = self.attr

        long_version = kwargs.get("long")

        if long_version:
            name = attr["name_long"]
        else:
            name = attr["display_name"] if "display_name" in attr else attr["name"]
        text_only = kwargs.get("text_only", False)
        if not text_only and attr["id"] != self.attr["id"]:
            url_name = attr["url_name"] if "url_name" in attr and attr["url_name"] else attr["id"]
            name = u"<a href='{}'>{}</a>".format(url_for("profile.profile", attr_type=self.attr_type, attr_id=url_name), name)
        return name
Пример #19
0
def home():
    g.page_type = "home"

    feed = [copy.copy(f) for f in HOMEFEED]
    for box in feed:
        if "featured" not in box:
            box["featured"] = False
        if "/profile/" in box["link"]:
            attr_type = box["link"].split("/")[2]
            attr_id = box["link"].split("/")[3]
            attr = fetch(attr_id, attr_type)
            box["subtitle"] = attr["display_name"] if "display_name" in attr else attr["name"]
            section = [s for s in profile_cache[attr_type]["sections"] if s["anchor"] == box["section"]][0]
            box["section"] = {
                "title": section["title"],
                "icon": "/static/img/icons/{}.svg".format(box["section"])
            }
            sumlevel = attr["sumlevel"] if "sumlevel" in attr else attr["level"]
            if attr_type == "cip":
                sumlevel = (sumlevel + 1) * 2
            sumlevel = str(sumlevel)
            sumlevel = SUMLEVELS[attr_type][sumlevel]
            sumlevel = sumlevel["shortlabel"] if "shortlabel" in sumlevel else sumlevel["label"]
            box["type"] = {
                "icon": "/static/img/icons/{}.svg".format(attr_type),
                "title": "Profile",
                "type": TYPEMAP[attr_type],
                "depth": sumlevel.replace("_"," ")
            }
            img_type = "feature" if box["featured"] else "thumb"
            box["image"] = "/static/img/{}/{}".format(img_type, attr["image_path"])
        elif "/story/" in box["link"]:
            box["type"] = {
                "icon": "/static/img/icons/about.svg",
                "title": TYPEMAP["story"],
                "type": "story"
            }
            story = [s for s in story_cache if s["story_id"] == box["link"].split("/")[2]][0]
            box["image"] = story["background_image"]
            box["title"] = story["title"]
            box["subtitle"] = story["description"]
            box["author"] = "By {}".format(story["authors"][0]["name"])
        elif "/map/" in box["link"]:
            box["type"] = {
                "icon": "/static/img/icons/demographics.svg",
                "title": TYPEMAP["map"],
                "type": "map"
            }
            box["viz"] = "geo_map"

    return render_template("general/home.html", feed=feed)
Пример #20
0
    def nearby(self, **kwargs):

        if self.attr_type != "university":
            return []

        attr_id = self.id(**kwargs)
        ids_only = kwargs.get("ids", False)
        endpoint = kwargs.get("endpoint", "nearby")
        url = "{}/attrs/{}/university/{}".format(API, endpoint, attr_id)

        try:
            results = requests.get(url).json()
            if "error" in results:
                results = requests.get(url.replace(endpoint, "nearby")).json()
            results = [r for r in datafold(results) if r["id"] != attr_id]

            sector = kwargs.get("sector", False)
            if sector:
                results = [fetch(r["id"], "university") for r in results]
                if sector == "private":
                    results = [
                        r for r in results
                        if str(r["sector"]) in ["2", "3", "5", "6", "8", "9"]
                    ]
                else:
                    results = [
                        r for r in results if str(r["sector"]) not in
                        ["2", "3", "5", "6", "8", "9"]
                    ]

            if ids_only:
                return ",".join([r["id"] for r in results])
            return [fetch(r["id"], "university") for r in results]
        except ValueError:
            app.logger.info("STAT ERROR: {}".format(url))
            if ids_only:
                return ""
            return []
Пример #21
0
    def __init__(self, attr_id, attr_type, required_namespaces=None):
        """Initializes a new Profile class.

        Args:
            attr_id (str): The ID of the selected attribute
            attr_type (str): The attribute type of the profile.

        """

        # set attr (using the fetch function) and attr_type
        self.attr = fetch(attr_id, attr_type)
        self.attr_type = attr_type
        self.variables = self.load_vars(required_namespaces)
        self.splash = Section(self.load_yaml(self.open_file("splash")), self)
Пример #22
0
    def __init__(self, attr_id, attr_type, required_namespaces=None):
        """Initializes a new Profile class.

        Args:
            attr_id (str): The ID of the selected attribute
            attr_type (str): The attribute type of the profile.

        """

        # set attr (using the fetch function) and attr_type
        self.attr = fetch(attr_id, attr_type)
        self.attr_type = attr_type
        self.variables = self.load_vars(required_namespaces)
        self.splash = Section(self.load_yaml(self.open_file("splash")), self)
Пример #23
0
 def carnegie(self, **kwargs):
     parent = kwargs.get("parent", "carnegie_parent")
     carnegie_id = self.attr[parent]
     if not carnegie_id:
         carnegie_id = self.id(**kwargs)
     key = kwargs.get("key", "id")
     if key == "id":
         return carnegie_id
     else:
         carnegie_attr = fetch(carnegie_id, "university")
         if key == "name":
             return self.make_links([carnegie_attr])
         else:
             return carnegie_attr[key]
Пример #24
0
def profile(attr_type, attr_id):

    if "_iocode" in attr_type:
        attr_type = "iocode"

    allowed_type = attr_type in PROFILES or attr_type in CROSSWALKS
    allowed_id = attr_type in attr_cache and attr_id in attr_cache[attr_type]
    if not allowed_type or not allowed_id:
        abort(404)
    if attr_type in CROSSWALKS:
        attr = attr_cache[attr_type][attr_id]

        crosswalks = acs_crosswalk(attr_type, attr_id)
        crosswalk_map = {
            "acs_occ": "soc",
            "acs_ind": "naics",
            "iocode": "naics"
        }
        crosswalk_labels = {
            "acs_occ": "ACS Occupation Code",
            "acs_ind": "ACS Industry Code",
            "iocode": "BEA I/O Code"
        }
        if len(crosswalks) > 1:
            g.page_type = "redirect"
            attr["type"] = crosswalk_labels[attr_type]
            return render_template("profile/redirect.html",
                                   attr=attr,
                                   crosswalks=crosswalks,
                                   crosswalk_type=crosswalk_map[attr_type])
        return redirect(
            url_for('.profile',
                    attr_type=crosswalk_map[attr_type],
                    attr_id=crosswalks[0]["id"]))

    g.page_class = attr_type

    # pass id and type to Profile class
    p = profile_fetch(attr_type, attr_id)

    if request.args.get("json", False):
        return json.dumps(p, cls=MyEncoder)

    g.compare = request.args.get("compare", False)
    if g.compare:
        g.compare = fetch(g.compare, attr_type)

    # render the profile template and pass the profile to jinja
    return render_template("profile/index.html", profile=p)
Пример #25
0
 def formatImage(attr, attr_type):
     image_attr = False
     if "image_link" in attr and attr["image_link"]:
         image_attr = attr
     else:
         parents = [
             fetch(p["id"], attr_type)
             for p in get_parents(attr["id"], attr_type)
         ]
         for p in reversed(parents):
             if "image_link" in p and p["image_link"]:
                 image_attr = p
                 break
     if image_attr:
         return image_attr["id"]
Пример #26
0
 def image(self):
     if "image_link" in self.attr:
         url = "/static/img/splash/{}/".format(self.attr_type)
         image_attr = False
         if self.attr["image_link"]:
             image_attr = self.attr
         else:
             parents = [fetch(p["id"], self.attr_type) for p in get_parents(self.attr["id"], self.attr_type)]
             for p in reversed(parents):
                 if p["image_link"]:
                     image_attr = p
                     break
         if image_attr:
             return {
                 "url": "{}{}.jpg".format(url, image_attr["id"]),
                 "link": image_attr["image_link"],
                 "author": image_attr["image_author"],
                 "meta": image_attr.get("image_meta", False)
                 }
     return None
Пример #27
0
 def image(self):
     if "image_link" in self.attr:
         url = "/static/img/splash/{}/".format(self.attr_type)
         image_attr = False
         if self.attr["image_link"]:
             image_attr = self.attr
         else:
             parents = [fetch(p["id"], self.attr_type) for p in get_parents(self.attr["id"], self.attr_type)]
             for p in reversed(parents):
                 if p["image_link"]:
                     image_attr = p
                     break
         if image_attr:
             return {
                 "url": "{}{}.jpg".format(url, image_attr["id"]),
                 "link": image_attr["image_link"],
                 "author": image_attr["image_author"],
                 "meta": image_attr.get("image_meta", False)
                 }
     return None
Пример #28
0
 def formatImage(attr, attr_type):
     url = "/static/img/splash/{}/".format(attr_type)
     image_attr = False
     if "image_link" in attr and attr["image_link"]:
         image_attr = attr
     else:
         parents = [
             fetch(p["id"], attr_type)
             for p in get_parents(attr["id"], attr_type)
         ]
         for p in reversed(parents):
             if "image_link" in p and p["image_link"]:
                 image_attr = p
                 break
     if image_attr:
         return {
             "url": "{}{}.jpg".format(url, image_attr["id"]),
             "link": image_attr["image_link"],
             "author": image_attr["image_author"],
             "meta": image_attr.get("image_meta", False)
         }
Пример #29
0
 def default_degree(self, **kwargs):
     if not self.common_degree:
         url = "{}/api?university={}&show=degree&required=grads_total&order=grads_total&sort=desc".format(
             API, self.attr["id"])
         try:
             results = requests.get(url).json()
             if "error" in results:
                 self.common_degree = "5"
             else:
                 results = [r for r in datafold(results)]
                 bachelor = [r for r in results if r["degree"] == "5"]
                 if len(results) == 0 or len(bachelor) > 0:
                     self.common_degree = "5"
                 else:
                     self.common_degree = results[0]["degree"]
         except ValueError:
             self.common_degree = "5"
     key = kwargs.get("key", False)
     if key:
         return fetch(self.common_degree, "degree")[key]
     return self.common_degree
Пример #30
0
def tileProfiles(profiles):
    for i, page in enumerate(profiles):
        show, slug = page.split("/")
        attr = fetch(slug, show)
        if show == "university":
            attr_id = attr["id"] if attr["image_link"] else attr["msa"]
            attr_type = "university" if attr["image_link"] else "geo"
        else:
            attr_id = attr["id"]
            attr_type = show
        profiles[i] = {
            "image":
            "/search/{}/{}/img".format(attr_type, attr_id),
            "link":
            "/profile/{}".format(page),
            "title":
            attr["display_name"] if "display_name" in attr else attr["name"],
            "new":
            1 if show == "university" else 0
        }
    return profiles
Пример #31
0
def tileProfiles(profiles):
    for i, page in enumerate(profiles):
        show, slug = page.split("/")
        attr = fetch(slug, show)
        attr_id = attr["id"]
        sumlevel = attr["sumlevel"] if "sumlevel" in attr else attr["level"]
        profiles[i] = {
            "image":
            "/search/{}/{}/img".format(show, attr_id),
            "link":
            "/profile/{}".format(page),
            "title":
            attr["display_name"] if "display_name" in attr else attr["name"],
            # "subtitle": SUMLEVELS[show][str(sumlevel)]["label"],
            "type": {
                "icon": "/static/img/icons/{}.svg".format(show),
                "title": SUMLEVELS[show][str(sumlevel)]["label"],
                "type": TYPEMAP[show],
                "depth": "{}".format(sumlevel).replace("_", " ")
            }
        }
    return profiles
Пример #32
0
def tileAPI(column):
    url = "{}{}&limit={}".format(API, column["url"], TILEMAX)
    r = requests.get(url).json()

    show = re.findall(r"show=([a-z_0-9]+)", url)[0]
    order = re.findall(r"order=([a-z_0-9]+)", url)[0]
    sumlevel = re.findall(r"sumlevel=([a-z_0-9]+)", url)[0]
    if show == "geo":
        sumlevel = sumlevelMap[sumlevel]
    data = datafold(r)

    for d in data:
        attr_id = d[show]
        attr = fetch(attr_id, show)
        slug = attr["url_name"] if attr["url_name"] else attr_id
        d["title"] = attr["display_name"] if "display_name" in attr else attr[
            "name"]
        # d["subtitle"] = "{}: {}".format(DICTIONARY[order], num_format(d[order], order))
        d["subtitle"] = SUMLEVELS[show][sumlevel]["label"]
        d["link"] = "/profile/{}/{}".format(show, slug)
        d["image"] = "/search/{}/{}/img".format(show, attr_id)
        d["type"] = {
            "icon": "/static/img/icons/{}.svg".format(show),
            "title": SUMLEVELS[show][sumlevel]["label"],
            "type": TYPEMAP[show],
            "depth": "{}".format(sumlevel).replace("_", " ")
        }

    column["icon"] = "/static/img/icons/{}.svg".format(show)
    column["data"] = data
    column["source"] = r["source"]
    if show in footMap:
        column["footer"] = {
            "link": "/search/?kind={}".format(show),
            "text": "{} more".format(num_format(footMap[show]))
        }
    return column
Пример #33
0
def profile(attr_type, attr_id):

    if "_iocode" in attr_type:
        attr_type = "iocode"

    allowed_type = attr_type in PROFILES or attr_type in CROSSWALKS
    allowed_id = attr_type in attr_cache and attr_id in attr_cache[attr_type]
    if not allowed_type or not allowed_id:
        abort(404)
    if attr_type in CROSSWALKS:
        attr = attr_cache[attr_type][attr_id]

        crosswalks = acs_crosswalk(attr_type, attr_id)
        crosswalk_map = {"acs_occ": "soc", "acs_ind": "naics", "iocode": "naics"}
        crosswalk_labels = {"acs_occ": "ACS Occupation Code", "acs_ind": "ACS Industry Code", "iocode": "BEA I/O Code"}
        if len(crosswalks) > 1:
            g.page_type = "redirect"
            attr["type"] = crosswalk_labels[attr_type]
            return render_template("profile/redirect.html", attr=attr, crosswalks=crosswalks, crosswalk_type=crosswalk_map[attr_type])
        return redirect(url_for('.profile', attr_type=crosswalk_map[attr_type], attr_id=crosswalks[0]["id"]))

    g.page_class = attr_type


    # pass id and type to Profile class
    p = profile_fetch(attr_type, attr_id)

    if request.args.get("json", False):
        return json.dumps(p, cls=MyEncoder)

    g.compare = request.args.get("compare", False)
    if g.compare:
        g.compare = fetch(g.compare, attr_type)

    # render the profile template and pass the profile to jinja
    return render_template("profile/index.html", profile = p)
Пример #34
0
def stat(params, col="name", dataset=False, data_only=False, moe=False, truncate=0):

    # convert request arguments into a url query string
    rank = int(params.pop("rank", "1"))
    if "limit" in params:
        limit = int(params["limit"])
    else:
        limit = 1
    if rank > 1 and limit == 1:
        params["limit"] = rank
    query = RequestEncodingMixin._encode_params(params)
    url = "{}/api?{}".format(API, query)
    stat_url = "{}?{}&col={}&dataset={}&moe={}&rank={}".format(url_for("profile.statView"), query, col, dataset, moe, str(rank))

    try:
        r = requests.get(url).json()
    except ValueError:
        app.logger.info("STAT ERROR: {}".format(url))
        return {
            "url": stat_url,
            "value": "N/A"
        }

    if data_only:
        return r
    else:
        r = datafold(r)

    if dataset == "stat":
        if isinstance(r[0][col], list):
            r = [{params["show"]:x} for x in r[0][col]]
            col = "name"

    if len(r) == 0:
        return {
            "url": stat_url,
            "value": "N/A"
        }

    # if the output key is 'name', fetch attributes for each return and create an array of 'name' values
    # else create an array of the output key for each returned datapoint
    vals = []
    show = params["show"].split(",")[-1]
    if col == "ratio":
        if limit == 1:
            vals = sorted([v for k, v in r[0].iteritems() if k in params["required"].split(",")], reverse=True)
            if vals[0] == 0 or vals[1] == 0:
                val = 0
            else:
                val = vals[0]/vals[1]
            return num_format(val, key=col)
        else:
            denom = max([d[params["order"]] for d in r[1:]])
            return num_format(r[0][params["order"]]/denom, key=col)


    if col == "diff":
        return num_format(r[0][params["order"]] - r[1][params["order"]], key=col)

    if col in COLMAP or "-" in col:
        vals = datapivot(r, col.split("-"), sort="desc")

        vals = [v for v in vals[rank - 1:limit]]

        if moe:
            top = [v["moe"] for v in vals]
        else:
            top = [v["name"] for v in vals]
            vals = [v["value"] for v in vals]

    else:
        if rank > 1:
            r = r[rank-1:]

        if moe:
            top = [d[moe] for d in r]
        elif col == "name":
            if dataset in ["acs", "pums"]:
                attr = "{}_{}".format(dataset, show)
            else:
                attr = show

            top = [fetch(d[show], attr) for d in r]

            if attr in PROFILES or attr in CROSSWALKS:
                top = [(t["id"], t["display_name"] if "display_name" in t else t[col], t["url_name"] if "url_name" in t and t["url_name"] else t["id"]) for t in top]
                top = [u"<a href='{}'>{}</a>".format(url_for("profile.profile", attr_type=attr, attr_id=t[2]), t[1]) if attr != "geo" or t[0][:3] != "140" else t[1] for t in top]
            else:
                top = [t["display_name"] if "display_name" in t else t[col] for t in top]

        elif col == "id":
            top = [d[show] for d in r]
        else:
            top = [d[col] for d in r]

    if col != "id":
        if moe:
            col = moe
        top = [num_format(t, col) if isinstance(t, (int, float)) else t for t in top]

    # coerce all values to strings
    top = [u"{}".format(t) if t != "" else u"N/A" for t in top]

    if col == "id":
        top = u",".join(top)
    else:
        num_items = len(top)

        if truncate and num_items > truncate:
            top, rest = top[:int(truncate)], top[int(truncate):]
            # now stringify
            top = u"{}; <a href='#' class='show-more pri-link'>& {} more</a>".format(u"; ".join(top), len(rest))
            if len(rest) > 1:
                rest = u"; ".join(rest)
            else:
                rest = u"and {}".join(rest[-1])
            top = u"<span>{}</span><span class='the_rest'>{}</span>".format(top, rest)

        else:
            if num_items > 1:
                top[-1] = u"and {}".format(top[-1])
            if num_items == 2:
                top = u" ".join(top)
            else:
                top = u"; ".join(top)

    # otherwise, return the list joined with commans
    return {
        "url": stat_url,
        "value": top,
        "data": vals
    }
Пример #35
0
    def __init__(self, config, profile, anchor=""):
        """Initializes a new Section class.

        Args:
            config (str): The parsed YAML string as a dict
            profile (Profile): The Profile class instance this Section will be a part of.

        """

        # Set the attr and profile attributes
        self.attr = profile.attr
        self.attr_type = profile.attr_type
        self.anchor = anchor

        if "title" in config:
            self.title = config["title"]

        if "group" in config:
            self.group = config["group"]

        if "description" in config:
            self.description = config["description"]
            if not isinstance(self.description, list):
                self.description = [self.description]

        if "viz" in config:
            self.viz = Viz(config["viz"], profile=profile)

        if "topics" in config:
            self.topics = config["topics"]

            # filter out topics that are not appropriate for sumlevel
            self.topics = [t for t in self.topics if self.allowed_levels(t)]

            # loop through the topics
            for topic in self.topics:
                if "title" in topic:
                    topic["title"] = self.tooltipify(topic["title"])

                if "description" in topic:
                    if not isinstance(topic["description"], list):
                        topic["description"] = [topic["description"]]
                    topic["description"] = [
                        self.tooltipify(desc) for desc in topic["description"]
                    ]

                def getHighlight(viz_obj):
                    ids = viz_obj["id"]
                    if not isinstance(ids, list):
                        ids = [ids]
                    if profile.attr_type in ids:
                        return self.attr["id"]
                    else:
                        return False

                if "stat" in topic:
                    topic["stat"] = [
                        s for s in topic["stat"] if self.allowed_levels(s)
                    ]
                    for s in topic["stat"]:
                        if "title" in s:
                            s["title"] = self.tooltipify(s["title"])

                # instantiate the "viz" config into an array of Viz classes
                if "viz" in topic:
                    if not isinstance(topic["viz"], list):
                        topic["viz"] = [topic["viz"]]
                    topic["viz"] = [
                        v for v in topic["viz"] if self.allowed_levels(v)
                    ]
                    topic["viz"] = [
                        Viz(viz, getHighlight(viz), profile=profile)
                        for viz in topic["viz"]
                    ]

                if "miniviz" in topic:
                    topic["miniviz"] = Viz(topic["miniviz"],
                                           getHighlight(topic["miniviz"]),
                                           profile=profile)

                # fill selector if present
                if "select" in topic:
                    if isinstance(topic["select"]["data"], str):
                        if "param" not in topic["select"]:
                            topic["select"]["param"] = topic["select"]["data"]
                        topic["select"]["data"] = [
                            v for k, v in attr_cache[topic["select"]
                                                     ["data"]].iteritems()
                        ]
                        if "filter" in topic["select"] and topic["select"][
                                "filter"] in profile.variables:
                            f = [
                                v[topic["select"]["param"]]["raw"] for v in
                                profile.variables[topic["select"]["filter"]]
                            ]
                            topic["select"]["data"] = [
                                d for d in topic["select"]["data"]
                                if d["id"] in f
                            ]
                    elif isinstance(topic["select"]["data"], list):
                        topic["select"]["data"] = [
                            fetch(v, False) for v in topic["select"]["data"]
                        ]
                    if len(topic["select"]["data"]) < 2:
                        del topic["select"]

        if "sections" in config:
            self.sections = config["sections"]

        if "stats" in config:
            self.stats = config["stats"]
Пример #36
0
    def __init__(self, config, profile, anchor=""):
        """Initializes a new Section class.

        Args:
            config (str): The parsed YAML string as a dict
            profile (Profile): The Profile class instance this Section will be a part of.

        """

        # Set the attr and profile attributes
        self.attr = profile.attr
        self.attr_type = profile.attr_type
        self.anchor = anchor

        if "title" in config:
            self.title = config["title"]

        if "group" in config:
            self.group = config["group"]

        if "description" in config:
            self.description = config["description"]
            if not isinstance(self.description, list):
                self.description = [self.description]

        if "viz" in config:
            self.viz = Viz(config["viz"], profile = profile)


        if "topics" in config:
            self.topics = config["topics"]

            # filter out topics that are not appropriate for sumlevel
            self.topics = [t for t in self.topics if self.allowed_levels(t)]

            # loop through the topics
            for topic in self.topics:
                if "title" in topic:
                    topic["title"] = self.tooltipify(topic["title"])

                if "description" in topic:
                    if not isinstance(topic["description"], list):
                        topic["description"] = [topic["description"]]
                    topic["description"] = [self.tooltipify(desc) for desc in topic["description"]]

                def getHighlight(viz_obj):
                    ids = viz_obj["id"]
                    if not isinstance(ids, list):
                        ids = [ids]
                    if profile.attr_type in ids:
                        return self.attr["id"]
                    else:
                        return False

                if "stat" in topic:
                    topic["stat"] = [s for s in topic["stat"] if self.allowed_levels(s)]
                    for s in topic["stat"]:
                        if "title" in s:
                            s["title"] = self.tooltipify(s["title"])

                # instantiate the "viz" config into an array of Viz classes
                if "viz" in topic:
                    if not isinstance(topic["viz"], list):
                        topic["viz"] = [topic["viz"]]
                    topic["viz"] = [v for v in topic["viz"] if self.allowed_levels(v)]
                    topic["viz"] = [Viz(viz, getHighlight(viz), profile = profile) for viz in topic["viz"]]


                if "miniviz" in topic:
                    topic["miniviz"] = Viz(topic["miniviz"], getHighlight(topic["miniviz"]), profile = profile)


                # fill selector if present
                if "select" in topic:
                    if isinstance(topic["select"]["data"], str):
                        if "param" not in topic["select"]:
                            topic["select"]["param"] = topic["select"]["data"]
                        topic["select"]["data"] = [v for k, v in attr_cache[topic["select"]["data"]].iteritems()]
                        if "filter" in topic["select"] and topic["select"]["filter"] in profile.variables:
                            f = [v[topic["select"]["param"]]["raw"] for v in profile.variables[topic["select"]["filter"]]]
                            topic["select"]["data"] = [d for d in topic["select"]["data"] if d["id"] in f]
                    elif isinstance(topic["select"]["data"], list):
                        topic["select"]["data"] = [fetch(v, False) for v in topic["select"]["data"]]
                    if len(topic["select"]["data"]) < 2:
                        del topic["select"]

        if "sections" in config:
            self.sections = config["sections"]

        if "stats" in config:
            self.stats = config["stats"]
Пример #37
0
    def ranks(self, **kwargs):

        ranks = int(kwargs.get("limit", 1))
        col = kwargs.get("col")
        attr_type = kwargs.get("attr_type", self.attr_type)

        params = {}
        params[attr_type] = self.attr["id"]
        params["required"] = col
        params["show"] = kwargs.get("show", self.attr_type)
        params["year"] = kwargs.get("year", "latest")
        params["sumlevel"] = kwargs.get("sumlevel", self.sumlevel(**kwargs))

        query = RequestEncodingMixin._encode_params(params)
        url = "{}/api?{}".format(API, query)

        try:
            rank = int(datafold(requests.get(url).json())[0][col])
        except ValueError:
            app.logger.info("STAT ERROR: {}".format(url))
            return ""

        del params[attr_type]
        params["limit"] = 1
        params["order"] = col
        params["sort"] = "desc"

        if rank <= (ranks / 2 + 1):
            results = range(1, ranks + 1)
        else:

            query = RequestEncodingMixin._encode_params(params)
            url = "{}/api?{}".format(API, query)

            try:
                max_rank = int(datafold(requests.get(url).json())[0][col])
            except ValueError:
                app.logger.info("STAT ERROR: {}".format(url))
                return ""

            if rank > (max_rank - ranks / 2 - 1):
                results = range(max_rank - ranks + 1, max_rank + 1)
            else:
                results = range(int(math.ceil(rank - ranks / 2)),
                                int(math.ceil(rank + ranks / 2) + 1))

        prev = kwargs.get("prev", False)
        next = kwargs.get("next", False)
        if prev:
            if rank == results[0]:
                return "N/A"
            else:
                results = [results[results.index(rank) - 1]]
        if next:
            if rank == results[-1]:
                return "N/A"
            else:
                results = [results[results.index(rank) + 1]]

        key = kwargs.get("key", False)

        if key == "id" or key == "name":
            del params["limit"]
            params[col] = ",".join([str(r) for r in results])
            query = RequestEncodingMixin._encode_params(params)
            url = "{}/api?{}".format(API, query)
            try:
                results = datafold(requests.get(url).json())
            except ValueError:
                app.logger.info("STAT ERROR: {}".format(url))
                return ""

            if key == "id":
                results = [d[params["show"]] for d in results]
            elif key == "name":
                return self.make_links([
                    fetch(d[params["show"]], params["show"]) for d in results
                ], params["show"])

        return ",".join([str(r) for r in results])
Пример #38
0
 def sector(self, **kwargs):
     if kwargs.get("text", False):
         return fetch(self.attr["sector"], "sector")["name"]
     return "private" if str(self.attr["sector"]) in [
         "2", "3", "5", "6", "8", "9"
     ] else "public"
Пример #39
0
    def parents(self, **kwargs):
        id_only = kwargs.get("id_only", False)
        limit = kwargs.pop("limit", None)
        attr_id = self.id(**kwargs)
        prefix = kwargs.get("prefix", None)

        if (prefix or limit) and id_only == False:
            top = get_parents(attr_id, self.attr_type)
            if prefix:
                top = [p for p in top if p["id"].startswith(prefix)]
            if limit:
                top = top[-int(limit):]
            top = self.make_links(top)
            return top

        if self.attr["id"] == "01000US":

            col = kwargs.get("col", False)
            if col:

                params = {
                    "show": "geo",
                    "required": col,
                    "sumlevel": "state",
                    "order": col,
                    "sort": "desc",
                    "year": "latest"
                }

                query = RequestEncodingMixin._encode_params(params)
                url = "{}/api?{}".format(API, query)

                try:
                    results = [r for r in datafold(requests.get(url).json()) if r[col]]
                except ValueError:
                    app.logger.info("STAT ERROR: {}".format(url))
                    return ""

                results = results[:2] + results[-2:]

                if id_only:
                    return ",".join([r["geo"] for r in results])
                else:
                    return [fetch(r["geo"], "geo") for r in results]
            else:
                results = [
                    {"id": "04000US06", "name": "California", "url_name": "california"},
                    {"id": "04000US48", "name": "Texas", "url_name": "texas"},
                    {"id": "04000US36", "name": "New York", "url_name": "new-york"},
                    {"id": "16000US1150000", "name":"Washington D.C.", "url_name": "washington-dc"},
                    {"id": "16000US3651000", "name":"New York, NY", "url_name": "new-york-ny"},
                    {"id": "16000US0644000", "name":"Los Angeles, CA", "url_name": "los-angeles-ca"},
                    {"id": "16000US1714000", "name":"Chicago, IL", "url_name": "chicago-il"}
                ]

                if id_only:
                    return ",".join([r["id"] for r in results])
                else:
                    return results

        results = [p for p in get_parents(attr_id, self.attr_type) if p["id"] != attr_id]
        results = self.get_uniques(results)
        for p in results:
            if self.attr_type == "geo":
                level = p["id"][:3]
            elif self.attr_type == "cip":
                level = str(len(p["id"]))
            else:
                level = str(fetch(p["id"], self.attr_type)["level"])
            p["sumlevel"] = SUMLEVELS[self.attr_type][level]["label"]

        if prefix:
            results = [r for r in results if r["id"].startswith(prefix)]

        if limit:
            results = results[-int(limit):]

        if id_only:
            return ",".join([r["id"] for r in results])
        else:
            return results
Пример #40
0
    def parents(self, **kwargs):
        id_only = kwargs.get("id_only", False)
        limit = kwargs.pop("limit", None)
        attr_id = self.id(**kwargs)
        prefix = kwargs.get("prefix", None)

        if (prefix or limit) and id_only == False:
            top = get_parents(attr_id, self.attr_type)
            if prefix:
                top = [p for p in top if p["id"].startswith(prefix)]
            if limit:
                top = top[-int(limit):]
            top = self.make_links(top)
            return top

        if self.attr["id"] == "01000US":

            col = kwargs.get("col", False)
            if col:

                params = {
                    "show": "geo",
                    "required": col,
                    "sumlevel": "state",
                    "order": col,
                    "sort": "desc",
                    "year": "latest"
                }

                query = RequestEncodingMixin._encode_params(params)
                url = "{}/api?{}".format(API, query)

                try:
                    results = [r for r in datafold(requests.get(url).json()) if r[col]]
                except ValueError:
                    app.logger.info("STAT ERROR: {}".format(url))
                    return ""

                results = results[:2] + results[-2:]

                if id_only:
                    return ",".join([r["geo"] for r in results])
                else:
                    return [fetch(r["geo"], "geo") for r in results]
            else:
                results = [
                    {"id": "04000US06", "name": "California", "url_name": "california"},
                    {"id": "04000US48", "name": "Texas", "url_name": "texas"},
                    {"id": "04000US36", "name": "New York", "url_name": "new-york"},
                    {"id": "16000US1150000", "name":"Washington D.C.", "url_name": "washington-dc"},
                    {"id": "16000US3651000", "name":"New York, NY", "url_name": "new-york-ny"},
                    {"id": "16000US0644000", "name":"Los Angeles, CA", "url_name": "los-angeles-ca"},
                    {"id": "16000US1714000", "name":"Chicago, IL", "url_name": "chicago-il"}
                ]

                if id_only:
                    return ",".join([r["id"] for r in results])
                else:
                    return results

        results = [p for p in get_parents(attr_id, self.attr_type) if p["id"] != attr_id]
        results = self.get_uniques(results)

        if prefix:
            results = [r for r in results if r["id"].startswith(prefix)]

        if limit:
            results = results[-int(limit):]

        if id_only:
            return ",".join([r["id"] for r in results])
        else:
            return results