Video Demo: https://www.youtube.com/watch?v=NB2tSq_7e-s
In telecommunication networks, ensuring strong and stable performance is essential. Manually analyzing every base station antenna (cell) is both challenging and time-consuming. Cell coverage is one of the main factors affecting network quality and must be regularly optimized using a antenna inbuilt parameter called “tilt.” The goal is to keep each cell’s coverage within its intended area — not extending too far into neighboring cells or falling short of providing service. Coverage issues directly impact main key performance indicators such as RRC Success Rate.
- If a cell’s coverage extends too far and the RRC Success Rate is below a threshold, the tilt is increased to reduce coverage.
- If coverage is too limited and the RRC Success Rate is low, the tilt is decreased to expand signal reach. This project automates the analysis and adjustment process, helping engineers quickly identify and correct coverage inconsistencies to maintain and improve overall network performance.
- csv
- re
- numpy
- NearestNeighbors class of neighbors module in sklearn library.
- Cell, type: class
- get_input_data , type : function
- get_RRC_threshold, type : function
- get_closest_neighbor_distance, type : function
- analyze_and_update_data, type : function
- save_output_data, type : function
The Cell class is designed to represent the properties and behaviors of a cellular network element. It stores key attributes such as:
- CellName (str)
- Latitude (float)
- Longitude (float)
- RRC_Attempts (int)
- RRC_Successes (int)
- Timing_Advance (int)
- Tilt (int)
Upon initialization, the class validates the input values to ensure they meet the following conditions:
- RRC_Attempt >= 0
- 0 <= RRC_Success <= RRC_Attempt
- 0 <= Timing_Advance <= 100
- 0 <= Tilt <= 100
If any of these conditions are not satisfied, the class prevents the creation of the instance. If all validations pass, the instance is successfully created with the provided attributes. The class also defines two instance methods: uptilt() — Increases the Tilt value by 20. downtilt() — Decreases the Tilt value by 20.
Main function calls the following functions respectively
This function gathers Cell information from a valid csv file. User is prompted until he/she enters a valid existing .csv file. This part is handled by an infinite while loop and try / except method. After receiving csv file, csv.DictReader opens the input csv file, read it, and a for loop creates one instance of the Cell class for every row individually. These cells are saved under a list, which is returned by the function. Additional eq method added to class to be able to perform test and compare the actual result with desired result. If the input not valid, user is warned : "Could not read input_file, please try again"
This function prompts user until he/she enters a valid RRC threshold which is between 0 and 100 regardless of including % sing or not. And return the value as integer. Otherwise warn user with "RRC Success Rate Threshold should be a percentage value between 0 and 100, please try again".
This function accepts a list of Cell instances generated by the get_input_data function. It computes the distances between all pairs of source and neighbor cells and identifies the closest neighbor which is located between azimuth +60 and azimuth -60 degrees of source cell. The function returns a list of dictionaries, where each dictionary contains the source cell’s name and the distance to its nearest neighbor in front. I get online help to decide which approach I should use to find the closest neighbors of a point. Challenge here is that; in telecommunication systems, data is always huge, there are too many base stations / cells and all cells are producing statistics every 15 minutes. To overcome this challenge, instead of using regular mathematical functions and loops built in python, I decided to use .kneighbors method in NearestNeighbors class in sklearn.neighbors library. All structural and logical decisions of the program were taken by me. The detailed behavior of the function is outlined below: Creates an empty list to store (and return at the end) the names of all cells and their respective closest neighbor distances in front. Create a radian numPy ndarray (as Haversine formulation uses radians) consist of the latitude and longitude of the source cells (The classes in sklearn.neighbors can handle NumPy arrays as input. / https://scikit-learn.org/stable/modules/neighbors.html). Haversine formulation is selected because the distance calculation will be done based on earth points. Created NearestNeighbors instance for all the neighbors. Neighbor point distances and their respective indices calculated and stored from closest to farthest with the help of .kneighbors method. After that, 2 nested for loops are used to first iterate over source cells and then iterate over neighbor cells to find the first neighbor which falls between azimuth ±60° of the source cell. Ndarray produced by .kneighbors help at this point to iterate over neighbor cells as every row has the distance information of all the neighbor cells. Built in mathematical functions used to calculate the bearing of each source and neighbor pairs. Industrial standard mathematical formulation is used to calculate bearing, can be referred to : https://www.movable-type.co.uk/scripts/latlong.html Bearing angular azimuth compared with 60 to select the first valid (nearest) match. Source CellName and closest instances are stores and returned in a list of dictionaries.
This function takes the following as input:
- cell instance list (type: list)
- CellName and closest instances (type: list (list of dictionaries))
- RRC Success Rate threshold (type : int) Function sets cell instance state as Overshooter and tilt value as tilt+20 in two nested for loops if:
- the cell’s tolerated timing advance (increase by 10%) is greater than the closest neighbor distance and the RRC Success Rate is below user configurable RRC Success Rate threshold. Function sets cell instance state as Undershooter and tilt value as tilt-20 in two nested for loops if:
- the cell’s tolerated timing advance (decrease by 75%) is less than the closest neighbor distance and the RRC Success Rate is below user configurable RRC Success Rate threshold. Function takes no action if neither of the conditions met. After the loop run completes, function returns the cell list once again. This time cell’s tilt values and state information are updated.
This function uses the cell instance list that is produced by analyze_and_update_data function. List content is written to a file called output.csv as every cell instance will be a row. And this will be our final outcome of the program.
Total 15 functions are used to test the program
9 scenarios are illustrated to test:
- Correct Input
- Incorrect filename
- incorrect_RRC_Att_input
- incorrect_RRC_Succ_less_than_RRC_Att_input
- incorrect_RRC_Succ_less_than_0_input
- incorrect_Timing_Advance_less_than_0_input
- incorrect_Timing_Advance_higher_than_100_input
- incorrect_tilt_less_than_0_input
- incorrect_tilt_higher_than_100_input Testing the functions used in the project was challenging. I figured builtin functions that expects input from user can be replaced with desired input based on the test requirements with monkeypatch.setattr method. It helped me to built the testing function for get_input_data function. Also another useful method is capfd.readouterr which captures the output if you are in a infitinite loop and do not want to raise an error and exit the program. To test a function with infinite while loop and not creak the loop with invalid input: user can use a finite input sequence, when the inputs are finishedStopIteration error raises, and list of outcome can be compared with actual function warning.
2 scenarios are illustrated to test:
- test_get_RRC_threshold_correct
- test_get_RRC_threshold_incorrect Same methods monkeypatch.setattr and capfd.readouterr are used
1 scenario is illustrated. This function does not raise an error and relies on valid input fed to Cell class
3 scenarios are illustrated to test:
- test_analyze_and_update_data_overshooter
- test_analyze_and_update_data_undershooter
- test_analyze_and_update_data_low_RRC_Success_Rate_input