def sout(self): rc = self.rc if rc.filter: collection = key_value_pair_filter(self.gtx["grants"], rc.filter) else: collection = self.gtx["grants"] grants = [] if rc.date: desired_date = date_parser.parse(rc.date).date() else: desired_date = dt.date.today() for grant in collection: if rc.current and not is_current(grant, now=desired_date): continue if not rc.verbose: if grant.get("alias") not in BLACKLIST: grants.append(grant) else: grants.append(grant) # Sort the grants by end date in reverse chronological order grants.sort(key=lambda k: get_dates(k).get('end_date'), reverse=True) if rc.keys: results = (collection_str(grants, rc.keys)) print(results, end="") return for g in grants: print("{}, awardnr: {}, acctn: {}, {} to {}".format( g.get('alias', ''), g.get('awardnr', ''), g.get('account', ''), get_dates(g).get('begin_date'), get_dates(g).get('end_date'))) return
def sout(self): rc = self.rc list_search = [] collection = self.gtx["contacts"] if rc.name: list_search.extend(["name", rc.name]) if rc.inst: list_search.extend(["institution", rc.inst]) if rc.notes: list_search.extend(["notes", rc.notes]) if rc.filter: list_search.extend(rc.filter) filtered_contacts_id = (search_collection(collection, list_search)).strip(' \n') filtered_contacts_id = list(filtered_contacts_id.split(' \n')) if rc.date: date_list = [] temp_dat = date_parser.parse(rc.date).date() temp_dict = {"begin_date": (temp_dat - dateutil.relativedelta.relativedelta( months=int(rc.range))).isoformat(), "end_date": (temp_dat + dateutil.relativedelta.relativedelta( months=int(rc.range))).isoformat()} for contact in collection: curr_d = get_dates(contact)['date'] if is_current(temp_dict, now=curr_d): date_list.append(contact.get('_id')) filtered_contacts_id = [value for value in filtered_contacts_id if value in date_list] filtered_contacts = [] string_contacts = '' for contact in collection: if contact.get('_id') in filtered_contacts_id: filtered_contacts.append(contact) institution = contact.get('institution') institution_name = fuzzy_retrieval(self.gtx['institutions'], ['name', '_id', 'aka'], institution) if institution_name: contact['institution'] = institution_name.get('name') if rc.verbose: contact_str = f"{contact.get('name')}\n" for k in ['_id', 'email', 'institution', 'department', 'notes', 'aka']: if contact.get(k): if isinstance(contact.get(k), list): lst_expanded = '\n -'.join(map(str, contact.get(k))) contact_str += f" {k}:\n -{lst_expanded}\n" else: contact_str += f" {k}: {contact.get(k)}\n" string_contacts += contact_str else: string_contacts += f"{contact.get('name')} | {contact.get('_id')} |" \ f" institution: {contact.get('institution')} |" \ f" email: {contact.get('email', 'missing')}\n" print(string_contacts.strip('\n')) return
def sout(self): rc = self.rc grants = [] if rc.date: desired_date = date_parser.parse(rc.date).date() else: desired_date = dt.date.today() for grant in self.gtx["grants"]: if rc.current and not is_current(grant, now=desired_date): continue grants.append(grant) # Sort the grants by end date in reverse chronological order grants.sort(key=lambda k: get_dates(k).get('end_date'), reverse=True) for g in grants: print("{}, awardnr: {}, acctn: {}, {} to {}".format( g.get('alias', ''), g.get('awardnr', ''), g.get('account', ''), get_dates(g).get('begin_date'), get_dates(g).get('end_date'))) return
def sout(self): rc = self.rc if rc.filter: collection = key_value_pair_filter(self.gtx["grants"], rc.filter) else: collection = self.gtx["grants"] grants = [] if rc.date: desired_date = date_parser.parse(rc.date).date() else: desired_date = dt.date.today() for grant in collection: # fixme maybe change this logic and change the name of "year" in proposal to "submitted_year" or sthg if grant.get( 'year' ): # year is used for prop submission but breaks get_dates del grant['year'] if rc.current and not is_current(grant, now=desired_date): continue if not rc.verbose: if grant.get("alias") not in BLACKLIST: grants.append(grant) else: grants.append(grant) # Sort the grants by end date in reverse chronological order grants.sort(key=lambda k: get_dates(k).get('end_date'), reverse=True) if rc.keys: results = (collection_str(grants, rc.keys)) print(results, end="") return for g in grants: print("{}, awardnr: {}, acctn: {}, {} to {}".format( g.get('alias', ''), g.get('awardnr', ''), g.get('account', ''), get_dates(g).get('begin_date'), get_dates(g).get('end_date'))) return
def latex(self): """Render latex template""" for group in self.gtx["groups"]: grp = group["_id"] pi = fuzzy_retrieval(self.gtx["people"], ["aka", "name"], group["pi_name"]) pinames = pi["name"].split() piinitialslist = [i[0] for i in pinames] pi['initials'] = "".join(piinitialslist).upper() grants = merge_collections(self.gtx["proposals"], self.gtx["grants"], "proposal_id") for g in grants: for person in g["team"]: rperson = fuzzy_retrieval(self.gtx["people"], ["aka", "name"], person["name"]) if rperson: person["name"] = rperson["name"] if g.get('budget'): amounts = [i.get('amount') for i in g.get('budget')] g['subaward_amount'] = sum(amounts) current_grants = [dict(g) for g in grants if is_current(g)] current_grants, _, _ = filter_grants(current_grants, {pi["name"]}, pi=False, multi_pi=True) for g in current_grants: if g.get('budget'): amounts = [i.get('amount') for i in g.get('budget')] g['subaward_amount'] = sum(amounts) pending_grants = [ g for g in self.gtx["proposals"] if is_pending(g["status"]) ] for g in pending_grants: for person in g["team"]: rperson = fuzzy_retrieval(self.gtx["people"], ["aka", "name"], person["name"]) if rperson: person["name"] = rperson["name"] pending_grants, _, _ = filter_grants(pending_grants, {pi["name"]}, pi=False, multi_pi=True) grants = pending_grants + current_grants for grant in grants: grant.update( award_start_date="{2}/{1}/{0}".format( grant["begin_day"], month_to_int(grant["begin_month"]), grant["begin_year"], ), award_end_date="{2}/{1}/{0}".format( grant["end_day"], month_to_int(grant["end_month"]), grant["end_year"], ), ) badids = [ i["_id"] for i in current_grants if not i.get('cpp_info').get('cppflag', "") ] iter = copy(current_grants) for grant in iter: if grant["_id"] in badids: current_grants.remove(grant) piname = HumanName(pi["name"]) outfile = "current-pending-{}-{}".format(grp, piname.last.lower()) self.render( "current_pending.tex", outfile + ".tex", pi=pi, pending=pending_grants, current=current_grants, pi_upper=pi["name"].upper(), group=group, ) self.pdf(outfile)
def latex(self): """Render latex template""" rc = self.rc if not rc.people: raise RuntimeError("ERROR: please rerun specifying --people name") if not rc.from_date: raise RuntimeError("ERROR: please rerun specifying --from") build_target = get_id_from_name( all_docs_from_collection(rc.client, "people"), rc.people[0]) begin_year = int(rc.from_date.split("-")[0]) begin_period = date_parser.parse(rc.from_date).date() pre_begin_period = begin_period - relativedelta(years=1) if rc.to_date: to_date = date_parser.parse(rc.to_date).date() end_period = to_date post_end_period = to_date + relativedelta(years=1) else: end_period = begin_period + relativedelta(years=1) - relativedelta( days=1) post_end_period = begin_period + relativedelta( years=2) - relativedelta(days=1) me = [p for p in self.gtx["people"] if p["_id"] == build_target][0] me["begin_period"] = dt.date.strftime(begin_period, "%m/%d/%Y") me["begin_period"] = dt.date.strftime(begin_period, "%m/%d/%Y") me["pre_begin_period"] = dt.date.strftime(pre_begin_period, "%m/%d/%Y") me["end_period"] = dt.date.strftime(end_period, "%m/%d/%Y") me["post_end_period"] = dt.date.strftime(post_end_period, "%m/%d/%Y") projs = filter_projects(self.gtx["projects"], set([build_target]), group="bg") ######### # highlights ######### for proj in projs: if proj.get('highlights'): proj["current_highlights"] = False for highlight in proj.get('highlights'): highlight_date = dt.date( highlight.get("year"), month_to_int(highlight.get("month", 1)), 1) if highlight_date > begin_period and highlight_date < end_period: highlight["is_current"] = True proj["current_highlights"] = True ######### # current and pending ######### pi = fuzzy_retrieval(self.gtx["people"], ["aka", "name", "_id"], build_target) # pi['initials'] = "SJLB" grants = merge_collections_superior(self.gtx["proposals"], self.gtx["grants"], "proposal_id") for g in grants: for person in g["team"]: rperson = fuzzy_retrieval(self.gtx["people"], ["aka", "name"], person["name"]) if rperson: person["name"] = rperson["name"] if g.get('budget'): amounts = [i.get('amount') for i in g.get('budget')] g['subaward_amount'] = sum(amounts) current_grants = [dict(g) for g in grants if is_current(g)] current_grants, _, _ = filter_grants(current_grants, {pi["name"]}, pi=False, multi_pi=True) pending_grants = [ g for g in self.gtx["proposals"] if g["status"] == "pending" ] for g in pending_grants: for person in g["team"]: rperson = fuzzy_retrieval(self.gtx["people"], ["aka", "name"], person["name"]) if rperson: person["name"] = rperson["name"] pending_grants, _, _ = filter_grants(pending_grants, {pi["name"]}, pi=False, multi_pi=True) grants = pending_grants + current_grants for grant in grants: grant.update( award_start_date="{2}/{1}/{0}".format( grant["begin_day"], month_to_int(grant["begin_month"]), grant["begin_year"], ), award_end_date="{2}/{1}/{0}".format( grant["end_day"], month_to_int(grant["end_month"]), grant["end_year"], ), ) badids = [ i["_id"] for i in current_grants if not i['cpp_info'].get('cppflag', "") ] iter = copy(current_grants) for grant in iter: if grant["_id"] in badids: current_grants.remove(grant) ######### # end current and pending ######### ######### # advising ######### undergrads = filter_employment_for_advisees(self.gtx["people"], begin_period, "undergrad") masters = filter_employment_for_advisees(self.gtx["people"], begin_period, "ms") currents = filter_employment_for_advisees(self.gtx["people"], begin_period, "phd") graduateds = filter_employment_for_advisees( self.gtx["people"], begin_period.replace(year=begin_year - 5), "phd") postdocs = filter_employment_for_advisees(self.gtx["people"], begin_period, "postdoc") visitors = filter_employment_for_advisees(self.gtx["people"], begin_period, "visitor-unsupported") iter = deepcopy(graduateds) for g in iter: if g.get("active"): graduateds.remove(g) iter = deepcopy(currents) for g in iter: if not g.get("active"): currents.remove(g) ###################### # service ##################### mego = deepcopy(me) dept_service = filter_service([mego], begin_period, "department") mego = deepcopy(me) school_service = filter_service([mego], begin_period, "school") mego = deepcopy(me) uni_service = filter_service([mego], begin_period, "university") uni_service.extend(school_service) mego = deepcopy(me) prof_service = filter_service([mego], begin_period, "profession") mego = deepcopy(me) outreach = filter_service([mego], begin_period, "outreach") mego = deepcopy(me) lab = filter_facilities([mego], begin_period, "research") mego = deepcopy(me) shared = filter_facilities([mego], begin_period, "shared") mego = deepcopy(me) fac_other = filter_facilities([mego], begin_period, "other") mego = deepcopy(me) fac_teaching = filter_facilities([mego], begin_period, "teaching") mego = deepcopy(me) fac_wishlist = filter_facilities([mego], begin_period, "research_wish", verbose=False) mego = deepcopy(me) tch_wishlist = filter_facilities([mego], begin_period, "teaching_wish") mego = deepcopy(me) curric_dev = filter_activities([mego], begin_period, "teaching") mego = deepcopy(me) other_activities = filter_activities([mego], begin_period, "other") ########################## # Presentation list ########################## keypres = filter_presentations(self.gtx["people"], self.gtx["presentations"], self.gtx["institutions"], build_target, types=["award", "plenary", "keynote"], since=begin_period, before=end_period, statuses=["accepted"]) invpres = filter_presentations(self.gtx["people"], self.gtx["presentations"], self.gtx["institutions"], build_target, types=["invited"], since=begin_period, before=end_period, statuses=["accepted"]) sempres = filter_presentations(self.gtx["people"], self.gtx["presentations"], self.gtx["institutions"], build_target, types=["colloquium", "seminar"], since=begin_period, before=end_period, statuses=["accepted"]) declpres = filter_presentations(self.gtx["people"], self.gtx["presentations"], self.gtx["institutions"], build_target, types=["all"], since=begin_period, before=end_period, statuses=["declined"]) ######################### # Awards ######################### ahs = awards(me, since=begin_period) ######################## # Publications ######################## names = frozenset(me.get("aka", []) + [me["name"]]) pubs = filter_publications(all_docs_from_collection( rc.client, "citations"), names, reverse=True, bold=False, since=begin_period) bibfile = make_bibtex_file(pubs, pid=me["_id"], person_dir=self.bldir) articles = [prc for prc in pubs if prc.get("entrytype") in "article"] nonarticletypes = [ "book", "inbook", "proceedings", "inproceedings", "incollection", "unpublished", "phdthesis", "misc" ] nonarticles = [ prc for prc in pubs if prc.get("entrytype") in nonarticletypes ] peer_rev_conf_pubs = [prc for prc in pubs if prc.get("peer_rev_conf")] pubiter = deepcopy(pubs) for prc in pubiter: if prc.get("peer_rev_conf"): peer_rev_conf_pubs = prc pubs.pop(prc) ############## # TODO: add Current Projects to Research summary section ############## ############# # IP ############# patents = filter_patents(self.gtx["patents"], self.gtx["people"], build_target, since=begin_period) licenses = filter_licenses(self.gtx["patents"], self.gtx["people"], build_target, since=begin_period) ############# # hindex ############# hindex = sorted(me["hindex"], key=doc_date_key).pop() ######################### # render ######################### self.render( "columbia_annual_report.tex", "billinge-ann-report.tex", pi=pi, p=me, projects=projs, pending=pending_grants, current=current_grants, undergrads=undergrads, masters=masters, currentphds=currents, graduatedphds=graduateds, postdocs=postdocs, visitors=visitors, dept_service=dept_service, uni_service=uni_service, prof_service=prof_service, outreach=outreach, lab=lab, shared=shared, facilities_other=fac_other, fac_teaching=fac_teaching, fac_wishlist=fac_wishlist, tch_wishlist=tch_wishlist, curric_dev=curric_dev, other_activities=other_activities, keypres=keypres, invpres=invpres, sempres=sempres, declpres=declpres, sentencecase=sentencecase, monthstyle=month_fullnames, ahs=ahs, pubs=articles, nonarticles=nonarticles, peer_rev_conf_pubs=peer_rev_conf_pubs, bibfile=bibfile, patents=patents, licenses=licenses, hindex=hindex, ) self.pdf("billinge-ann-report")
def sout(self): rc = self.rc outdated, depleted, underspent, overspent = [], [], [], [] all_appts = collect_appts(self.gtx['people']) if rc.no_gui: matplotlib.use('agg') for person in self.gtx['people']: appts = collect_appts([person]) if not appts: continue this_begin = min(get_dates(appt)['begin_date'] for appt in appts) this_end = max(get_dates(appt)['end_date'] for appt in appts) is_fully_appointed(person, this_begin, this_end) for appt in appts: if appt.get("grant") in BLACKLIST: print(appt.get("grant")) continue grant = rc.client.find_one(rc.database, "grants", {"_id": appt.get("grant")}) if not grant: raise RuntimeError( " grant: {}, person: {}, appointment: {}, grant not found in grants database" .format(appt.get("grant"), person.get("_id"), appt.get("_id"))) prop = rc.client.find_one(rc.database, "proposals", {"_id": grant.get("proposal_id")}) if prop.get('year'): del prop['year'] grant_begin = get_dates(grant)['begin_date'] if grant.get('begin_date') or grant.get('begin_year') \ else get_dates(prop)['begin_date'] grant_end = get_dates(grant)['end_date'] if grant.get('end_date') or grant.get('end_year') \ else get_dates(prop)['end_date'] grant.update({ 'begin_date': grant_begin, 'end_date': grant_end }) appt_begin, appt_end = get_dates( appt)['begin_date'], get_dates(appt)['end_date'] this_burn = grant_burn(grant, all_appts, grant_begin, grant_end, begin_date=appt_begin, end_date=appt_end) timespan = appt_end - appt_begin outdated_period, depleted_period = False, False for x in range(timespan.days + 1): day = appt_begin + relativedelta(days=x) if not outdated_period: if not is_current(grant, now=day): outdated.append( " person: {}, appointment: {}, grant: {},\n" " from {} until {}".format( person.get('_id'), appt.get('_id'), grant.get('_id'), str(day), str( min(appt_end, get_dates(grant)['begin_date'])))) outdated_period = True if not depleted_period and not outdated_period: day_burn = 0 if appt.get('type') == 'gra': day_burn = this_burn[x].get('student_days') elif appt.get('type') == 'pd': day_burn = this_burn[x].get('postdoc_days') elif appt.get('type') == 'ss': day_burn = this_burn[x].get('ss_days') if day_burn < 0: depleted.append( " person: {}, appointment: {}, grant: {},\n" " from {} until {}".format( person.get('_id'), appt.get('_id'), grant.get('_id'), str(day), str(appt_end))) depleted_period = True datearray, cum_student, cum_pd, cum_ss = [], None, None, None if not rc.no_plot: grants_begin, grants_end = None, None for grant in self.gtx['grants']: if grant.get('_id') in BLACKLIST or grant.get( 'alias') in BLACKLIST: continue prop = rc.client.find_one(rc.database, "proposals", {"_id": grant.get("proposal_id")}) if prop.get('year'): del prop['year'] grant_begin = get_dates(grant)['begin_date'] if grant.get('begin_date') or grant.get('begin_year') \ else get_dates(prop)['begin_date'] grant_end = get_dates(grant)['end_date'] if grant.get('end_date') or grant.get('end_year') \ else get_dates(prop)['end_date'] if not grants_begin or grant_begin < grants_begin: grants_begin = grant_begin if not grants_end or grant_end > grants_end: grants_end = grant_end grants_timespan = grants_end - grants_begin for x in range(grants_timespan.days + 1): datearray.append(grants_begin + relativedelta(days=x)) cum_student, cum_pd, cum_ss = [0.0] * len(datearray), [ 0.0 ] * len(datearray), [0.0] * len(datearray) for grant in self.gtx["grants"]: if grant.get('_id') in BLACKLIST or grant.get( 'alias') in BLACKLIST: continue prop = rc.client.find_one(rc.database, "proposals", {"_id": grant.get("proposal_id")}) if prop.get('year'): del prop['year'] grant_begin = get_dates(grant)['begin_date'] if grant.get('begin_date') or grant.get('begin_year') \ else get_dates(prop)['begin_date'] grant_end = get_dates(grant)['end_date'] if grant.get('end_date') or grant.get('end_year') \ else get_dates(prop)['end_date'] grant.update({'begin_date': grant_begin, 'end_date': grant_end}) grant_amounts = grant_burn(grant, all_appts, grant_begin, grant_end) end_amount = grant_amounts[-1].get('student_days') + grant_amounts[-1].get('postdoc_days') + \ grant_amounts[-1].get('ss_days') if end_amount > 30.5: underspent.append( " {}: grant: {}, underspend amount: {} months".format( str(grant_end), grant.get('_id'), round(end_amount / 30.5, 2))) elif end_amount < -30.5: overspent.append( " {}: grant: {}, overspend amount: {} months".format( str(grant_end), grant.get('_id'), round(end_amount / 30.5, 2))) if not rc.no_plot: grant_dates = [] grant_duration = (grant_end - grant_begin).days + 1 this_student, this_pd, this_ss = [0.0] * grant_duration, [ 0.0 ] * grant_duration, [0.0] * grant_duration counter = 0 for x in range(len(datearray)): if is_current(grant, now=datearray[x]): grant_dates.append(datearray[x]) this_student[counter] = grant_amounts[counter].get( 'student_days') cum_student[x] += grant_amounts[counter].get( 'student_days') this_pd[counter] = grant_amounts[counter].get( 'postdoc_days') cum_pd[x] += grant_amounts[counter].get('postdoc_days') this_ss[counter] = grant_amounts[counter].get( 'ss_days') cum_ss[x] += grant_amounts[counter].get('ss_days') counter += 1 plotter(grant_dates, student=this_student, pd=this_pd, ss=this_ss, title=f"{grant.get('_id')}") if outdated: print("appointments on outdated grants:") for appt in outdated: print(appt) if depleted: print("appointments on depleted grants:") for appt in depleted: print(appt) if underspent: print("underspent grants:") for grant in underspent: print(grant) if overspent: print("overspent grants:") for grant in overspent: print(grant) if not rc.no_plot: print( plotter(datearray, student=cum_student, pd=cum_pd, ss=cum_ss, title="Cumulative burn")) return
def latex(self): """Render latex template""" rc = self.rc # Convert Date Strings to Datetime Objects if not rc.from_date: raise ValueError( "ERROR: need begin for the report period." "Please rerun specifying --from and --to in YYYY-MM-DD format." ) else: rp_start_date = date_parser.parse(rc.from_date).date() if not rc.to_date: rp_end_date = date.today() else: rp_end_date = date_parser.parse(rc.to_date).date() report_dates = {'begin_date': rp_start_date, 'end_date': rp_end_date} # NSF Grant _id if not rc.grants: raise RuntimeError( "Error: no grant specified. Please rerun specifying a grant") if isinstance(rc.grants, str): rc.grants = [rc.grants] if len(rc.grants) > 1: raise RuntimeError( "Error: more than one grant specified. Please rerun with" "only a single grant.") grant_id = rc.grants[0] # Get prum associated to grant and active during reporting period # institutions_coll = [inst for inst in self.gtx["institutions"]] institutions_coll = self.gtx["institutions"] grant_prums = [ prum for prum in self.gtx['projecta'] if grant_id in prum.get('grants', []) and "checklist" not in prum.get("deliverable").get("scope") ] # for prum in self.gtx['projecta']: # if grant_name in prum['grants']: # begin_date = get_dates(prum).get('begin_date') # due_date = get_due_date(prum['deliverable']) # # if projectum was finished during reporting period or is still current # # some projectum don't have an "end date", but all projecta have a deliverable # # due_date # if (rp_start_date <= due_date <= rp_end_date and prum['status'] is "finished") or is_current(prum): # grant_prums.append(prum) # Get people associated with grant grant_prums_finished_this_period = [ prum for prum in grant_prums if is_current(report_dates, get_dates(prum).get('end_date')) ] grant_prum_leads = list(set([prum['lead'] for prum in grant_prums])) grant_prum_collaborators = list( set([ collab for prum in grant_prums for collab in prum.get('collaborators', []) ])) grant_prum_group_members = list( set([ grp_mbr for prum in grant_prums for grp_mbr in prum.get('group_members', []) ])) grant_people = grant_prum_leads # Accomplishments major_activities = [] significant_results = [] for prum in grant_prums: if prum['status'] == "finished": continue else: major_activities.append(prum) for prum in grant_prums_finished_this_period: significant_results.append(prum) # Opportunities for Training and Professional Development training_and_professional_development = [] # presentations for id in grant_people: training_and_professional_development.extend( filter_presentations(self.gtx["people"], self.gtx["presentations"], institutions_coll, id, types=["all"], since=rp_start_date, before=rp_end_date, statuses=["accepted"])) # thesis defendings # how do i access people.yml in rg-db-public vs the people.yml file in rg-db-group? # defended_theses = [] # for id in grant_people: # for prsn in self.gtx['people']: # if prsn["_id"] != id: # continue # else: # person = prsn # for education in person['education']: # edu_dates = get_dates(education) # if 'phd' in education['degree'].lower() and 'columbia' in education['institution'].lower() and \ # rp_start_date.year <= edu_dates.get('end_date', edu_dates['date']).year <= rp_end_date.year: # defended_theses.append(id) # Products # need rg-db-public's citation.yml # publications = filter_publications(self.gtx["citations"], ## set(grant_people), # since=rp_start_date, # before=rp_end_date) publications = [ publ for publ in self.gtx["citations"] if grant_id in publ.get("grant", "") ] for publ in publications: doi = publ.get('doi') if doi and doi != 'tbd': publ = get_formatted_crossref_reference(doi) names = [ HumanName(author).full_name for author in publ.get("author") ] publ['author'] = names # Participants/Organizations participants = [] for person in self.gtx["people"]: months_on_grant, months_left = self.months_on( grant_id, person, rp_start_date, rp_end_date) if months_on_grant > 0: participants.append({ "name": person.get("name"), "email": person.get("email"), "position": person.get('position'), "months_on_grant": int(round(months_on_grant, 0)) }) collaborators = {} missing_contacts = [] for id in grant_prum_collaborators: for contact in self.gtx["contacts"]: if contact["_id"] == id: name = contact.get("name") aka = contact.get("aka") institution_id = contact.get("institution") institution = fuzzy_retrieval(institutions_coll, ["name", "aka", "_id"], institution_id) if institution: inst_name = institution.get("name") else: print( f"WARNING: institution {institution_id} not found " f"in institutions collection") inst_name = institution_id collaborators[id] = { "aka": aka, "name": name, "institution": inst_name } missing_contacts = [ id for id in grant_prum_collaborators if not collaborators.get(id) ] missing_contacts = list(set(missing_contacts)) for person_id in missing_contacts: print( f"WARNING contact {person_id} not found in contacts collection" ) # Impacts begin_date_str = rp_start_date.isoformat() end_date_str = rp_end_date.isoformat() self.render( "grantreport.txt", f"{grant_id}_report_{begin_date_str}_{end_date_str}.txt", begin_date=begin_date_str, end_date=end_date_str, majorActivities=major_activities, significantResults=significant_results, trainingAndProfessionalDevelopment= training_and_professional_development, # defendedTheses=defended_theses, products=publications, grantPeople=grant_people, participants=participants, collaborators=collaborators, hline= "------------------------------------------------------------------------------" )
def test_is_current(thing, expected, now=TEST_DATE): assert is_current(thing, now=now) == expected
def sout(self): gtx = self.gtx rc = self.rc if rc.filter: collection = key_value_pair_filter(self.gtx["people"], rc.filter) else: collection = self.gtx["people"] bad_stati = ["finished", "cancelled", "paused", "back_burner"] people = [] group = fuzzy_retrieval(gtx['groups'], ["_id", "aka", "name"], rc.groupname) group_id = group.get("_id") if rc.filter: if not rc.verbose: results = (collection_str(collection, rc.keys)) print(results, end="") return else: for person in collection: print("{}, {} | group_id: {}".format( person.get('name'), person.get('position'), person.get('_id'))) print(" orcid: {} | github_id: {}".format( person.get('orcid_id'), person.get('github_id'))) pass #code to print verbosely on filtering if not rc.filter: for person in gtx["people"]: if rc.current: if not person.get('active'): continue people.append(person) elif rc.prior: if person.get('active'): continue people.append(person) else: people.append(person) cleaned_people = [] for person in people: not_current_positions = [ emp for emp in person.get('employment') if not is_current(emp) ] not_current_positions.sort(key=lambda x: get_dates(x)["end_date"]) current_positions = [ emp for emp in person.get('employment') if is_current(emp) ] current_positions.sort(key=lambda x: get_dates(x)["begin_date"]) positions = not_current_positions + current_positions position_keys = [ position_key(position) for position in positions if position.get("group", "") == group_id ] if position_keys: person["position_key"] = max(position_keys)[0] cleaned_people.append(person) else: print( f"Person {person['name']} has no positions in group {group_id}" ) cleaned_people.sort(key=lambda k: k['position_key'], reverse=True) position_names = { 1: "Undergrads", 2.5: "Masters Students", 2: "Visiting Students", 3: "Graduate Students", 4: "Post Docs", 5: "Visitors", 8: "Assistant Scientists", 9: "Associate Scientists", 10: "Scientists", 11: "PI" } accounting = 12 for person in cleaned_people: if person.get('position_key') < accounting: accounting = person.get('position_key') print( f" -- {position_names.get(accounting,position_names.get(5))} --" ) if rc.verbose: print("{}, {}".format(person.get('name'), person.get('position'))) print(" email: {} | group_id: {}".format( person.get('email'), person.get('_id'))) print(" github_id: {} | orcid: {}".format( person.get('github_id'), person.get('orcid_id'))) for position in positions: if is_current(position): inst = fuzzy_retrieval(gtx["institutions"], ["aka", "name", "_id"], position.get("organization")) if inst: instname = inst.get("name") else: print( f"WARNING: {position.get('organization')} not in institutions collection" ) print(" current organization: {}".format(instname)) print(" current position: {}".format( position.get('full_position', position.get('position').title()))) if not person.get('active'): if position.get('group') == "bg": print(" billinge group position: {}".format( position.get('position'))) else: print("{}".format(person.get('name'))) return
def latex(self): """Render latex template""" gtx = self.gtx rc = self.rc for group in self.gtx["groups"]: gtx["grants"] = list(sorted( all_docs_from_collection(rc.client, "grants"), key=_id_key )) gtx["proposals"] = list(sorted( all_docs_from_collection(rc.client, "proposals"), key=_id_key )) grp = group["_id"] pi = fuzzy_retrieval( self.gtx["people"], ["aka", "name"], group["pi_name"] ) pinames = pi["name"].split() piinitialslist = [i[0] for i in pinames] pi['initials'] = "".join(piinitialslist).upper() grants = merge_collections_all(self.gtx["proposals"], self.gtx["grants"], "proposal_id") for g in grants: g['end_date'] = get_dates(g).get('end_date') g['begin_date'] = get_dates(g).get('begin_date', dt.date(1900, 1, 2)) for person in g.get("team", []): rperson = fuzzy_retrieval( self.gtx["people"], ["aka", "name"], person["name"] ) if rperson: person["name"] = rperson["name"] if g.get('budget'): amounts = [i.get('amount') for i in g.get('budget')] g['subaward_amount'] = sum(amounts) current_grants = [ dict(g) for g in grants if is_current(g) ] current_grants, _, _ = filter_grants( current_grants, {pi["name"]}, pi=False, multi_pi=True ) current_grants = [g for g in current_grants if g.get("status") != "declined"] for g in current_grants: if g.get('budget'): amounts = [i.get('amount') for i in g.get('budget')] g['subaward_amount'] = sum(amounts) pending_grants = [ g for g in self.gtx["proposals"] if is_pending(g["status"]) ] for g in pending_grants: for person in g["team"]: rperson = fuzzy_retrieval( self.gtx["people"], ["aka", "name"], person["name"] ) if rperson: person["name"] = rperson["name"] pending_grants, _, _ = filter_grants( pending_grants, {pi["name"]}, pi=False, multi_pi=True ) summed_grants = pending_grants + current_grants for grant in summed_grants: grant.update( award_start_date="{}/{}/{}".format( grant.get("begin_date").month, grant.get("begin_date").day, grant.get("begin_date").year, ), award_end_date="{}/{}/{}".format( grant.get("end_date").month, grant.get("end_date").day, grant.get("end_date").year, ), ) badids = [i["_id"] for i in current_grants if not i.get('cpp_info').get('cppflag', "")] iter = copy(current_grants) for grant in iter: if grant["_id"] in badids: current_grants.remove(grant) piname = HumanName(pi["name"]) outfile = "current-pending-{}-{}".format(grp, piname.last.lower()) self.render( "current_pending.tex", outfile + ".tex", pi=pi, pending=pending_grants, current=current_grants, pi_upper=pi["name"].upper(), group=group, ) self.pdf(outfile)
def latex(self): """Render latex template""" rc = self.rc group = fuzzy_retrieval(self.gtx['groups'], ["_id", "aka", "name"], rc.groupname) if not rc.people: raise RuntimeError("ERROR: please rerun specifying --people name") if not rc.from_date: raise RuntimeError("ERROR: please rerun specifying --from") build_target = get_id_from_name( all_docs_from_collection(rc.client, "people"), rc.people[0]) begin_year = int(rc.from_date.split("-")[0]) begin_period = date_parser.parse(rc.from_date).date() pre_begin_period = begin_period - relativedelta(years=1) if rc.to_date: to_date = date_parser.parse(rc.to_date).date() end_period = to_date post_end_period = to_date + relativedelta(years=1) else: end_period = begin_period + relativedelta(years=1) - relativedelta( days=1) post_end_period = begin_period + relativedelta( years=2) - relativedelta(days=1) me = [p for p in self.gtx["people"] if p["_id"] == build_target][0] me["begin_period"] = dt.date.strftime(begin_period, "%m/%d/%Y") me["begin_period"] = dt.date.strftime(begin_period, "%m/%d/%Y") me["pre_begin_period"] = dt.date.strftime(pre_begin_period, "%m/%d/%Y") me["end_period"] = dt.date.strftime(end_period, "%m/%d/%Y") me["post_end_period"] = dt.date.strftime(post_end_period, "%m/%d/%Y") projs = filter_projects(self.gtx["projects"], set([build_target]), group=group["_id"]) ######## # Recommendation Letters count ######## recletts = self.gtx['recletts'] num_recletts = len([ reclett["_id"] for reclett in recletts if get_dates(reclett).get("end_date") >= begin_period ]) ######## # Proposal review count ######## proprevs = self.gtx['proprevs'] num_proprevs = len([ proprev["_id"] for proprev in proprevs if get_dates(proprev).get("end_date") >= begin_period and proprev.get('status') == 'submitted' ]) ######## # Manuscript review count ######## manrevs = self.gtx['manrevs'] num_manrevs = len([ manrev["_id"] for manrev in manrevs if manrev.get("status") == "submitted" and get_dates(manrev, date_field_prefix="submitted").get( "submitted_date", dt.date(1971, 1, 1)) is not None and get_dates(manrev, date_field_prefix="submitted").get( "submitted_date", dt.date(1971, 1, 1)) >= begin_period ]) ######### # highlights ######### for proj in projs: if proj.get('highlights'): proj["current_highlights"] = False for highlight in proj.get('highlights'): highlight_date = get_dates(highlight) if highlight_date.get("end_date") >= begin_period: highlight["is_current"] = True proj["current_highlights"] = True ######### # current and pending ######### pi = fuzzy_retrieval(self.gtx["people"], ["aka", "name"], group["pi_name"]) pinames = pi["name"].split() piinitialslist = [i[0] for i in pinames] pi['initials'] = "".join(piinitialslist).upper() grants = merge_collections_all(self.gtx["proposals"], self.gtx["grants"], "proposal_id") for g in grants: g['end_date'] = get_dates(g).get('end_date') g['begin_date'] = get_dates(g).get('begin_date', dt.date(1900, 1, 2)) g['award_start_date'] = "{}/{}/{}".format( g.get("begin_date").month, g.get("begin_date").day, g.get("begin_date").year, ) g['award_end_date'] = "{}/{}/{}".format( g.get("end_date").month, g.get("end_date").day, g.get("end_date").year) for person in g.get("team", []): rperson = fuzzy_retrieval(self.gtx["people"], ["aka", "name"], person["name"]) if rperson: person["name"] = rperson["name"] if g.get('budget'): amounts = [i.get('amount') for i in g.get('budget')] g['subaward_amount'] = sum(amounts) current_grants = [dict(g) for g in grants if is_current(g)] current_grants, _, _ = filter_grants(current_grants, {pi["name"]}, pi=False, multi_pi=True) current_grants = [ g for g in current_grants if g.get("status") != "declined" ] for g in current_grants: if g.get('budget'): amounts = [i.get('amount') for i in g.get('budget')] g['subaward_amount'] = sum(amounts) pending_grants = [ g for g in self.gtx["proposals"] if is_pending(g["status"]) ] for g in pending_grants: for person in g["team"]: rperson = fuzzy_retrieval(self.gtx["people"], ["aka", "name"], person["name"]) if rperson: person["name"] = rperson["name"] pending_grants, _, _ = filter_grants(pending_grants, {pi["name"]}, pi=False, multi_pi=True) badids = [ i["_id"] for i in current_grants if not i.get('cpp_info').get('cppflag', "") ] declined_proposals = [ g for g in self.gtx["proposals"] if is_declined(g["status"]) ] for g in declined_proposals: for person in g["team"]: rperson = fuzzy_retrieval(self.gtx["people"], ["aka", "name"], person["name"]) if rperson: person["name"] = rperson["name"] declined_proposals, _, _ = filter_grants(declined_proposals, {pi["name"]}, pi=False, multi_pi=True) declined_proposals = [ proposal for proposal in declined_proposals if get_dates(proposal).get('begin_date') >= begin_period and get_dates(proposal, date_field_prefix="submitted").get( 'submitted_date', end_period) <= end_period ] iter = copy(current_grants) for grant in iter: if grant["_id"] in badids: current_grants.remove(grant) ######### # end current and pending ######### ######### # advising ######### undergrads = filter_employment_for_advisees(self.gtx["people"], begin_period, "undergrad", rc.people[0]) masters = filter_employment_for_advisees(self.gtx["people"], begin_period, "ms", rc.people[0]) currents = filter_employment_for_advisees(self.gtx["people"], begin_period, "phd", rc.people[0]) graduateds = filter_employment_for_advisees( self.gtx["people"], begin_period.replace(year=begin_year - 5), "phd", rc.people[0]) postdocs = filter_employment_for_advisees(self.gtx["people"], begin_period, "postdoc", rc.people[0]) visitors = filter_employment_for_advisees(self.gtx["people"], begin_period, "visitor-unsupported", rc.people[0]) iter = deepcopy(graduateds) for g in iter: if g.get("active"): graduateds.remove(g) iter = deepcopy(currents) for g in iter: if not g.get("active"): currents.remove(g) ###################### # service ##################### mego = deepcopy(me) dept_service = filter_service(mego, begin_period, "department") mego = deepcopy(me) school_service = filter_service(mego, begin_period, "school") mego = deepcopy(me) uni_service = filter_service(mego, begin_period, "university") uni_service.extend(school_service) if num_recletts > 0: uni_service.append({ "name": f"Wrote recommendation letters for {num_recletts} " f"people this period" }) mego = deepcopy(me) prof_service = filter_service(mego, begin_period, "profession") if num_proprevs > 0: prof_service.append({ "name": f"Reviewed {num_proprevs} funding proposals for " f"national agencies this period" }) if num_manrevs > 0: prof_service.append({ "name": f"Reviewed {num_manrevs} manuscripts for " f"peer reviewed journals this period" }) mego = deepcopy(me) phd_defenses = filter_committees(mego, begin_period, "phddefense") phd_proposals = filter_committees(mego, begin_period, "phdproposal") phd_orals = filter_committees(mego, begin_period, "phdoral") mego = deepcopy(me) outreach = filter_service(mego, begin_period, "outreach") mego = deepcopy(me) lab = filter_facilities([mego], begin_period, "research") mego = deepcopy(me) shared = filter_facilities([mego], begin_period, "shared") mego = deepcopy(me) fac_other = filter_facilities([mego], begin_period, "other") mego = deepcopy(me) fac_teaching = filter_facilities([mego], begin_period, "teaching") mego = deepcopy(me) fac_wishlist = filter_facilities([mego], begin_period, "research_wish", verbose=False) mego = deepcopy(me) tch_wishlist = filter_facilities([mego], begin_period, "teaching_wish") mego = deepcopy(me) curric_dev = filter_activities([mego], begin_period, "teaching") mego = deepcopy(me) other_activities = filter_activities([mego], begin_period, "other") ########################## # Presentation list ########################## keypres = filter_presentations(self.gtx["people"], self.gtx["presentations"], self.gtx["institutions"], build_target, types=["award", "plenary", "keynote"], since=begin_period, before=end_period, statuses=["accepted"]) invpres = filter_presentations(self.gtx["people"], self.gtx["presentations"], self.gtx["institutions"], build_target, types=["invited"], since=begin_period, before=end_period, statuses=["accepted"]) sempres = filter_presentations(self.gtx["people"], self.gtx["presentations"], self.gtx["institutions"], build_target, types=["colloquium", "seminar"], since=begin_period, before=end_period, statuses=["accepted"]) declpres = filter_presentations(self.gtx["people"], self.gtx["presentations"], self.gtx["institutions"], build_target, types=["all"], since=begin_period, before=end_period, statuses=["declined"]) ######################### # Awards ######################### ahs = awards(me, since=begin_period) ######################## # Publications ######################## names = frozenset(me.get("aka", []) + [me["name"]]) pubs = filter_publications(all_docs_from_collection( rc.client, "citations"), names, reverse=True, bold=False, since=begin_period) #remove unpublished papers # unpubs = [pub for pub in pubs if len(pub.get("doi") == 0)] pubed = [pub for pub in pubs if len(pub.get("doi")) > 0] non_arts = [pub for pub in pubs if pub.get("entrytype") != "article"] pubs = pubed + non_arts bibfile = make_bibtex_file(pubs, pid=me["_id"], person_dir=self.bldir) articles = [ prc for prc in pubs if prc.get("entrytype") == "article" and not prc.get("peer_rev_conf") ] NONARTICLETYPES = [ "book", "inbook", "proceedings", "inproceedings", "incollection", "unpublished", "phdthesis", "misc" ] nonarticles = [ prc for prc in pubs if prc.get("entrytype") in NONARTICLETYPES ] peer_rev_conf_pubs = [prc for prc in pubs if prc.get("peer_rev_conf")] ############## # TODO: add Current Projects to Research summary section ############## ############# # IP ############# patents = filter_patents(self.gtx["patents"], self.gtx["people"], build_target, since=begin_period) licenses = filter_licenses(self.gtx["patents"], self.gtx["people"], build_target, since=begin_period) ############# # hindex ############# if not me.get("miscellaneous"): me["miscellaneous"] = {"metrics_for_success": []} if me.get("hindex"): hindex = sorted(me["hindex"], key=doc_date_key).pop() ######################### # render ######################### self.render( "columbia_annual_report.tex", f"{pi['_id']}-ann-report.tex", pi=pi, p=me, projects=projs, pending=pending_grants, current=current_grants, declined=declined_proposals, undergrads=undergrads, masters=masters, currentphds=currents, graduatedphds=graduateds, postdocs=postdocs, visitors=visitors, phd_defenses=phd_defenses, phd_proposals=phd_proposals, phd_orals=phd_orals, dept_service=dept_service, uni_service=uni_service, prof_service=prof_service, outreach=outreach, lab=lab, shared=shared, facilities_other=fac_other, fac_teaching=fac_teaching, fac_wishlist=fac_wishlist, tch_wishlist=tch_wishlist, curric_dev=curric_dev, other_activities=other_activities, keypres=keypres, invpres=invpres, sempres=sempres, declpres=declpres, sentencecase=sentencecase, monthstyle=month_fullnames, ahs=ahs, pubs=articles, nonarticles=nonarticles, peer_rev_conf_pubs=peer_rev_conf_pubs, bibfile=bibfile, patents=patents, licenses=licenses, hindex=hindex, ) self.pdf("billinge-ann-report")
def sout(self): gtx = self.gtx rc = self.rc if rc.filter: collection = key_value_pair_filter(self.gtx["people"], rc.filter) else: collection = self.gtx["people"] bad_stati = ["finished", "cancelled", "paused", "back_burner"] people = [] if rc.filter: if not rc.verbose: results = (collection_str(collection, rc.keys)) # "scopatz" print(results, end="") return else: for person in collection: print("{}, {} | group_id: {}".format( person.get('name'), person.get('position'), person.get('_id'))) print(" orcid: {} | github_id: {}".format( person.get('orcid_id'), person.get('github_id'))) pass #code to print verbosely on filtering if not rc.filter: for person in gtx["people"]: if rc.current: if not person.get('active'): continue people.append(person) elif rc.prior: if person.get('active'): continue people.append(person) else: people.append(person) for i in people: if rc.verbose: print("{}, {}".format(i.get('name'), i.get('position'))) print(" email: {} | group_id: {}".format( i.get('email'), i.get('_id'))) print(" github_id: {} | orcid: {}".format( i.get('github_id'), i.get('orcid_id'))) not_current_positions = [ emp for emp in i.get('employment') if not is_current(emp) ] not_current_positions.sort( key=lambda x: get_dates(x)["end_date"]) current_positions = [ emp for emp in i.get('employment') if is_current(emp) ] current_positions.sort( key=lambda x: get_dates(x)["begin_date"]) positions = not_current_positions + current_positions for position in positions: if is_current(position): inst = fuzzy_retrieval(gtx["institutions"], ["aka", "name", "_id"], position.get("organization")) if inst: instname = inst.get("name") else: print( f"WARNING: {position.get('organization')} not in institutions collection" ) print(" current organization: {}".format(instname)) print(" current position: {}".format( position.get('full_position', position.get('position').title()))) if not i.get('active'): if position.get('group') == "bg": print(" billinge group position: {}".format( position.get('position'))) else: print("{}".format(i.get('name'))) return
def sout(self): rc = self.rc outdated, depleted, underspent, overspent = [], [], [], [] all_appts = collect_appts(self.gtx['people']) if rc.projection_from_date: projection_from_date = date_parser.parse( rc.projection_from_date).date() else: projection_from_date = date.today() grants_with_appts = [] cum_months_to_cover = 0 for person in self.gtx['people']: person_dates = group_member_employment_start_end(person, "bg") last_emp, months_to_cover = 0, 0 if person_dates: last_emp = max( [emp.get('end_date', 0) for emp in person_dates]) if last_emp: months_to_cover = round( (last_emp - projection_from_date).days / 30.5, 2) if months_to_cover > 0: print( f"{person['_id']} needs to be covered for {months_to_cover} months" ) cum_months_to_cover += months_to_cover appts = collect_appts([person]) if not appts: continue this_begin = min(get_dates(appt)['begin_date'] for appt in appts) this_end = max(get_dates(appt)['end_date'] for appt in appts) is_fully_appointed(person, this_begin, this_end) for appt in appts: grants_with_appts.append(appt.get("grant")) if appt.get("grant") in BLACKLIST: if rc.verbose: print( f"skipping {appt.get('grant')} since it is in the blacklist" ) continue if appt.get("grant") not in grants_with_appts: if rc.verbose: print( f"skipping {appt.get('grant')} since it has no appointments assigned to it" ) continue grant = rc.client.find_one(rc.database, "grants", {"alias": appt.get("grant")}) if not grant: raise RuntimeError( " grant: {}, person: {}, appointment: {}, grant not found in grants database" .format(appt.get("grant"), person.get("_id"), appt.get("_id"))) prop = rc.client.find_one(rc.database, "proposals", {"_id": grant.get("proposal_id")}) if prop.get('year'): del prop['year'] grant_begin = get_dates(grant)['begin_date'] if grant.get('begin_date') or grant.get('begin_year') \ else get_dates(prop)['begin_date'] grant_end = get_dates(grant)['end_date'] if grant.get('end_date') or grant.get('end_year') \ else get_dates(prop)['end_date'] grant.update({ 'begin_date': grant_begin, 'end_date': grant_end }) appt_begin, appt_end = get_dates( appt)['begin_date'], get_dates(appt)['end_date'] this_burn = grant_burn(grant, all_appts, begin_date=appt_begin, end_date=appt_end) timespan = appt_end - appt_begin outdated_period, depleted_period = False, False for x in range(timespan.days + 1): day = appt_begin + relativedelta(days=x) if not outdated_period: if not is_current(grant, now=day): outdated.append( " person: {}, appointment: {}, grant: {},\n" " from {} until {}".format( person.get('_id'), appt.get('_id'), grant.get('_id'), str(day), str( min(appt_end, get_dates(grant)['begin_date'])))) outdated_period = True if not depleted_period and not outdated_period: day_burn = 0 if appt.get('type') == 'gra': day_burn = this_burn[x].get('student_days') elif appt.get('type') == 'pd': day_burn = this_burn[x].get('postdoc_days') elif appt.get('type') == 'ss': day_burn = this_burn[x].get('ss_days') if day_burn < -5: depleted.append( " person: {}, appointment: {}, grant: {},\n" " from {} until {}".format( person.get('_id'), appt.get('_id'), grant.get('alias'), str(day), str(appt_end))) depleted_period = True grants_with_appts = list(set(grants_with_appts)) datearray, cum_student, cum_pd, cum_ss = [], None, None, None if not rc.no_plot: grants_begin, grants_end = None, None for grant in self.gtx['grants']: if grant.get('_id') in BLACKLIST or grant.get( 'alias') in BLACKLIST: continue if grant.get('alias') not in grants_with_appts: continue prop = rc.client.find_one(rc.database, "proposals", {"_id": grant.get("proposal_id")}) if prop.get('year'): del prop['year'] grant_begin = get_dates(grant)['begin_date'] if grant.get('begin_date') or grant.get('begin_year') \ else get_dates(prop)['begin_date'] grant_end = get_dates(grant)['end_date'] if grant.get('end_date') or grant.get('end_year') \ else get_dates(prop)['end_date'] if not grants_begin or grant_begin < grants_begin: grants_begin = grant_begin if not grants_end or grant_end > grants_end: grants_end = grant_end grants_timespan = grants_end - grants_begin for x in range(grants_timespan.days + 1): datearray.append(grants_begin + relativedelta(days=x)) cum_student, cum_pd, cum_ss = [0.0] * len(datearray), [ 0.0 ] * len(datearray), [0.0] * len(datearray) plots = [] cum_underspend = 0 for grant in self.gtx["grants"]: if grant.get('_id') in BLACKLIST or grant.get( 'alias') in BLACKLIST: continue if grant.get('alias') not in grants_with_appts: continue prop = rc.client.find_one(rc.database, "proposals", {"_id": grant.get("proposal_id")}) if prop.get('year'): del prop['year'] grant_begin = get_dates(grant)['begin_date'] if grant.get('begin_date') or grant.get('begin_year') \ else get_dates(prop)['begin_date'] grant_end = get_dates(grant)['end_date'] if grant.get('end_date') or grant.get('end_year') \ else get_dates(prop)['end_date'] budget_begin = min( get_dates(period)['begin_date'] for period in grant.get('budget')) budget_end = max( get_dates(period)['end_date'] for period in grant.get('budget')) if grant_begin < budget_begin: raise RuntimeError( f"grant does not have a complete budget. grant begin: {grant_begin} " f"budget begin: {budget_begin}") elif grant_end > budget_end: raise RuntimeError( f"grant {grant.get('alias')} does not have a complete budget. grant end: {grant_end} " f"budget end: {budget_end}") days_to_go = (grant_end - projection_from_date).days grant.update({'begin_date': grant_begin, 'end_date': grant_end}) grant_amounts = grant_burn(grant, all_appts) end_amount = grant_amounts[-1].get('student_days') + grant_amounts[-1].get('postdoc_days') + \ grant_amounts[-1].get('ss_days') if end_amount > 15.25: underspent.append( " end: {}, grant: {}, underspend amount: {} months,\n required ss+gra burn: {}" .format(str(grant_end), grant.get('alias'), round(end_amount / 30.5, 2), round(end_amount / days_to_go, 2))) cum_underspend += end_amount elif end_amount < -30.5: overspent.append( " end: {}, grant: {}, overspend amount: {} months". format(str(grant_end), grant.get('alias'), round(end_amount / 30.5, 2))) if not rc.no_plot: grant_dates = [] grant_duration = (grant_end - grant_begin).days + 1 this_student, this_pd, this_ss = [0.0] * grant_duration, [ 0.0 ] * grant_duration, [0.0] * grant_duration counter = 0 for x in range(len(datearray)): if is_current(grant, now=datearray[x]): grant_dates.append(datearray[x]) this_student[counter] = grant_amounts[counter].get( 'student_days') cum_student[x] += grant_amounts[counter].get( 'student_days') this_pd[counter] = grant_amounts[counter].get( 'postdoc_days') cum_pd[x] += grant_amounts[counter].get('postdoc_days') this_ss[counter] = grant_amounts[counter].get( 'ss_days') cum_ss[x] += grant_amounts[counter].get('ss_days') counter += 1 plots.append( plotter(grant_dates, student=this_student, pd=this_pd, ss=this_ss, title=f"{grant.get('alias')}")[0]) if outdated: print("appointments on outdated grants:") for appt in outdated: print(appt) if depleted: print("appointments on depleted grants:") for appt in depleted: print(appt) if underspent: print("underspent grants:") for grant in underspent: print(grant) print( f"cumulative underspend = {round(cum_underspend/30.5, 2)} months, cumulative months to support = {round(cum_months_to_cover, 2)}" ) if overspent: print("overspent grants:") for grant in overspent: print(grant) if not rc.no_plot: for plot in plots: if not rc.no_gui: plt.show() cum_plot, cum_ax, outp = plotter(datearray, student=cum_student, pd=cum_pd, ss=cum_ss, title="Cumulative burn") if not rc.no_gui: plt.show() print(outp) return