diff --git a/data/people/people.json b/data/people/people.json index c81f7ff..767b49d 100644 --- a/data/people/people.json +++ b/data/people/people.json @@ -86,12 +86,12 @@ "img": "img/people/rawanolayan.jpg", "date-added": "12-05-2023", "date-joined": "05-17-2021", - "date-left": "", - "status" : "active", + "date-left": "07-31-2024", + "status" : "moved", "link": "", "pubs": "https://scholar.google.com/citations?hl=en&user=qxUMqP4AAAAJ&view_op=list_works&sortby=pubdate", "github": "", - "profile": "Rawan is funded by a collaboration with Boehringer Ingelheim, and works on single cell RNA-seq methods." + "profile": "Rawan was funded by a collaboration with Boehringer Ingelheim, and works on single cell RNA-seq methods." }, "Allison Shultz": { "id": "15", @@ -191,12 +191,12 @@ "img": "img/people/subirshakya.jpg", "date-added": "12-05-2023", "date-joined": "03-01-2021", - "date-left": "", - "status" : "active", + "date-left": "08-23-2024", + "status" : "moved", "link": "https://www.subir.com.np/", "pubs": "https://scholar.google.com/citations?hl=en&user=ETGvbj0AAAAJ&view_op=list_works&sortby=pubdate", "github": "", - "profile": "Subir works on population and comparative genomics of birds, funded by an NIH grant to study enhancer evolution in birds." + "profile": "Former postdoc, Subir works on population and comparative genomics of birds. He is now a postdoc at LMU Munich." }, "Ekaterina Osipova": { "id": "31", @@ -307,13 +307,13 @@ "img": "", "date-added": "12-05-2023", "date-joined": "12-18-2023", - "date-left": "", - "status" : "active", + "date-left": "NA-NA-2024", + "status" : "moved", "link": "", "pubs": "", "github": "", "degree": "", - "profile": "Full stack developer for instrument facility applications" + "profile": "Former full stack developer for instrument facility applications" }, "Meghan Correa": { "id": "62", @@ -322,7 +322,7 @@ "office" : "", "date-added": "12-05-2023", "date-joined": "", - "date-left": "", + "date-left": "NA-NA-2022", "status" : "moved", "link": "", "pubs": "", diff --git a/docs/index.md b/docs/index.md index 7b6edf6..07da4e5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -331,110 +331,6 @@ The mission of the Bioinformatics Core includes training, consulting, and resear
-
-
-
-
- Rawan Olayan, Ph.D.
- -
-
-
-
-
-
-
- Profile picture of Rawan Olayan - - -
-
-
- Senior Bioinformatics Scientist
- Northwest Labs, B227.40
-

Rawan is funded by a collaboration with Boehringer Ingelheim, and works on single cell RNA-seq methods.

-
-
-
-
-
- -
- - -
- -
- -
- -
-
-
- -
-
-
-
-
-
- - Profile picture of Subir Shakya - - - -
-
-
- Postdoctoral Fellow
- Northwest Labs, B227.65
-

Subir works on population and comparative genomics of birds, funded by an NIH grant to study enhancer evolution in birds.

-
-
-
-
-
-
-
@@ -495,7 +391,7 @@ The mission of the Bioinformatics Core includes training, consulting, and resear
-
+
@@ -601,41 +497,6 @@ The mission of the Software Operations Core is to support the needs of data gene
-
- -
- -
- -
-
-
-
- Jared Vessella-Smith
- -
-
-
-
-
-
-
- Profile picture of Jared Vessella-Smith -
-
-
- Applications Professional
- Northwest Labs, B227.40
-

Full stack developer for instrument facility applications

-
-
-
-
-
- -
-
-
Social icons: Icons8 @@ -650,29 +511,29 @@ The mission of the Software Operations Core is to support the needs of data gene
- Allison Shultz
+ Subir Shakya
- (2017-2018)
+ (2021-2024)
-

Allison is now the Associate Curator of Ornithology at the Natural History Museum of Los Angeles County.

+

Former postdoc, Subir works on population and comparative genomics of birds. He is now a postdoc at LMU Munich.

- Brian Arnold
+ Rawan Olayan
- (2018-2020)
+ (2021-2024)
-

Brian is now a departmental data scientist with the Ecology and Evolutionary Biology department at Princeton.

+

Rawan was funded by a collaboration with Boehringer Ingelheim, and works on single cell RNA-seq methods.

- Ming "Tommy" Tang
+ Jared Vessella-Smith
- (2018-2020)
+ (2023-2024)
-

Tommy is now the Director of Computational Biology at Immunitas Therapeutics.

+

Former full stack developer for instrument facility applications

@@ -684,6 +545,15 @@ The mission of the Software Operations Core is to support the needs of data gene
+
+ Alexandria D'Souza
+ + (2019-2022)
+ +

Alexandria primarily worked with the mass spec core and the Woo lab while she was in the group.

+
+
+
Scott Van Buren
@@ -694,20 +564,44 @@ The mission of the Software Operations Core is to support the needs of data gene
- Juerg Straubhaar
+ Meghan Correa
- (2017-2021)
+

Former full stack developer currently at Cisco

+
-

Juerg worked primarily on proteomics data with the Mass Spec Core and the Melton Lab while he was in the group.

+
+
+ +
+ +
+ +
+ +
+ 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 ####################