Skip to content

University

Universities

Bases: Supergroup

Source code in june/groups/university.py
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
class Universities(Supergroup):
    """ """
    venue_class = University

    def __init__(self, universities: List[venue_class]):
        super().__init__(members=universities)

    @classmethod
    def for_areas(
        cls,
        areas: Areas,
        universities_filename: str,
        max_distance_to_area: float,
    ) -> "Universities":
        """Initialises universities based on proximity to areas.

        Args:
            areas (Areas): Areas where universities will be created.
            universities_filename (str): Path to the university data file.
            max_distance_to_area (float): Maximum allowable distance to assign a university to an area.

        Returns:
            Universities: An instance containing all created universities.

        """
        universities_df = pd.read_csv(universities_filename)
        longitudes = universities_df["longitude"].astype(float).values
        latitudes = universities_df["latitude"].astype(float).values
        coordinates = np.array(list(zip(latitudes, longitudes)))
        n_students = universities_df["n_students"].values
        ukprn_values = universities_df["UKPRN"].values

        universities = []
        for coord, n_stud, ukprn in zip(coordinates, n_students, ukprn_values):
            closest_area, distance = areas.get_closest_areas(
                coordinates=coord, return_distance=True, k=1
            )
            distance = distance[0]
            closest_area = closest_area[0]
            if distance > max_distance_to_area:
                continue
            university = cls.venue_class(
                area=closest_area,
                n_students_max=n_stud,
                ukprn=ukprn,
                coordinates=(float(coord[0]), float(coord[1])),
            )
            universities.append(university)

        logger.info(f"There are {len(universities)} universities in this world.")

        # Visualization - Sample 5 universities for inspection
        sample_universities = [
            {
                "| Uni ID": uni.id,
                "| Area": uni.area.name if uni.area else "Unknown",
                "| UKPRN": uni.ukprn,
                "| Max Students": uni.n_students_max,
                "| Coordinates": uni.coordinates,
            }
            for uni in random.sample(universities, min(5, len(universities)))
        ]

        df_universities = pd.DataFrame(sample_universities)
        print("\n===== Sample of Created Universities =====")
        print(df_universities)

        return cls(universities)

    @classmethod
    def for_geography(
        cls,
        geography: Geography,
        universities_filename: str = default_universities_filename,
        max_distance_to_area: float = 20,
    ) -> "Universities":
        """Create universities for a given geography.

        Args:
            geography (Geography): The geography object with areas to initialise universities.
            universities_filename (str, optional): (Default value = default_universities_filename)
            max_distance_to_area (float, optional): Maximum distance from an area to consider a university. (Default value = 20)

        Returns:
            Universities: An instance containing all created universities.

        """
        return cls.for_areas(
            geography.areas,
            universities_filename=universities_filename,
            max_distance_to_area=max_distance_to_area,
        )

    # @property
    # def n_professors(self):
    #     return sum([uni.n_professors for uni in self.members])

    @property
    def n_students(self):
        """ """
        return sum([uni.n_students for uni in self.members])

n_students property

for_areas(areas, universities_filename, max_distance_to_area) classmethod

Initialises universities based on proximity to areas.

Parameters:

Name Type Description Default
areas Areas

Areas where universities will be created.

required
universities_filename str

Path to the university data file.

required
max_distance_to_area float

Maximum allowable distance to assign a university to an area.

required

Returns:

Name Type Description
Universities Universities

An instance containing all created universities.

Source code in june/groups/university.py
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
@classmethod
def for_areas(
    cls,
    areas: Areas,
    universities_filename: str,
    max_distance_to_area: float,
) -> "Universities":
    """Initialises universities based on proximity to areas.

    Args:
        areas (Areas): Areas where universities will be created.
        universities_filename (str): Path to the university data file.
        max_distance_to_area (float): Maximum allowable distance to assign a university to an area.

    Returns:
        Universities: An instance containing all created universities.

    """
    universities_df = pd.read_csv(universities_filename)
    longitudes = universities_df["longitude"].astype(float).values
    latitudes = universities_df["latitude"].astype(float).values
    coordinates = np.array(list(zip(latitudes, longitudes)))
    n_students = universities_df["n_students"].values
    ukprn_values = universities_df["UKPRN"].values

    universities = []
    for coord, n_stud, ukprn in zip(coordinates, n_students, ukprn_values):
        closest_area, distance = areas.get_closest_areas(
            coordinates=coord, return_distance=True, k=1
        )
        distance = distance[0]
        closest_area = closest_area[0]
        if distance > max_distance_to_area:
            continue
        university = cls.venue_class(
            area=closest_area,
            n_students_max=n_stud,
            ukprn=ukprn,
            coordinates=(float(coord[0]), float(coord[1])),
        )
        universities.append(university)

    logger.info(f"There are {len(universities)} universities in this world.")

    # Visualization - Sample 5 universities for inspection
    sample_universities = [
        {
            "| Uni ID": uni.id,
            "| Area": uni.area.name if uni.area else "Unknown",
            "| UKPRN": uni.ukprn,
            "| Max Students": uni.n_students_max,
            "| Coordinates": uni.coordinates,
        }
        for uni in random.sample(universities, min(5, len(universities)))
    ]

    df_universities = pd.DataFrame(sample_universities)
    print("\n===== Sample of Created Universities =====")
    print(df_universities)

    return cls(universities)

for_geography(geography, universities_filename=default_universities_filename, max_distance_to_area=20) classmethod

Create universities for a given geography.

Parameters:

Name Type Description Default
geography Geography

The geography object with areas to initialise universities.

required
universities_filename str

(Default value = default_universities_filename)

default_universities_filename
max_distance_to_area float

Maximum distance from an area to consider a university. (Default value = 20)

20

Returns:

Name Type Description
Universities Universities

An instance containing all created universities.

Source code in june/groups/university.py
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
@classmethod
def for_geography(
    cls,
    geography: Geography,
    universities_filename: str = default_universities_filename,
    max_distance_to_area: float = 20,
) -> "Universities":
    """Create universities for a given geography.

    Args:
        geography (Geography): The geography object with areas to initialise universities.
        universities_filename (str, optional): (Default value = default_universities_filename)
        max_distance_to_area (float, optional): Maximum distance from an area to consider a university. (Default value = 20)

    Returns:
        Universities: An instance containing all created universities.

    """
    return cls.for_areas(
        geography.areas,
        universities_filename=universities_filename,
        max_distance_to_area=max_distance_to_area,
    )

University

Bases: Group

Source code in june/groups/university.py
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
class University(Group):
    """ """
    def __init__(
        self,
        n_students_max: int = None,
        n_years: int = 6,
        ukprn: str = None,
        area: Area = None,
        coordinates: Tuple[float, float] = None,
        registered_members_ids: dict = None
    ):
        """
        Create a University given its description.

        Parameters
        ----------
        n_students_max : int
            Maximum number of students that can attend the university.
        n_years : int
            Number of academic years in the university.
        ukprn : str
            Unique identifier for the university.
        area : Area
            The area the university belongs to.
        coordinates : Tuple[float, float]
            Latitude and longitude of the university.
        registered_members_ids : dict, optional
            A dict mapping subgroup IDs to lists of member IDs.
        """
        super().__init__()
        self.n_students_max = n_students_max
        self.n_years = n_years
        self.ukprn = ukprn
        self.area = area
        self.coordinates = coordinates
        self.subgroups = [Subgroup(self, i) for i in range(self.n_years)]
        self.registered_members_ids = registered_members_ids if registered_members_ids is not None else {}

    @property
    def students(self):
        """ """
        return [person for subgroup in self.subgroups[:] for person in subgroup]

    @property
    def n_students(self):
        """ """
        return sum([self.subgroups[i].size for i in range(1, len(self.subgroups))])

    @property
    def super_area(self):
        """ """
        return self.area.super_area

    def add(self, person, subgroup="student"):
        """

        Args:
            person: 
            subgroup: (Default value = "student")

        """
        if subgroup == "student":
            if person.age not in age_to_years:
                year = randint(0, len(self.subgroups) - 1)
            else:
                year = age_to_years[person.age]
            self.subgroups[year].append(person)
            person.subgroups.primary_activity = self.subgroups[year]
            if person.work_super_area is not None:
                person.work_super_area.remove_worker(person)
        elif subgroup == "professors":
            # No professors in the modeling of the code!
            self.subgroups[0].append(person)
            person.subgroups.primary_activity = self.subgroups[0]

    def add_to_registered_members(self, person_id, subgroup_type=0):
        """Add a person to the registered members list for a specific subgroup.

        Args:
            person_id (int): The ID of the person to add
            subgroup_type (int, optional, optional): The subgroup to add the person to (default: 0)

        """
        # Create the subgroup if it doesn't exist
        if subgroup_type not in self.registered_members_ids:
            self.registered_members_ids[subgroup_type] = []

        # Add the person if not already in the list
        if person_id not in self.registered_members_ids[subgroup_type]:
            self.registered_members_ids[subgroup_type].append(person_id)

    @property
    def is_full(self):
        """ """
        return self.n_students >= self.n_students_max

is_full property

n_students property

students property

super_area property

__init__(n_students_max=None, n_years=6, ukprn=None, area=None, coordinates=None, registered_members_ids=None)

Create a University given its description.

Parameters

n_students_max : int Maximum number of students that can attend the university. n_years : int Number of academic years in the university. ukprn : str Unique identifier for the university. area : Area The area the university belongs to. coordinates : Tuple[float, float] Latitude and longitude of the university. registered_members_ids : dict, optional A dict mapping subgroup IDs to lists of member IDs.

Source code in june/groups/university.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def __init__(
    self,
    n_students_max: int = None,
    n_years: int = 6,
    ukprn: str = None,
    area: Area = None,
    coordinates: Tuple[float, float] = None,
    registered_members_ids: dict = None
):
    """
    Create a University given its description.

    Parameters
    ----------
    n_students_max : int
        Maximum number of students that can attend the university.
    n_years : int
        Number of academic years in the university.
    ukprn : str
        Unique identifier for the university.
    area : Area
        The area the university belongs to.
    coordinates : Tuple[float, float]
        Latitude and longitude of the university.
    registered_members_ids : dict, optional
        A dict mapping subgroup IDs to lists of member IDs.
    """
    super().__init__()
    self.n_students_max = n_students_max
    self.n_years = n_years
    self.ukprn = ukprn
    self.area = area
    self.coordinates = coordinates
    self.subgroups = [Subgroup(self, i) for i in range(self.n_years)]
    self.registered_members_ids = registered_members_ids if registered_members_ids is not None else {}

add(person, subgroup='student')

Parameters:

Name Type Description Default
person
required
subgroup

(Default value = "student")

'student'
Source code in june/groups/university.py
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
def add(self, person, subgroup="student"):
    """

    Args:
        person: 
        subgroup: (Default value = "student")

    """
    if subgroup == "student":
        if person.age not in age_to_years:
            year = randint(0, len(self.subgroups) - 1)
        else:
            year = age_to_years[person.age]
        self.subgroups[year].append(person)
        person.subgroups.primary_activity = self.subgroups[year]
        if person.work_super_area is not None:
            person.work_super_area.remove_worker(person)
    elif subgroup == "professors":
        # No professors in the modeling of the code!
        self.subgroups[0].append(person)
        person.subgroups.primary_activity = self.subgroups[0]

add_to_registered_members(person_id, subgroup_type=0)

Add a person to the registered members list for a specific subgroup.

Parameters:

Name Type Description Default
person_id int

The ID of the person to add

required
subgroup_type (int, optional)

The subgroup to add the person to (default: 0)

0
Source code in june/groups/university.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
def add_to_registered_members(self, person_id, subgroup_type=0):
    """Add a person to the registered members list for a specific subgroup.

    Args:
        person_id (int): The ID of the person to add
        subgroup_type (int, optional, optional): The subgroup to add the person to (default: 0)

    """
    # Create the subgroup if it doesn't exist
    if subgroup_type not in self.registered_members_ids:
        self.registered_members_ids[subgroup_type] = []

    # Add the person if not already in the list
    if person_id not in self.registered_members_ids[subgroup_type]:
        self.registered_members_ids[subgroup_type].append(person_id)