Example #1
0
def publisher_dicts():
    for publisher, activities in data.current_stats['inverted_publisher'][
            'activities'].items():
        publisher_stats = data.get_publisher_stats(publisher)
        yield {
            'Publisher Name':
            publisher_name[publisher],
            'Publisher Registry Id':
            publisher,
            'Activities':
            activities,
            'Organisations':
            publisher_stats['organisations'],
            'Files':
            publisher_stats['activity_files'] +
            publisher_stats['organisation_files'],
            'Activity Files':
            publisher_stats['activity_files'],
            'Organisation Files':
            publisher_stats['organisation_files'],
            'Total File Size':
            publisher_stats['file_size'],
            'Reporting Org on Registry':
            data.ckan_publishers[publisher]['result']['publisher_iati_id'],
            'Reporting Orgs in Data (count)':
            len(publisher_stats['reporting_orgs']),
            'Reporting Orgs in Data':
            ';'.join(publisher_stats['reporting_orgs']),
            'Hierarchies (count)':
            len(publisher_stats['hierarchies']),
            'Hierarchies':
            ';'.join(publisher_stats['hierarchies']),
        }
Example #2
0
def has_future_transactions(publisher):
    """
        returns 0, 1 or 2
        Returns 2 if the most recent data for a publisher has future transactions.
        Returns 1 if the publisher has ever had future transactions.
        Returns -1 if the publisher has not been checked for some reason.
        Returns 0 otherwise.
    """
    publisher_stats = get_publisher_stats(publisher)
    if 'transaction_dates' in publisher_stats:
        for transaction_type, transaction_counts in publisher_stats[
                'transaction_dates'].items():
            for transaction_date_string, count in transaction_counts.items():
                transaction_date = parse_iso_date(transaction_date_string)
                if transaction_date and transaction_date > datetime.date.today(
                ):
                    return 2
    if publisher not in blacklist_publisher:
        return -1
    today = datetime.date.today()
    mindate = datetime.date(today.year - 1, today.month, 1)
    for date, activity_blacklist in blacklist_publisher[publisher][
            'activities_with_future_transactions'].items():
        if parse_iso_date(date) >= mindate and activity_blacklist:
            return 1
    return 0
Example #3
0
def table():
    """Generate data for the publisher coverage table
    """

    # Loop over each publisher
    for publisher_title, publisher in publishers_ordered_by_title:

        # Store the data for this publisher as a new variable
        publisher_stats = get_publisher_stats(publisher)
        
        # Create a list for publisher data, and populate it with basic data
        row = {}
        row['publisher'] = publisher
        row['publisher_title'] = publisher_title


        # Compute IATI spend
        iati_spend_total = 0
        transactions_usd = publisher_stats['sum_transactions_by_type_by_year_usd']

        if '2014' in transactions_usd.get('3', {}).get('USD', {}):
            iati_spend_total += transactions_usd['3']['USD']['2014']

        if '2014' in transactions_usd.get('D', {}).get('USD', {}):
            iati_spend_total += transactions_usd['D']['USD']['2014']

        if '2014' in transactions_usd.get('4', {}).get('USD', {}):
            iati_spend_total += transactions_usd['4']['USD']['2014']

        if '2014' in transactions_usd.get('E', {}).get('USD', {}):
            iati_spend_total += transactions_usd['E']['USD']['2014']

        # Convert to millions USD 
        row['iati_spend'] = float( iati_spend_total / 1000000)


        # Set spend ratio score
        # This is manually set at 100% for now. The IATI technical team is still working on compiling reference spend data from disparate sources, in order to assess the spend ratio.
        row['spend_ratio'] = 100


        # Compute coverage score
        if row['spend_ratio'] >= 80:
            row['coverage_adjustment'] = 100

        elif row['spend_ratio'] >= 60:
            row['coverage_adjustment'] = 80

        elif row['spend_ratio'] >= 40:
            row['coverage_adjustment'] = 60

        else:
            row['coverage_adjustment'] = 40


        # Return a generator object
        yield row
def generate_row(publisher):
    """Generate comprehensiveness table data for a given publisher 
    """

    publisher_stats = get_publisher_stats(publisher)
        
    # Set an inital dictionary, which will later be populated further
    row = {}
    row['publisher'] = publisher
    row['publisher_title'] = publisher_name[publisher]
    
    
    # Calculate percentages for publisher data populated with any data
    for slug in column_slugs['core'] + column_slugs['financials'] + column_slugs['valueadded']:

        # Set the stats base for calculating the numerator. This is based on the hierarchy set in the lookup
        if column_base_lookup[slug] == 'bottom_hierarchy':
            publisher_base = publisher_stats.get('bottom_hierarchy', {})

        elif column_base_lookup[slug] == 'hierarchy_with_most_budgets':
            publisher_base = publisher_stats['by_hierarchy'].get(get_hierarchy_with_most_budgets(publisher_stats), {})

        elif column_base_lookup[slug] == 'first_hierarchy_with_commitments':
            if get_first_hierarchy_with_commitments(publisher_stats):
                publisher_base = publisher_stats['by_hierarchy'].get(get_first_hierarchy_with_commitments(publisher_stats), {})
            else:
                publisher_base = publisher_stats.get('bottom_hierarchy', {})

        else:
            # Most common case will be column_base_lookup[slug] == 'all':
            publisher_base = publisher_stats

        numerator_all = publisher_base.get('comprehensiveness', {}).get(slug, 0)
        numerator_valid = publisher_base.get('comprehensiveness_with_validation', {}).get(slug, 0)

        if denominator(slug, publisher_base) != 0:
            # Populate the row with the %age
            row[slug] = int(round(
                float(numerator_all)/denominator(slug, publisher_base)*100
                ))
            row[slug+'_valid'] = int(round(
                float(numerator_valid)/denominator(slug, publisher_base)*100
                ))

    # Loop for averages
    # Calculate the average for each grouping, and the overall 'summary' average
    for page in ['core', 'financials', 'valueadded', 'summary']: 
        # Note that the summary must be last, so that it can use the average calculations from the other groupings
        row[page+'_average'] = int(round(
            sum((row.get(x[0]) or 0)*x[2] for x in columns[page]) / float(sum(x[2] for x in columns[page]))
            ))
        row[page+'_average_valid'] = int(round(
            sum((row.get(x[0]+'_valid') or 0)*x[2] for x in columns[page]) / float(sum(x[2] for x in columns[page]))
            ))

    return row
def table():
    """Generate the comprehensiveness table
    """

    # Loop over the data for each publisher
    for publisher_title, publisher in publishers_ordered_by_title:
        publisher_stats = get_publisher_stats(publisher)

        # Set an inital dictionary, which will later be populated further
        row = {}
        row["publisher"] = publisher
        row["publisher_title"] = publisher_title

        # This for loop is for non-financial data
        for k, v in publisher_stats["comprehensiveness"].items():
            if k not in column_slugs["financials"]:
                if denominator(k, publisher_stats) != 0:
                    # Populate the row with the %age
                    row[k] = int(float(v) / denominator(k, publisher_stats) * 100)

        # Ensure that only lowest hierarchy is used for financial calculations
        # Arises from https://github.com/IATI/IATI-Dashboard/issues/278
        if "comprehensiveness" in publisher_stats["bottom_hierarchy"]:
            # This loop covers the financials: everything that is low in the hierarchy-attribute of an activity element
            for k, v in publisher_stats["bottom_hierarchy"]["comprehensiveness"].items():
                if k in column_slugs["financials"]:
                    if denominator(k, publisher_stats["bottom_hierarchy"]) != 0:
                        row[k] = int(float(v) / denominator(k, publisher_stats["bottom_hierarchy"]) * 100)

        # Calculate percentages for publisher data which is considered valid
        for k, v in publisher_stats["comprehensiveness_with_validation"].items():
            if k not in column_slugs["financials"]:
                if denominator(k, publisher_stats) != 0:
                    row[k + "_valid"] = int(float(v) / denominator(k, publisher_stats) * 100)

        # Ensure that only lowest hierarchy is used for financial calculations
        # Arises from https://github.com/IATI/IATI-Dashboard/issues/278
        if "comprehensiveness_with_validation" in publisher_stats["bottom_hierarchy"]:
            for k, v in publisher_stats["bottom_hierarchy"]["comprehensiveness_with_validation"].items():
                if k in column_slugs["financials"]:
                    if denominator(k, publisher_stats["bottom_hierarchy"]) != 0:
                        row[k + "_valid"] = int(float(v) / denominator(k, publisher_stats["bottom_hierarchy"]) * 100)

        # Calculate the average for each grouping, and the overall 'summary' average
        for page in ["core", "financials", "valueadded", "summary"]:
            # Note that the summary must be last, so that it can use the average calculations from the other groupings
            row[page + "_average"] = sum((row.get(x[0]) or 0) * x[2] for x in columns[page]) / sum(
                x[2] for x in columns[page]
            )
            row[page + "_average_valid"] = sum((row.get(x[0] + "_valid") or 0) * x[2] for x in columns[page]) / sum(
                x[2] for x in columns[page]
            )

        # Generate a row object
        yield row
Example #6
0
def publisher_dicts():
    for publisher, activities in data.current_stats['inverted_publisher'][
            'activities'].items():
        if publisher in publisher_name:
            publisher_stats = data.get_publisher_stats(publisher)
            yield {
                'Publisher Name': publisher_name[publisher],
                'Publisher Registry Id': publisher,
                'Activities': activities,
                'Hierarchies (count)': len(publisher_stats['hierarchies']),
                'Hierarchies': ';'.join(publisher_stats['hierarchies']),
            }
def table():
    """Generate data for the publisher forward-looking table
    """

    # Loop over each publisher
    for publisher_title, publisher in publishers_ordered_by_title:

        # Store the data for this publisher as a new variable
        publisher_stats = get_publisher_stats(publisher)
        
        # Create a list for publisher data, and populate it with basic data
        row = {}
        row['publisher'] = publisher
        row['publisher_title'] = publisher_title
        row['year_columns'] = [{},{},{}]

        # Work with hierarchies
        by_hierarchy = publisher_stats['by_hierarchy']
        hierarchies_with_nonzero_budgets = [
            h for h, stats in by_hierarchy.items()
            if not all(x==0 for x in stats['forwardlooking_activities_with_budgets'].values())
        ]
        
        # Flag if budgets on current activities are reported at more than one hierarchy
        row['flag'] = len(hierarchies_with_nonzero_budgets) > 1

        # Loop over each of the three years (i.e. this year and the following two years) to generate the statistics for the table
        for year in years:

            # If 'forwardlooking_activities_current' and 'forwardlooking_activities_with_budgets' are both in the bottom hierarchy
            if 'forwardlooking_activities_current' in publisher_stats['bottom_hierarchy'] and 'forwardlooking_activities_with_budgets' in publisher_stats['bottom_hierarchy'] :
                if len(hierarchies_with_nonzero_budgets) != 1:
                    # If budgets are at more than one hierarchy (or no hierarchies), just use activities at all hierarchies
                    row['year_columns'][0][year] = publisher_stats['forwardlooking_activities_current'].get(year) or 0
                    row['year_columns'][1][year] = publisher_stats['forwardlooking_activities_with_budgets'].get(year) or 0
                else:
                    # Else, use the hierarchy which they are reported at
                    row['year_columns'][0][year] = by_hierarchy[hierarchies_with_nonzero_budgets[0]]['forwardlooking_activities_current'].get(year) or 0
                    row['year_columns'][1][year] = by_hierarchy[hierarchies_with_nonzero_budgets[0]]['forwardlooking_activities_with_budgets'].get(year) or 0
                if not int(row['year_columns'][0][year]):
                    row['year_columns'][2][year] = '-'
                else:
                    row['year_columns'][2][year] = int(round(float(row['year_columns'][1][year])/float(row['year_columns'][0][year])*100))
            else:
                # Else if either 'forwardlooking_activities_current' or 'forwardlooking_activities_with_budgets' are not in the bottom hierarchy, set data zero
                # This should only occur if a publisher has 0 activities
                row['year_columns'][0][year] = '0'
                row['year_columns'][1][year] = '0'
                row['year_columns'][2][year] = '-'

        # Return a generator object
        yield row
Example #8
0
def table():
    """Generate coverage table data for every publisher and return as a generator object
    """

    # Loop over each publisher
    for publisher_title, publisher in publishers_ordered_by_title:

        # Store the data for this publisher as new variables
        publisher_stats = get_publisher_stats(publisher)

        # Skip if all activities from this publisher are secondary reported
        if publisher in secondary_publishers:
            continue

        # Return a generator object
        yield generate_row(publisher)
Example #9
0
def table():
    """Generate coverage table data for every publisher and return as a generator object
    """

    # Loop over each publisher
    for publisher_title, publisher in publishers_ordered_by_title:

        # Store the data for this publisher as new variables
        publisher_stats = get_publisher_stats(publisher)

        # Skip if all activities from this publisher are secondary reported
        if publisher in secondary_publishers:
            continue

        # Return a generator object
        yield generate_row(publisher)
Example #10
0
def table():
    """Generate data for the humanitarian table
    """

    # Loop over each publisher
    for publisher_title, publisher in publishers_ordered_by_title:
        # Store the data for this publisher as a new variable
        publisher_stats = get_publisher_stats(publisher)

        # Create a list for publisher data, and populate it with basic data
        row = {}
        row['publisher'] = publisher
        row['publisher_title'] = publisher_title
        row['publisher_type'] = common.get_publisher_type(publisher)['name']

        # Get data from IATI-Stats output
        row['num_activities'] = publisher_stats.get('humanitarian', {}).get(
            'is_humanitarian', '0')
        row['publishing_humanitarian'] = 100 if int(
            row['num_activities']) > 0 else 0

        # Calculate percentage of all humanitarian activities that are defined using the @humanitarian attribute
        row['humanitarian_attrib'] = (publisher_stats.get(
            'humanitarian', {}).get('is_humanitarian_by_attrib', '0') / float(
                row['num_activities']) if int(row['num_activities']) > 0 else
                                      0) * 100

        # Calculate percentage of all humanitarian activities that use the <humanitarian-scope> element to define an appeal or emergency
        row['appeal_emergency'] = (publisher_stats.get('humanitarian', {}).get(
            'contains_humanitarian_scope', '0') /
                                   float(row['num_activities']) if
                                   int(row['num_activities']) > 0 else 0) * 100

        # Calculate percentage of all humanitarian activities that use clusters
        row['clusters'] = (publisher_stats.get('humanitarian', {}).get(
            'uses_humanitarian_clusters_vocab', '0') /
                           float(row['num_activities'])
                           if int(row['num_activities']) > 0 else 0) * 100

        # Calculate the mean average
        row['average'] = (row['publishing_humanitarian'] +
                          row['humanitarian_attrib'] +
                          row['appeal_emergency'] + row['clusters']) / float(4)

        # Return a generator object
        yield row
Example #11
0
def publisher_dicts():
    for publisher, activities in data.current_stats['inverted_publisher']['activities'].items():
        publisher_stats = data.get_publisher_stats(publisher)
        yield {
            'Publisher Name': publisher_name[publisher],
            'Publisher Registry Id': publisher,
            'Activities': activities,
            'Organisations': publisher_stats['organisations'],
            'Files': publisher_stats['activity_files']+publisher_stats['organisation_files'],
            'Activity Files': publisher_stats['activity_files'],
            'Organisation Files': publisher_stats['organisation_files'],
            'Total File Size': publisher_stats['file_size'],
            'Reporting Org on Registry': data.ckan_publishers[publisher]['result']['publisher_iati_id'],
            'Reporting Orgs in Data (count)': len(publisher_stats['reporting_orgs']),
            'Reporting Orgs in Data': ';'.join(publisher_stats['reporting_orgs']),
            'Hierarchies (count)': len(publisher_stats['hierarchies']),
            'Hierarchies': ';'.join(publisher_stats['hierarchies']),
        }
Example #12
0
def publisher_dicts():
    for publisher, activities in data.current_stats["inverted_publisher"]["activities"].items():
        publisher_stats = data.get_publisher_stats(publisher)
        yield {
            "Publisher Name": publisher_name[publisher],
            "Publisher Registry Id": publisher,
            "Activities": activities,
            "Organisations": publisher_stats["organisations"],
            "Files": publisher_stats["activity_files"] + publisher_stats["organisation_files"],
            "Activity Files": publisher_stats["activity_files"],
            "Organisation Files": publisher_stats["organisation_files"],
            "Total File Size": publisher_stats["file_size"],
            "Reporting Org on Registry": data.ckan_publishers[publisher]["result"]["publisher_iati_id"],
            "Reporting Orgs in Data (count)": len(publisher_stats["reporting_orgs"]),
            "Reporting Orgs in Data": ";".join(publisher_stats["reporting_orgs"]),
            "Data Tickets": len(data.data_tickets[publisher]),
            "Hierarchies (count)": len(publisher_stats["hierarchies"]),
            "Hierarchies": ";".join(publisher_stats["hierarchies"]),
        }
Example #13
0
def table():
    """Generate data for the humanitarian table
    """

    # Loop over each publisher
    for publisher_title, publisher in publishers_ordered_by_title:
        # Store the data for this publisher as a new variable
        publisher_stats = get_publisher_stats(publisher)

        # Create a list for publisher data, and populate it with basic data
        row = {}
        row['publisher'] = publisher
        row['publisher_title'] = publisher_title
        row['publisher_type'] = common.get_publisher_type(publisher)['name']

        # Get data from IATI-Stats output
        row['num_activities'] = publisher_stats.get('humanitarian', {}).get('is_humanitarian', '0')
        row['publishing_humanitarian'] = 100 if int(row['num_activities']) > 0 else 0

        # Calculate percentage of all humanitarian activities that are defined using the @humanitarian attribute
        row['humanitarian_attrib'] = (
            publisher_stats.get('humanitarian', {}).get('is_humanitarian_by_attrib', '0') / float(row['num_activities'])
              if int(row['num_activities']) > 0 else 0
            ) * 100

        # Calculate percentage of all humanitarian activities that use the <humanitarian-scope> element to define an appeal or emergency
        row['appeal_emergency'] = (
            publisher_stats.get('humanitarian', {}).get('contains_humanitarian_scope', '0') / float(row['num_activities'])
              if int(row['num_activities']) > 0 else 0
            ) * 100

        # Calculate percentage of all humanitarian activities that use clusters
        row['clusters'] = (
            publisher_stats.get('humanitarian', {}).get('uses_humanitarian_clusters_vocab', '0') / float(row['num_activities'])
              if int(row['num_activities']) > 0 else 0
            ) * 100

        # Calculate the mean average
        row['average'] = (row['publishing_humanitarian'] + row['humanitarian_attrib'] + row['appeal_emergency'] + row['clusters']) / float(4)

        # Return a generator object
        yield row
def table():
    for publisher_title, publisher in publishers_ordered_by_title:
        publisher_stats = get_publisher_stats(publisher)
        # Data structure that gets passed to the table
        row = {}
        row['publisher'] = publisher
        row['publisher_title'] = publisher_title
        
        # This for loop is for non-financials
        for k,v in publisher_stats['comprehensiveness'].items():
            if k not in column_slugs['financials']:
                if denominator(k, publisher_stats) != 0:
                    row[k] = int(float(v)/denominator(k, publisher_stats)*100)
                    
        # https://github.com/IATI/IATI-Dashboard/issues/278
        if 'comprehensiveness' in publisher_stats['bottom_hierarchy']:
            # This loop covers the financials: everything that is low in the hierarchy-attribute of an activity element
            for k,v in publisher_stats['bottom_hierarchy']['comprehensiveness'].items():
                if k in column_slugs['financials']:
                    if denominator(k, publisher_stats['bottom_hierarchy']) != 0:
                        row[k] = int(float(v)/denominator(k, publisher_stats['bottom_hierarchy'])*100)

        for k,v in publisher_stats['comprehensiveness_with_validation'].items():
            if k not in column_slugs['financials']:
                if denominator(k, publisher_stats) != 0:
                    row[k+'_valid'] = int(float(v)/denominator(k, publisher_stats)*100)
        # https://github.com/IATI/IATI-Dashboard/issues/278
        if 'comprehensiveness_with_validation' in publisher_stats['bottom_hierarchy']:
            for k,v in publisher_stats['bottom_hierarchy']['comprehensiveness_with_validation'].items():
                if k in column_slugs['financials']:
                    if denominator(k, publisher_stats['bottom_hierarchy']) != 0:
                        row[k+'_valid'] = int(float(v)/denominator(k, publisher_stats['bottom_hierarchy'])*100)

        for page in ['core', 'financials', 'valueadded', 'summary']: 
            # summary must be last to use calculations from others
            row[page+'_average'] = sum((row.get(x[0]) or 0)*x[2] for x in columns[page]) / sum(x[2] for x in columns[page])
            row[page+'_average_valid'] = sum((row.get(x[0]+'_valid') or 0)*x[2] for x in columns[page]) / sum(x[2] for x in columns[page])

        yield row
Example #15
0
def has_future_transactions(publisher):
    """
        returns 0, 1 or 2
        Returns 2 if the most recent data for a publisher has future transactions.
        Returns 1 if the publisher has ever had future transactions.
        Returns -1 if the publisher has not been checked for some reason.
        Returns 0 otherwise.
    """
    publisher_stats = get_publisher_stats(publisher)
    if 'transaction_dates' in publisher_stats:
        for transaction_type, transaction_counts in publisher_stats['transaction_dates'].items():
            for transaction_date_string, count in transaction_counts.items():
                transaction_date = parse_iso_date(transaction_date_string)
                if transaction_date and transaction_date > datetime.date.today():
                    return 2
    if publisher not in blacklist_publisher:
        return -1
    today = datetime.date.today()
    mindate = datetime.date(today.year-1, today.month, 1)
    for date, activity_blacklist in blacklist_publisher[publisher]['activities_with_future_transactions'].items():
        if parse_iso_date(date) >= mindate and activity_blacklist:
            return 1
    return 0
def table():
    for publisher_title, publisher in publishers_ordered_by_title:
        publisher_stats = get_publisher_stats(publisher)
        row = {}
        row['publisher'] = publisher
        row['publisher_title'] = publisher_title
        row['year_columns'] = [{},{},{}]

        by_hierarchy = publisher_stats['by_hierarchy']
        hierarchies_with_nonzero_budgets = [
            h for h, stats in by_hierarchy.items()
            if not all(x==0 for x in stats['forwardlooking_activities_with_budgets'].values())
        ]
        # Flag if budgets on current activities are reported at more than one hierarchy
        row['flag'] = len(hierarchies_with_nonzero_budgets) > 1


        for year in years:
            if 'forwardlooking_activities_current' in publisher_stats['bottom_hierarchy'] and 'forwardlooking_activities_with_budgets' in publisher_stats['bottom_hierarchy'] :
                if len(hierarchies_with_nonzero_budgets) != 1:
                    # If budgets are at more than one hierarchy (or no hierarchies), just use activities at all hierarchies
                    row['year_columns'][0][year] = publisher_stats['forwardlooking_activities_current'].get(year) or 0
                    row['year_columns'][1][year] = publisher_stats['forwardlooking_activities_with_budgets'].get(year) or 0
                else:
                    # Else, use the hierarchy they are reported at
                    row['year_columns'][0][year] = by_hierarchy[hierarchies_with_nonzero_budgets[0]]['forwardlooking_activities_current'].get(year) or 0
                    row['year_columns'][1][year] = by_hierarchy[hierarchies_with_nonzero_budgets[0]]['forwardlooking_activities_with_budgets'].get(year) or 0
                if not int(row['year_columns'][0][year]):
                    row['year_columns'][2][year] = '-'
                else:
                    row['year_columns'][2][year] = int(round(float(row['year_columns'][1][year])/float(row['year_columns'][0][year])*100))
            else:
                # Should only occur if a publisher has 0 activities
                row['year_columns'][0][year] = '0'
                row['year_columns'][1][year] = '0'
                row['year_columns'][2][year] = '-'
        yield row
Example #17
0
def generate_row(publisher):
    """Generate coverage table data for a given publisher
    """

    # Store the data for this publisher as new variables
    publisher_stats = get_publisher_stats(publisher)
    transactions_usd = publisher_stats['sum_transactions_by_type_by_year_usd']

    # Create a list for publisher data, and populate it with basic data
    row = {}
    row['publisher'] = publisher
    row['publisher_title'] = publisher_name[publisher]
    row['no_data_flag_red'] = 0
    row['no_data_flag_amber'] = 0
    row['spend_data_error_reported_flag'] = 0
    row['sort_order'] = 0

    # Compute 2014 IATI spend
    iati_2014_spend_total = 0

    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2014 spend total should be based on their
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2014' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['2']['USD']['2014']

        if '2014' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['C']['USD']['2014']

    else:
        # This is a non-DFI publisher
        if '2014' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['3']['USD']['2014']

        if '2014' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['D']['USD']['2014']

        if '2014' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['4']['USD']['2014']

        if '2014' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['E']['USD']['2014']

    # Convert to millions USD
    row['iati_spend_2014'] = round(float(iati_2014_spend_total / 1000000), 2)

    # Compute 2015 IATI spend
    iati_2015_spend_total = 0

    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2015 spend total should be based on their
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2015' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['2']['USD']['2015']

        if '2015' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['C']['USD']['2015']

    else:
        # This is a non-DFI publisher
        if '2015' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['3']['USD']['2015']

        if '2015' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['D']['USD']['2015']

        if '2015' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['4']['USD']['2015']

        if '2015' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['E']['USD']['2015']

    # Convert to millions USD
    row['iati_spend_2015'] = round(float(iati_2015_spend_total / 1000000), 2)

    # Compute 2016 IATI spend
    iati_2016_spend_total = 0

    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2016 spend total should be based on their
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2016' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['2']['USD']['2016']

        if '2016' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['C']['USD']['2016']

    else:
        # This is a non-DFI publisher
        if '2016' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['3']['USD']['2016']

        if '2016' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['D']['USD']['2016']

        if '2016' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['4']['USD']['2016']

        if '2016' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['E']['USD']['2016']

    # Convert to millions USD
    row['iati_spend_2016'] = round(float(iati_2016_spend_total / 1000000), 2)

    # Get reference data
    # Get data from stats files. Set as empty stings if the IATI-Stats code did not find them in the reference data sheet
    data_2014 = publisher_stats['reference_spend_data_usd'].get(
        '2014', {
            'ref_spend': '',
            'not_in_sheet': True
        })
    data_2015 = publisher_stats['reference_spend_data_usd'].get(
        '2015', {
            'ref_spend': '',
            'official_forecast': '',
            'not_in_sheet': True
        })

    # Compute reference data as $USDm
    row['reference_spend_2014'] = round(
        (float(data_2014['ref_spend']) /
         1000000), 2) if is_number(data_2014['ref_spend']) else '-'
    row['reference_spend_2015'] = round(
        (float(data_2015['ref_spend']) /
         1000000), 2) if is_number(data_2015['ref_spend']) else '-'
    row['official_forecast_2015'] = round(
        (float(data_2015['official_forecast']) /
         1000000), 2) if is_number(data_2015['official_forecast']) else '-'

    # Compute spend ratio score
    # Compile a list of ratios for spend & reference data paired by year
    spend_ratio_candidates = [
        (row['iati_spend_2014'] / row['reference_spend_2014']) if
        (row['reference_spend_2014'] > 0)
        and is_number(row['reference_spend_2014']) else 0,
        (row['iati_spend_2015'] / row['reference_spend_2015']) if
        (row['reference_spend_2015'] > 0)
        and is_number(row['reference_spend_2015']) else 0,
        (row['iati_spend_2015'] / row['official_forecast_2015']) if
        (row['official_forecast_2015'] > 0)
        and is_number(row['official_forecast_2015']) else 0
    ]

    # If there are no annual pairs, add the value of non-matching-year spend / reference data
    if ((row['iati_spend_2014'] == 0 or row['reference_spend_2014'] == '-') and
        (row['iati_spend_2015'] == 0 or row['reference_spend_2015'] == '-') and
        (row['iati_spend_2015'] == 0 or row['official_forecast_2015'] == '-')):
        spend_ratio_candidates.append((
            row['iati_spend_2015'] / row['reference_spend_2014']
        ) if (row['reference_spend_2014'] > 0
              ) and is_number(row['reference_spend_2014']) else 0)
        spend_ratio_candidates.append((
            row['iati_spend_2016'] / row['reference_spend_2014']
        ) if (row['reference_spend_2014'] > 0
              ) and is_number(row['reference_spend_2014']) else 0)
        spend_ratio_candidates.append((
            row['iati_spend_2016'] / row['reference_spend_2015']
        ) if (row['reference_spend_2015'] > 0
              ) and is_number(row['reference_spend_2015']) else 0)

    # Get the maximum value and convert to a percentage
    row['spend_ratio'] = int(round(max(spend_ratio_candidates) * 100))

    return row
Example #18
0
def generate_row(publisher):
    """Generate comprehensiveness table data for a given publisher
    """

    publisher_stats = get_publisher_stats(publisher)

    # Set an inital dictionary, which will later be populated further
    row = {}
    row['publisher'] = publisher
    row['publisher_title'] = publisher_name[publisher]

    # Calculate percentages for publisher data populated with any data
    for slug in column_slugs['core'] + column_slugs[
            'financials'] + column_slugs['valueadded']:

        # Set the stats base for calculating the numerator. This is based on the hierarchy set in the lookup
        if column_base_lookup[slug] == 'bottom_hierarchy':
            publisher_base = publisher_stats.get('bottom_hierarchy', {})

        elif column_base_lookup[slug] == 'hierarchy_with_most_budgets':
            publisher_base = publisher_stats['by_hierarchy'].get(
                get_hierarchy_with_most_budgets(publisher_stats), {})

        elif column_base_lookup[slug] == 'first_hierarchy_with_commitments':
            if get_first_hierarchy_with_commitments(publisher_stats):
                publisher_base = publisher_stats['by_hierarchy'].get(
                    get_first_hierarchy_with_commitments(publisher_stats), {})
            else:
                publisher_base = publisher_stats.get('bottom_hierarchy', {})

        else:
            # Most common case will be column_base_lookup[slug] == 'all':
            publisher_base = publisher_stats

        if slug == 'budget':
            budget_all = publisher_base.get('comprehensiveness',
                                            {}).get(slug, 0)
            budget_not_provided_all = publisher_base.get(
                'comprehensiveness', {}).get('budget_not_provided', 0)
            row['flag'] = budget_not_provided_all > 0
            numerator_all = budget_all + budget_not_provided_all
            budget_valid = publisher_base.get(
                'comprehensiveness_with_validation', {}).get(slug, 0)
            budget_not_provided_valid = publisher_base.get(
                'comprehensiveness_with_validation',
                {}).get('budget_not_provided', 0)
            numerator_valid = budget_valid + budget_not_provided_valid
        else:
            numerator_all = publisher_base.get('comprehensiveness',
                                               {}).get(slug, 0)
            numerator_valid = publisher_base.get(
                'comprehensiveness_with_validation', {}).get(slug, 0)

        if denominator(slug, publisher_base) != 0:
            # Populate the row with the %age
            row[slug] = int(
                round(
                    float(numerator_all) / denominator(slug, publisher_base) *
                    100))
            row[slug + '_valid'] = int(
                round(
                    float(numerator_valid) /
                    denominator(slug, publisher_base) * 100))

    # Loop for averages
    # Calculate the average for each grouping, and the overall 'summary' average
    for page in ['core', 'financials', 'valueadded', 'summary']:
        # Note that the summary must be last, so that it can use the average calculations from the other groupings
        row[page + '_average'] = int(
            round(
                sum((row.get(x[0]) or 0) * x[2] for x in columns[page]) /
                float(sum(x[2] for x in columns[page]))))
        row[page + '_average_valid'] = int(
            round(
                sum((row.get(x[0] + '_valid') or 0) * x[2]
                    for x in columns[page]) /
                float(sum(x[2] for x in columns[page]))))

    return row
def table():
    """Generate data for the publisher forward-looking table
    """

    # Store timeliness data in variable
    timeliness_frequency_data = timeliness.publisher_frequency_dict()
    timeliness_timelag_data = timeliness.publisher_timelag_dict()

    # Store generator objects for the data that we are receiving
    forwardlooking_data = forwardlooking.table()
    comprehensiveness_data = comprehensiveness.table()
    coverage_data = coverage.table()

    # Loop over each publisher
    for publisher_title, publisher in publishers_ordered_by_title:

        # Store the data for this publisher as a new variable
        publisher_stats = get_publisher_stats(publisher)
        
        # Create a list for publisher data, and populate it with basic data
        row = {}
        row['publisher'] = publisher
        row['publisher_title'] = publisher_title
        row['publisher_type'] = common.get_publisher_type(publisher)

        # Compute timeliness statistic
        # Assign frequency score
        if timeliness_frequency_data[publisher][3] == 'Monthly':
            frequency_score = 4
        elif timeliness_frequency_data[publisher][3] == 'Quarterly':
            frequency_score = 3
        elif timeliness_frequency_data[publisher][3] == 'Six-Monthly':
            frequency_score = 2
        elif timeliness_frequency_data[publisher][3] == 'Annual':
            frequency_score = 1
        else: # timeliness_frequency_data[publisher][3] == 'Less than Annual' or something else!
            frequency_score = 0

        # Assign timelag score
        if timeliness_timelag_data[publisher][3] == 'One month':
            timelag_score = 4
        elif timeliness_timelag_data[publisher][3] == 'A quarter':
            timelag_score = 3
        elif timeliness_timelag_data[publisher][3] == 'Six months':
            timelag_score = 2
        elif timeliness_timelag_data[publisher][3] == 'One year':
            timelag_score = 1
        else: # timeliness_timelag_data[publisher][3] == 'More than one year' or something else!
            timelag_score = 0

        # Compute the percentage
        row['timeliness'] = int( (float(frequency_score + timelag_score) / 8) * 100 )


        # Compute forward looking statistic
        # Get the forward looking data for this publisher 
        publisher_forwardlooking_data = forwardlooking_data.next()

        # Convert the data for this publishers 'Percentage of current activities with budgets' fields into integers
        numbers = [ int(x) for x in publisher_forwardlooking_data['year_columns'][2].itervalues() if is_number(x) ]
        
        # Compute and store the mean average for these fields
        row['forwardlooking'] = sum(int(y) for y in numbers) / len(publisher_forwardlooking_data['year_columns'][2])


        # Compute comprehensive statistic
        # Get the comprehensiveness data for this publisher 
        publisher_comprehensiveness_data = comprehensiveness_data.next()

        # Set the comprehensive value to be the summary average for valid data
        row['comprehensive'] = convert_to_int(publisher_comprehensiveness_data['summary_average_valid'])


        # Compute score
        row['score'] = int( (row['timeliness'] + row['forwardlooking'] + row['comprehensive']) / 3 )

        
        # Get coverage statistic
        # Get the coverage data for this publisher 
        publisher_coverage_data = coverage_data.next()

        # Store the coverage data
        row['coverage_adjustment'] = int(publisher_coverage_data['coverage_adjustment'])


        # Compute Coverage-adjusted score
        row['score_coverage_adjusted'] = int( row['score'] * int(row['coverage_adjustment'] / 100) ) 


        # Return a generator object
        yield row
Example #20
0
def generate_row(publisher):
    """Generate coverage table data for a given publisher
    """

    # Store the data for this publisher as new variables
    publisher_stats = get_publisher_stats(publisher)
    transactions_usd = publisher_stats['sum_transactions_by_type_by_year_usd']

    # Create a list for publisher data, and populate it with basic data
    row = {}
    row['publisher'] = publisher
    row['publisher_title'] = publisher_name[publisher]
    row['no_data_flag_red'] = 0
    row['no_data_flag_amber'] = 0
    row['spend_data_error_reported_flag'] = 0
    row['sort_order'] = 0


    # Compute 2014 IATI spend
    iati_2014_spend_total = 0


    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2014 spend total should be based on their
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2014' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['2']['USD']['2014']

        if '2014' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['C']['USD']['2014']

    else:
        # This is a non-DFI publisher
        if '2014' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['3']['USD']['2014']

        if '2014' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['D']['USD']['2014']

        if '2014' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['4']['USD']['2014']

        if '2014' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['E']['USD']['2014']

    # Convert to millions USD
    row['iati_spend_2014'] = round(float( iati_2014_spend_total / 1000000), 2)


    # Compute 2015 IATI spend
    iati_2015_spend_total = 0

    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2015 spend total should be based on their
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2015' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['2']['USD']['2015']

        if '2015' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['C']['USD']['2015']

    else:
        # This is a non-DFI publisher
        if '2015' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['3']['USD']['2015']

        if '2015' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['D']['USD']['2015']

        if '2015' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['4']['USD']['2015']

        if '2015' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['E']['USD']['2015']

    # Convert to millions USD
    row['iati_spend_2015'] = round(float( iati_2015_spend_total / 1000000), 2)

    # Compute 2016 IATI spend
    iati_2016_spend_total = 0

    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2016 spend total should be based on their
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2016' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['2']['USD']['2016']

        if '2016' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['C']['USD']['2016']

    else:
        # This is a non-DFI publisher
        if '2016' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['3']['USD']['2016']

        if '2016' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['D']['USD']['2016']

        if '2016' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['4']['USD']['2016']

        if '2016' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['E']['USD']['2016']

    # Convert to millions USD
    row['iati_spend_2016'] = round(float( iati_2016_spend_total / 1000000), 2)


    # Get reference data
    # Get data from stats files. Set as empty stings if the IATI-Stats code did not find them in the reference data sheet
    data_2014 = publisher_stats['reference_spend_data_usd'].get('2014', {'ref_spend': '', 'not_in_sheet': True})
    data_2015 = publisher_stats['reference_spend_data_usd'].get('2015', {'ref_spend': '', 'official_forecast': '', 'not_in_sheet': True})

    # Compute reference data as $USDm
    row['reference_spend_2014'] = round((float(data_2014['ref_spend']) / 1000000), 2) if is_number(data_2014['ref_spend']) else '-'
    row['reference_spend_2015'] = round((float(data_2015['ref_spend']) / 1000000), 2) if is_number(data_2015['ref_spend']) else '-'
    row['official_forecast_2015'] = round((float(data_2015['official_forecast']) / 1000000), 2) if is_number(data_2015['official_forecast']) else '-'


    # Compute spend ratio score
    # Compile a list of ratios for spend & reference data paired by year
    spend_ratio_candidates = [(row['iati_spend_2014'] / row['reference_spend_2014']) if (row['reference_spend_2014'] > 0) and is_number(row['reference_spend_2014']) else 0,
                              (row['iati_spend_2015'] / row['reference_spend_2015']) if (row['reference_spend_2015'] > 0) and is_number(row['reference_spend_2015']) else 0,
                              (row['iati_spend_2015'] / row['official_forecast_2015']) if (row['official_forecast_2015'] > 0) and is_number(row['official_forecast_2015']) else 0]

    # If there are no annual pairs, add the value of non-matching-year spend / reference data
    if ((row['iati_spend_2014'] == 0 or row['reference_spend_2014'] == '-') and
        (row['iati_spend_2015'] == 0 or row['reference_spend_2015'] == '-') and
        (row['iati_spend_2015'] == 0 or row['official_forecast_2015'] == '-')):
        spend_ratio_candidates.append((row['iati_spend_2015'] / row['reference_spend_2014']) if (row['reference_spend_2014'] > 0) and is_number(row['reference_spend_2014']) else 0)
        spend_ratio_candidates.append((row['iati_spend_2016'] / row['reference_spend_2014']) if (row['reference_spend_2014'] > 0) and is_number(row['reference_spend_2014']) else 0)
        spend_ratio_candidates.append((row['iati_spend_2016'] / row['reference_spend_2015']) if (row['reference_spend_2015'] > 0) and is_number(row['reference_spend_2015']) else 0)


    # Get the maximum value and convert to a percentage
    row['spend_ratio'] = int(round(max(spend_ratio_candidates) * 100))

    return row
Example #21
0
def generate_row(publisher):
    """Generate coverage table data for a given publisher 
    """

    # Store the data for this publisher as new variables
    publisher_stats = get_publisher_stats(publisher)
    transactions_usd = publisher_stats['sum_transactions_by_type_by_year_usd']

    # Create a list for publisher data, and populate it with basic data
    row = {}
    row['publisher'] = publisher
    row['publisher_title'] = publisher_name[publisher]
    row['no_data_flag_red'] = 0
    row['no_data_flag_amber'] = 0
    row['spend_data_error_reported_flag'] = 0
    row['sort_order'] = 0


    # Compute 2014 IATI spend
    iati_2014_spend_total = 0
    

    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2014 spend total should be based on their  
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2014' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['2']['USD']['2014']

        if '2014' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['C']['USD']['2014']

    else:
        # This is a non-DFI publisher
        if '2014' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['3']['USD']['2014']

        if '2014' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['D']['USD']['2014']

        if '2014' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['4']['USD']['2014']

        if '2014' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['E']['USD']['2014']            

    # Convert to millions USD 
    row['iati_spend_2014'] = round(float( iati_2014_spend_total / 1000000), 2)


    # Compute 2015 IATI spend
    iati_2015_spend_total = 0

    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2015 spend total should be based on their  
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2015' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['2']['USD']['2015']

        if '2015' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['C']['USD']['2015']

    else:
        # This is a non-DFI publisher
        if '2015' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['3']['USD']['2015']

        if '2015' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['D']['USD']['2015']

        if '2015' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['4']['USD']['2015']

        if '2015' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['E']['USD']['2015']

    # Convert to millions USD 
    row['iati_spend_2015'] = round(float( iati_2015_spend_total / 1000000), 2)


    # Get reference data 
    # Get data from stats files. Set as empty stings if the IATI-Stats code did not find them in the reference data sheet
    data_2014 = publisher_stats['reference_spend_data_usd'].get('2014', {'ref_spend': '', 'not_in_sheet': True})
    data_2015 = publisher_stats['reference_spend_data_usd'].get('2015', {'ref_spend': '', 'official_forecast': '', 'not_in_sheet': True})

    # Compute reference data as $USDm
    row['reference_spend_2014'] = round((float(data_2014['ref_spend']) / 1000000), 2) if is_number(data_2014['ref_spend']) else '-'
    row['reference_spend_2015'] = round((float(data_2015['ref_spend']) / 1000000), 2) if is_number(data_2015['ref_spend']) else '-'
    row['official_forecast_2015'] = round((float(data_2015['official_forecast']) / 1000000), 2) if is_number(data_2015['official_forecast']) else '-'


    # Compute spend ratio score
    # Compile a list of ratios for spend & reference data paired by year
    spend_ratio_candidates = [(row['iati_spend_2014'] / row['reference_spend_2014']) if (row['reference_spend_2014'] > 0) and is_number(row['reference_spend_2014']) else 0, 
                              (row['iati_spend_2015'] / row['reference_spend_2015']) if (row['reference_spend_2015'] > 0) and is_number(row['reference_spend_2015']) else 0,
                              (row['iati_spend_2015'] / row['official_forecast_2015']) if (row['official_forecast_2015'] > 0) and is_number(row['official_forecast_2015']) else 0]
    
    # If there are no annual pairs, add the value of 2015 spend / 2014 reference data
    if ((row['iati_spend_2014'] == 0 or row['reference_spend_2014'] == '-') 
        and (row['iati_spend_2015'] == 0 or row['reference_spend_2015'] == '-') 
        and (row['iati_spend_2015'] == 0 or row['official_forecast_2015'] == '-')):
        spend_ratio_candidates.append((row['iati_spend_2015'] / row['reference_spend_2014']) if (row['reference_spend_2014'] > 0) and is_number(row['reference_spend_2014']) else 0)

    # Get the maximum value and convert to a percentage
    row['spend_ratio'] = int(round(max(spend_ratio_candidates) * 100))


    # Compute coverage score and raise to the top of its quintile
    # or set to default 20% where there is no data, or a data error is reported
    if publisher_stats['reference_spend_data_usd'].get('spend_data_error_reported', False):
        # For publishers where a data error is reported, set their score to 20%
        row['coverage_adjustment'] = 20
        row['spend_data_error_reported_flag'] = 1
        row['sort_order'] = 3

    elif all([row['reference_spend_2014'] == '-', row['reference_spend_2015'] == '-', row['official_forecast_2015'] == '-']):
        # For publishers where no reference data has been found, set their score to 20%
        row['coverage_adjustment'] = 20

        if data_2014.get('not_in_sheet', False) and data_2015.get('not_in_sheet', False):
            # This is a new publisher, who was not known when reference data was collected
            row['no_data_flag_amber'] = 1
            row['sort_order'] = 2
        else:
            # This is a known publisher, who appears in the reference data sheet (albeit with no data)
            row['no_data_flag_red'] = 1
            row['sort_order'] = 1

    elif row['spend_ratio'] > 120 and not publisher_stats['reference_spend_data_usd'].get('DAC', False):
        # Suggestion that if apend ratio is over 100%, then generally something is wrong with the data
        # Margin of 20% leeway given otherwise bumping coverage adjustment down to 20% due to data quality issues.
        # Note that this does not apply to DAC publishers
        # Full detail: https://github.com/IATI/IATI-Dashboard/issues/400
        row['coverage_adjustment'] = 20

    elif row['spend_ratio'] >= 80:
        row['coverage_adjustment'] = 100

    elif row['spend_ratio'] >= 60:
        row['coverage_adjustment'] = 80

    elif row['spend_ratio'] >= 40:
        row['coverage_adjustment'] = 60

    else:
        row['coverage_adjustment'] = 40

    return row
Example #22
0
def generate_row(publisher):
    """Generate coverage table data for a given publisher
    """

    # Store the data for this publisher as new variables
    publisher_stats = get_publisher_stats(publisher)
    transactions_usd = publisher_stats['sum_transactions_by_type_by_year_usd']

    # Create a list for publisher data, and populate it with basic data
    row = {}
    row['publisher'] = publisher
    row['publisher_title'] = publisher_name[publisher]
    row['no_data_flag_red'] = 0
    row['no_data_flag_amber'] = 0
    row['spend_data_error_reported_flag'] = 0
    row['sort_order'] = 0

    # Compute 2014 IATI spend
    iati_2014_spend_total = 0

    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2014 spend total should be based on their
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2014' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['2']['USD']['2014']

        if '2014' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['C']['USD']['2014']

    else:
        # This is a non-DFI publisher
        if '2014' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['3']['USD']['2014']

        if '2014' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['D']['USD']['2014']

        if '2014' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['4']['USD']['2014']

        if '2014' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2014_spend_total += transactions_usd['E']['USD']['2014']

    # Convert to millions USD
    row['iati_spend_2014'] = round(float(iati_2014_spend_total / 1000000), 2)

    # Compute 2015 IATI spend
    iati_2015_spend_total = 0

    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2015 spend total should be based on their
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2015' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['2']['USD']['2015']

        if '2015' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['C']['USD']['2015']

    else:
        # This is a non-DFI publisher
        if '2015' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['3']['USD']['2015']

        if '2015' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['D']['USD']['2015']

        if '2015' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['4']['USD']['2015']

        if '2015' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2015_spend_total += transactions_usd['E']['USD']['2015']

    # Convert to millions USD
    row['iati_spend_2015'] = round(float(iati_2015_spend_total / 1000000), 2)

    # Compute 2016 IATI spend
    iati_2016_spend_total = 0

    if publisher in dfi_publishers:
        # If this publisher is a DFI, then their 2016 spend total should be based on their
        # commitment transactions only. See https://github.com/IATI/IATI-Dashboard/issues/387
        if '2016' in transactions_usd.get('2', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['2']['USD']['2016']

        if '2016' in transactions_usd.get('C', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['C']['USD']['2016']

    else:
        # This is a non-DFI publisher
        if '2016' in transactions_usd.get('3', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['3']['USD']['2016']

        if '2016' in transactions_usd.get('D', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['D']['USD']['2016']

        if '2016' in transactions_usd.get('4', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['4']['USD']['2016']

        if '2016' in transactions_usd.get('E', {}).get('USD', {}):
            iati_2016_spend_total += transactions_usd['E']['USD']['2016']

    # Convert to millions USD
    row['iati_spend_2016'] = round(float(iati_2016_spend_total / 1000000), 2)

    # Get reference data
    # Get data from stats files. Set as empty stings if the IATI-Stats code did not find them in the reference data sheet
    data_2014 = publisher_stats['reference_spend_data_usd'].get(
        '2014', {
            'ref_spend': '',
            'not_in_sheet': True
        })
    data_2015 = publisher_stats['reference_spend_data_usd'].get(
        '2015', {
            'ref_spend': '',
            'official_forecast': '',
            'not_in_sheet': True
        })

    # Compute reference data as $USDm
    row['reference_spend_2014'] = round(
        (float(data_2014['ref_spend']) /
         1000000), 2) if is_number(data_2014['ref_spend']) else '-'
    row['reference_spend_2015'] = round(
        (float(data_2015['ref_spend']) /
         1000000), 2) if is_number(data_2015['ref_spend']) else '-'
    row['official_forecast_2015'] = round(
        (float(data_2015['official_forecast']) /
         1000000), 2) if is_number(data_2015['official_forecast']) else '-'

    # Compute spend ratio score
    # Compile a list of ratios for spend & reference data paired by year
    spend_ratio_candidates = [
        (row['iati_spend_2014'] / row['reference_spend_2014']) if
        (row['reference_spend_2014'] > 0)
        and is_number(row['reference_spend_2014']) else 0,
        (row['iati_spend_2015'] / row['reference_spend_2015']) if
        (row['reference_spend_2015'] > 0)
        and is_number(row['reference_spend_2015']) else 0,
        (row['iati_spend_2015'] / row['official_forecast_2015']) if
        (row['official_forecast_2015'] > 0)
        and is_number(row['official_forecast_2015']) else 0
    ]

    # If there are no annual pairs, add the value of non-matching-year spend / reference data
    if ((row['iati_spend_2014'] == 0 or row['reference_spend_2014'] == '-') and
        (row['iati_spend_2015'] == 0 or row['reference_spend_2015'] == '-') and
        (row['iati_spend_2015'] == 0 or row['official_forecast_2015'] == '-')):
        spend_ratio_candidates.append((
            row['iati_spend_2015'] / row['reference_spend_2014']
        ) if (row['reference_spend_2014'] > 0
              ) and is_number(row['reference_spend_2014']) else 0)
        spend_ratio_candidates.append((
            row['iati_spend_2016'] / row['reference_spend_2014']
        ) if (row['reference_spend_2014'] > 0
              ) and is_number(row['reference_spend_2014']) else 0)
        spend_ratio_candidates.append((
            row['iati_spend_2016'] / row['reference_spend_2015']
        ) if (row['reference_spend_2015'] > 0
              ) and is_number(row['reference_spend_2015']) else 0)

    # Get the maximum value and convert to a percentage
    row['spend_ratio'] = int(round(max(spend_ratio_candidates) * 100))

    # Compute coverage score and raise to the top of its quintile
    # or set to default 20% where there is no data, or a data error is reported
    if publisher_stats['reference_spend_data_usd'].get(
            'spend_data_error_reported', False):
        # For publishers where a data error is reported, set their score to 20%
        row['coverage_adjustment'] = 20
        row['spend_data_error_reported_flag'] = 1
        row['sort_order'] = 3

    elif all([
            row['reference_spend_2014'] == '-',
            row['reference_spend_2015'] == '-',
            row['official_forecast_2015'] == '-'
    ]):
        # For publishers where no reference data has been found, set their score to 20%
        row['coverage_adjustment'] = 20

        if data_2014.get('not_in_sheet', False) and data_2015.get(
                'not_in_sheet', False):
            # This is a new publisher, who was not known when reference data was collected
            row['no_data_flag_amber'] = 1
            row['sort_order'] = 2
        else:
            # This is a known publisher, who appears in the reference data sheet (albeit with no data)
            row['no_data_flag_red'] = 1
            row['sort_order'] = 1

    elif row['spend_ratio'] > 120 and not publisher_stats[
            'reference_spend_data_usd'].get('DAC', False):
        # Suggestion that if apend ratio is over 100%, then generally something is wrong with the data
        # Margin of 20% leeway given otherwise bumping coverage adjustment down to 20% due to data quality issues.
        # Note that this does not apply to DAC publishers
        # Full detail: https://github.com/IATI/IATI-Dashboard/issues/400
        row['coverage_adjustment'] = 20

    elif row['spend_ratio'] >= 80:
        row['coverage_adjustment'] = 100

    elif row['spend_ratio'] >= 60:
        row['coverage_adjustment'] = 80

    elif row['spend_ratio'] >= 40:
        row['coverage_adjustment'] = 60

    else:
        row['coverage_adjustment'] = 40

    return row
Example #23
0
def generate_row(publisher):
    """Generate forward-looking table data for a given publisher
    """

    # Store the data for this publisher as a new variable
    publisher_stats = get_publisher_stats(publisher)

    # Create a list for publisher data, and populate it with basic data
    row = {}
    row['publisher'] = publisher
    row['publisher_title'] = publisher_name[publisher]
    row['year_columns'] = [{}, {}, {}]
    row['budget_not_provided'] = False
    # Work with hierarchies
    by_hierarchy = publisher_stats['by_hierarchy']
    hierarchies_with_nonzero_budgets = [
        h for h, stats in by_hierarchy.items() if not all(
            x == 0
            for x in stats['forwardlooking_activities_with_budgets'].values())
    ]

    # Flag if budgets on current activities are reported at more than one hierarchy
    row['flag'] = len(hierarchies_with_nonzero_budgets) > 1

    hierarchies_with_budget_not_provided = [
        h for h, stats in by_hierarchy.items()
        if not all(x == 0 for x in
                   stats['forwardlooking_activities_with_budget_not_provided'].
                   values())
    ]

    # Loop over each of the three years (i.e. this year and the following two years) to generate the statistics for the table
    for year in years:
        if (len(hierarchies_with_budget_not_provided) > 0):
            row['budget_not_provided'] = True
        # If 'forwardlooking_activities_current' and 'forwardlooking_activities_with_budgets' or 'forwardlooking_activities_with_budget_not_provided' are in the bottom hierarchy
        if 'forwardlooking_activities_current' in publisher_stats[
                'bottom_hierarchy'] and (
                    'forwardlooking_activities_with_budgets'
                    in publisher_stats['bottom_hierarchy']
                    or 'forwardlooking_activities_with_budget_not_provided'
                    in publisher_stats['bottom_hierarchy']):
            if len(hierarchies_with_nonzero_budgets) != 1:
                # If budgets are at more than one hierarchy (or no hierarchies), just use activities at all hierarchies
                row['year_columns'][0][year] = publisher_stats[
                    'forwardlooking_activities_current'].get(year) or 0
                row['year_columns'][1][year] = publisher_stats[
                    'forwardlooking_activities_with_budgets'].get(year) or 0
                if row['budget_not_provided']:
                    row['year_columns'][1][year] += publisher_stats[
                        'forwardlooking_activities_with_budget_not_provided'].get(
                            year) or 0
            else:
                # Else, use the hierarchy which they are reported at
                row['year_columns'][0][year] = by_hierarchy[
                    hierarchies_with_nonzero_budgets[0]][
                        'forwardlooking_activities_current'].get(year) or 0
                row['year_columns'][1][year] = by_hierarchy[
                    hierarchies_with_nonzero_budgets[0]][
                        'forwardlooking_activities_with_budgets'].get(
                            year) or 0
                if row['budget_not_provided']:
                    row['year_columns'][1][year] += by_hierarchy[
                        hierarchies_with_nonzero_budgets[0]][
                            'forwardlooking_activities_with_budget_not_provided'].get(
                                year) or 0

            if not int(row['year_columns'][0][year]):
                row['year_columns'][2][year] = '-'
            else:
                row['year_columns'][2][year] = int(
                    round(
                        float(row['year_columns'][1][year]) /
                        float(row['year_columns'][0][year]) * 100))
        else:
            # Else if either 'forwardlooking_activities_current' or 'forwardlooking_activities_with_budgets' are not in the bottom hierarchy, set data zero
            # This should only occur if a publisher has 0 activities
            row['year_columns'][0][year] = '0'
            row['year_columns'][1][year] = '0'
            row['year_columns'][2][year] = '-'

    return row
def table():
    """Generate data for the publisher forward-looking table
    """

    # Store timeliness data in variable
    timeliness_frequency_data = timeliness.publisher_frequency_dict()
    timeliness_timelag_data = timeliness.publisher_timelag_dict()

    # Loop over each publisher
    for publisher_title, publisher in publishers_ordered_by_title:

        # Store the data for this publisher as a new variable
        publisher_stats = get_publisher_stats(publisher)

        # Skip if all activities from this publisher are secondary reported
        if publisher in secondary_publishers:
            continue

        # Create a list for publisher data, and populate it with basic data
        row = {}
        row['publisher'] = publisher
        row['publisher_title'] = publisher_title
        row['publisher_type'] = common.get_publisher_type(publisher)['name']

        # Compute timeliness statistic
        # Assign frequency score
        # Get initial frequency assessment, or use empty set in the case where the publisher is not found
        frequency_assessment_data = timeliness_frequency_data.get(
            publisher, ())
        frequency_assessment = None if len(
            frequency_assessment_data) < 4 else frequency_assessment_data[3]
        if frequency_assessment == 'Monthly':
            frequency_score = 4
        elif frequency_assessment == 'Quarterly':
            frequency_score = 3
        elif frequency_assessment == 'Six-Monthly':
            frequency_score = 2
        elif frequency_assessment == 'Annual':
            frequency_score = 1
        else:  # frequency_assessment == 'Less than Annual' or something else!
            frequency_score = 0

        # Assign timelag score
        # Get initial timelag assessment, or use empty set in the case where the publisher is not found
        timelag_assessment_data = timeliness_timelag_data.get(publisher, ())
        timelag_assessment = None if len(
            timelag_assessment_data) < 4 else timelag_assessment_data[3]
        if timelag_assessment == 'One month':
            timelag_score = 4
        elif timelag_assessment == 'A quarter':
            timelag_score = 3
        elif timelag_assessment == 'Six months':
            timelag_score = 2
        elif timelag_assessment == 'One year':
            timelag_score = 1
        else:  # timelag_assessment == 'More than one year' or something else!
            timelag_score = 0

        # Compute the percentage
        row['timeliness'] = int(
            round((float(frequency_score + timelag_score) / 8) * 100))

        # Compute forward-looking statistic
        # Get the forward-looking data for this publisher
        publisher_forwardlooking_data = forwardlooking.generate_row(publisher)

        # Convert the data for this publishers 'Percentage of current activities with budgets' fields into integers
        numbers = [
            int(x) for x in publisher_forwardlooking_data['year_columns']
            [2].itervalues() if is_number(x)
        ]

        # Compute and store the mean average for these fields
        row['forwardlooking'] = sum(int(round(y)) for y in numbers) / len(
            publisher_forwardlooking_data['year_columns'][2])

        # Compute comprehensive statistic
        # Get the comprehensiveness data for this publisher
        publisher_comprehensiveness_data = comprehensiveness.generate_row(
            publisher)

        # Set the comprehensive value to be the summary average for valid data
        row['comprehensive'] = convert_to_int(
            publisher_comprehensiveness_data['summary_average_valid'])

        # Compute score
        row['score'] = int(
            round(
                float(row['timeliness'] + row['forwardlooking'] +
                      row['comprehensive']) / 3))

        # Return a generator object
        yield row