@@ -650,29 +511,29 @@ The mission of the Software Operations Core is to support the needs of data gene
@@ -684,6 +545,15 @@ The mission of the Software Operations Core is to support the needs of data gene
+
+
+
+
+
Sara Smith Wuitchik
+
+ (2019-2021)
+
+
Sara is now an Assistant Professor at Mount Royal University in Calgary, Canada.
-
John Gaspar
+
Alex Llanos Garrido
- (2017-2019)
+ (2019-2021)
-
John is now a Data Science and Bioinformatics Team Lead at Merck.
+
Alex is now at the Universidad Complutense Madrid.
+
+
+
+
+
Juerg Straubhaar
+
+ (2017-2021)
+
+
Juerg worked primarily on proteomics data with the Mass Spec Core and the Melton Lab while he was in the group.
@@ -720,29 +614,29 @@ The mission of the Software Operations Core is to support the needs of data gene
-
Yasin Kaymaz
+
Brian Arnold
- (2017-2020)
+ (2018-2020)
-
Yasin is now an Assistant Professor at Ege University in Izmir, Turkey.
+
Brian is now a departmental data scientist with the Ecology and Evolutionary Biology department at Princeton.
-
Alexandria D'Souza
+
Yasin Kaymaz
- (2019-2022)
+ (2017-2020)
-
Alexandria primarily worked with the mass spec core and the Woo lab while she was in the group.
+
Yasin is now an Assistant Professor at Ege University in Izmir, Turkey.
-
Sara Smith Wuitchik
+
Ming "Tommy" Tang
- (2019-2021)
+ (2018-2020)
-
Sara is now an Assistant Professor at Mount Royal University in Calgary, Canada.
+
Tommy is now the Director of Computational Biology at Immunitas Therapeutics.
@@ -755,27 +649,29 @@ The mission of the Software Operations Core is to support the needs of data gene
-
Alex Llanos Garrido
+
Veronika Laine
- (2019-2021)
+ (2019)
-
Alex is now at the Universidad Complutense Madrid.
+
Veronika is now at the Finnish Museum of Natural History working on bats.
-
Veronika Laine
+
John Gaspar
- (2019)
+ (2017-2019)
-
Veronika is now at the Finnish Museum of Natural History working on bats.
+
John is now a Data Science and Bioinformatics Team Lead at Merck.
-
Meghan Correa
+
Allison Shultz
-
Former full stack developer currently at Cisco
+ (2017-2018)
+
+
Allison is now the Associate Curator of Ornithology at the Natural History Museum of Los Angeles County.
diff --git a/scripts/about_generator.py b/scripts/about_generator.py
index 9cd02c2..0421290 100644
--- a/scripts/about_generator.py
+++ b/scripts/about_generator.py
@@ -4,6 +4,7 @@
############################################################
import sys, os
+from datetime import datetime
import json
############################################################
@@ -28,6 +29,18 @@ def getAlumCardMargins(people_left, cards_per_row):
return ["0", "1"];
# [outer row margin, inner margin]
+def parse_date(date_str):
+ if date_str in [None, "", "unknown"]:
+ return datetime.min # Use a min date to push entries without a valid date to the end
+ if date_str.startswith("NA-NA-"):
+ year = date_str.split("-")[-1]
+ return datetime.strptime(f"01-01-{year}", "%m-%d-%Y")
+ try:
+ return datetime.strptime(date_str, "%m-%d-%Y")
+ except ValueError:
+ return datetime.min # Use a min date to push entries without a valid date to the end
+# Sort the moved people by "date-left" in descending order, placing those without "date-left" at the end
+
############################################################
print("-" * 20);
@@ -68,6 +81,19 @@ def getAlumCardMargins(people_left, cards_per_row):
# Some of these control the width of the cards and the space between them
# NOTE: that some margins depend on the number of cards in the row, and are set later on
+ # Initialize counters
+ counts = {
+ "Senior Bioinformatics Scientists": 0,
+ "Postdoctoral Researchers": 0
+ };
+
+ # Loop through the entries and count active people
+ for sub_section in counts.keys():
+ if sub_section in json_data:
+ for person, details in json_data[sub_section].items():
+ if details.get("status") == "active":
+ counts[sub_section] += 1;
+
for section in json_data:
cards_tables[section] = "";
# Write the section header
@@ -250,7 +276,7 @@ def getAlumCardMargins(people_left, cards_per_row):
# Add the outer margin and close the last row
cards_tables[section] += '\n
\n';
- # Put a vertical space between the sections
+ # Put a horizontal space between the sections
## End sub-section loop
## End section loop
@@ -273,97 +299,110 @@ def getAlumCardMargins(people_left, cards_per_row):
# Some of these control the width of the cards and the space between them
# NOTE: that some margins depend on the number of cards in the row, and are set later on
- for section in json_data:
- for sub_section in json_data[section]:
- people_left += len([ person for person in json_data[section][sub_section] if json_data[section][sub_section][person]['status'] != "active" ]);
- ## Since the alumni cards will be in one table, we need to count the total number of people instead of doing it by section like above
-
- first_row = True;
- # Since this is one table, we don't need to reset the first row variable for each section
+ alumni_list = [];
for section in json_data:
for sub_section in json_data[section]:
for person in json_data[section][sub_section]:
-
- person_data = json_data[section][sub_section][person];
- # Lookup the profile data for the current person
-
- if person_data['status'] == "active":
- continue;
- # Skip the current person if they are active
-
- if first_row:
- row_margin, alum_inner_margin = getAlumCardMargins(people_left, cards_per_row);
- # Get the row margins for the current row depending on how many cards are in the row
-
- cards_tables["alum"] += '\n
\n';
- cards_tables["alum"] += '\n
\n';
- first_row = False;
- ## Get the margins and add a div for the first row
-
- if cur_card_num > cards_per_row:
- cards_tables["alum"] += '\n
\n';
- cards_tables["alum"] += '
\n';
- # Close the current row
-
- cards_tables["alum"] += '\n
\n';
- # Put a vertical space between the two rows
-
- row_margin, alum_inner_margin = getAlumCardMargins(people_left, cards_per_row);
- # Get the row margins for the current row depending on how many cards are in the row
-
- cards_tables["alum"] += '\n
\n';
- cards_tables["alum"] += '\n
\n';
- cur_card_num = 1;
- # Add the new row divs
- ## If the current row is full, close it and add a new one
-
- if person_data['profile'] == "":
- cards_tables["alum"] += '\n
\n';
- else:
- cards_tables["alum"] += '\n
\n';
- ## The card container div
-
- if person_data['link'] != "":
- if person_data['link'].startswith("about/people/"):
- cards_tables["alum"] += '\t\t
' + person_data['name'] + '\n\n';
- else:
- cards_tables["alum"] += '\t\t
' + person_data['name'] + '\n\n';
- else:
- cards_tables["alum"] += '\t\t
' + person_data['name'] + '\n\n';
- # Add the person name with or without a link
-
- if person_data['date-joined'] != "" and person_data['date-left'] != "":
- start_year = person_data['date-joined'].split("-")[2];
- end_year = person_data['date-left'].split("-")[2];
-
- if start_year == end_year:
- cards_tables["alum"] += '\t\t(' + start_year + ')
\n\n';
- else:
- cards_tables["alum"] += '\t\t(' + start_year + '-' + end_year + ')
\n\n';
- # Lookup the start and end years for the current person and add them to the card if they are available
+ person_data = json_data[section][sub_section][person]
+ if person_data['status'] != "active":
+ alumni_list.append(person_data);
+ people_left += 1;
+ ## Get the list of alumni and the number of people
+ ## Since the alumni cards will be in one table, we need to count the total number of people instead of doing it by section like above
- if person_data['profile'] != "":
- cards_tables["alum"] += '\t\t
' + person_data['profile'] + '
\n';
- # Add the person profile if it is available
+ alumni_list.sort(key=lambda x: parse_date(x.get("date-left", "")), reverse=True)
+ # Sort the alumni by "date-left" in descending order, placing those without "date-left" at the end
- cards_tables["alum"] += '
\n';
- ## Close the card container div
+ for person_data in alumni_list:
+ print(person_data.get('name'))
- if cur_card_num != cards_per_row and people_left != 1:
- cards_tables["alum"] += '
\n';
- # Add the inner margin if the current card isn't the last one in the row
+ first_row = True;
+ # Since this is one table, we don't need to reset the first row variable for each section
- cur_card_num += 1;
- people_left -= 1;
- # Increment the card number and decrement the number of people left
- ## End person loop
- ## End sub-section loop
+ # for section in json_data:
+ # for sub_section in json_data[section]:
+ # for person in json_data[section][sub_section]:
+
+ for person_data in alumni_list:
+
+ #person_data = json_data[section][sub_section][person];
+ # Lookup the profile data for the current person
+
+ if person_data['status'] == "active":
+ continue;
+ # Skip the current person if they are active
+
+ if first_row:
+ row_margin, alum_inner_margin = getAlumCardMargins(people_left, cards_per_row);
+ # Get the row margins for the current row depending on how many cards are in the row
+
+ cards_tables["alum"] += '\n
\n';
+ cards_tables["alum"] += '\n
\n';
+ first_row = False;
+ ## Get the margins and add a div for the first row
+
+ if cur_card_num > cards_per_row:
+ cards_tables["alum"] += '\n
\n';
+ cards_tables["alum"] += '
\n';
+ # Close the current row
+
+ cards_tables["alum"] += '\n
\n';
+ # Put a vertical space between the two rows
+
+ row_margin, alum_inner_margin = getAlumCardMargins(people_left, cards_per_row);
+ # Get the row margins for the current row depending on how many cards are in the row
+
+ cards_tables["alum"] += '\n
\n';
+ cards_tables["alum"] += '\n
\n';
+ cur_card_num = 1;
+ # Add the new row divs
+ ## If the current row is full, close it and add a new one
+
+ if person_data['profile'] == "":
+ cards_tables["alum"] += '\n
\n';
+ else:
+ cards_tables["alum"] += '\n
\n';
+ ## The card container div
+
+ if person_data['link'] != "":
+ if person_data['link'].startswith("about/people/"):
+ cards_tables["alum"] += '\t\t
' + person_data['name'] + '\n\n';
+ else:
+ cards_tables["alum"] += '\t\t
' + person_data['name'] + '\n\n';
+ else:
+ cards_tables["alum"] += '\t\t
' + person_data['name'] + '\n\n';
+ # Add the person name with or without a link
+
+ if person_data['date-joined'] != "" and person_data['date-left'] != "":
+ start_year = person_data['date-joined'].split("-")[2];
+ end_year = person_data['date-left'].split("-")[2];
+
+ if start_year == end_year:
+ cards_tables["alum"] += '\t\t(' + start_year + ')
\n\n';
+ else:
+ cards_tables["alum"] += '\t\t(' + start_year + '-' + end_year + ')
\n\n';
+ # Lookup the start and end years for the current person and add them to the card if they are available
+
+ if person_data['profile'] != "":
+ cards_tables["alum"] += '\t\t
' + person_data['profile'] + '
\n';
+ # Add the person profile if it is available
+
+ cards_tables["alum"] += '
\n';
+ ## Close the card container div
+
+ if cur_card_num != cards_per_row and people_left != 1:
+ cards_tables["alum"] += '
\n';
+ # Add the inner margin if the current card isn't the last one in the row
+
+ cur_card_num += 1;
+ people_left -= 1;
+ # Increment the card number and decrement the number of people left
+ ## End alumni loop
cards_tables["alum"] += '\n
\n';
cards_tables["alum"] += "
\n\n";
# Add the outer margin and close the last row
- ## End section loop
####################