From b81c6252272031c660e4952c89d543852a339146 Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:26:34 +0000 Subject: [PATCH 01/20] Added TR to licence --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 72bad44..18541d3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Edward Oughton +Copyright (c) 2019 Edward Oughton & Tom Russell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 653582e7206ddc21072dd327475b16ea3d0a8196 Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:26:48 +0000 Subject: [PATCH 02/20] Correct url in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c3959b0..2875c3f 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ def readme(): long_description_content_type='text/markdown', author='Edward J. Oughton', author_email='edward.oughton@ouce.ox.ac.uk', - url='https://github.com/edwardoughton/cdcam', + url='https://github.com/nismod/cdcam', packages=find_packages('src'), package_dir={'': 'src'}, py_modules=[splitext(basename(path))[0] for path in glob('src/*.py')], From 7ec3679ca0a6ea69c668d136f508e318587494c3 Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:26:58 +0000 Subject: [PATCH 03/20] Correct author email --- docs/authors.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/authors.rst b/docs/authors.rst index f7807c9..103d999 100644 --- a/docs/authors.rst +++ b/docs/authors.rst @@ -2,5 +2,5 @@ Developers ========== -* Edward J. Oughton +* Edward J. Oughton * Tom Russell From 94d55aa6f6c7de307d53545cbe0c4a1b3f709340 Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:27:13 +0000 Subject: [PATCH 04/20] Add statement of need and applications to .md --- docs/getting-started.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/getting-started.rst b/docs/getting-started.rst index 2f211eb..66b2394 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -1,3 +1,28 @@ +================= +Statement of Need +================= + +Every decade a new generation of cellular technology is standardised and released. +Increasingly, given the importance of the Internet of Things, Industry 4.0 and Smart Health +applications, both governments and other digital ecosystem actors want to understand the costs +associated with digital connectivity. + +However, there are very few geospatial open-source tools to help simultaneously understand +both the engineering and cost implications of new connectivity technologies such as 5G. Hence, +``cdcam`` has been developed to address this key research need. + +============ +Applications +============ + +``cdcam`` has already been used to test the capacity, coverage and cost of 5G infrastructure +in Britain [@Oughton:2018a; @Oughton:2018b] and the Netherlands [@Oughton:2019a]. + +The model is one of several infrastructure simulation models being used in ongoing research +as part of the ITRC Mistral project to analyse national infrastructure systems-of-systems, +using scenarios of population change generated by ``simim`` [@simim] and connected by a +simulation model coupling library, ``smif`` [@smif]. + =============== Getting Started =============== From 29913fbbc84fcf33f963f535edd25a6fe4776bdd Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:27:21 +0000 Subject: [PATCH 05/20] Add new contents --- docs/index.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index 9b435c3..c3e1738 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -63,6 +63,16 @@ Consortium `_ (EP/N017064/1) and (ii) the UK's `Digital Contents -------- +.. toctree:: + :maxdepth: 2 + + Statement of Need + +.. toctree:: + :maxdepth: 2 + + Applications + .. toctree:: :maxdepth: 2 From 31faa08fadd037a1f30fc4f42db352c8528ce214 Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:27:36 +0000 Subject: [PATCH 06/20] Correct DOIs --- paper/paper.bib | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/paper/paper.bib b/paper/paper.bib index 526c0e3..5a89942 100644 --- a/paper/paper.bib +++ b/paper/paper.bib @@ -5,7 +5,7 @@ @article{Oughton:2018a pages = {141 - 155}, year = {2018}, issn = {0040-1625}, - doi = {https://doi.org/10.1016/j.techfore.2018.03.016}, + doi = {10.1016/j.techfore.2018.03.016}, url = {http://www.sciencedirect.com/science/article/pii/S0040162517313525}, author = {{Oughton}, E.~J. and {Frias}, Z. and {Russell}, T. and {Sicker}, D. and {Cleevely}, D.~D.}, } @@ -17,7 +17,7 @@ @article{Oughton:2018b pages = {636 - 652}, year = {2018}, issn = {0308-5961}, - doi = {https://doi.org/10.1016/j.telpol.2017.07.009}, + doi = {10.1016/j.telpol.2017.07.009}, url = {http://www.sciencedirect.com/science/article/pii/S0308596117302781}, author = {{Oughton}, E.~J. and {Frias}, Z.}, } @@ -28,7 +28,7 @@ @article{Oughton:2019a pages = {50 - 69}, year = {2019}, issn = {0736-5853}, - doi = {https://doi.org/10.1016/j.tele.2019.01.003}, + doi = {10.1016/j.tele.2019.01.003}, url = {http://www.sciencedirect.com/science/article/pii/S073658531830830X}, author = {{Oughton}, E.~J. and {Frias}, Z. and {van der Gaast}, S. and {van der Berg}, R.}, } @@ -38,7 +38,7 @@ @article{Oughton:2019b pages = {1 - 1}, year = {2019}, issn = {2169-3536}, - doi = {https://doi.org/10.1109/ACCESS.2019.2949460}, + doi = {10.1109/ACCESS.2019.2949460}, url = {https://ieeexplore.ieee.org/document/8882300}, author = {{Oughton}, E.~J. and {Katsaros}, K. and {Entezami}, F. and {Kaleshi}, D. and {Crowcroft}, J.}, } @@ -58,6 +58,6 @@ @article{smif issue = {1}, pages = {16}, year = {2019}, - doi = {https://doi.org/10.5334/jors.265}, + doi = {10.5334/jors.265}, author = {{Usher}, W. and {Russell}, T.}, } From ca76ac3dc2e8395da37c541007b8bb88afeda495 Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:27:57 +0000 Subject: [PATCH 07/20] Remove statement without available reference. --- paper/paper.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/paper/paper.md b/paper/paper.md index 71fc557..fc670a2 100644 --- a/paper/paper.md +++ b/paper/paper.md @@ -72,8 +72,6 @@ A common way to estimate the system capacity of a cellular network is via stocha The model is one of several infrastructure simulation models being used in ongoing research as part of the ITRC Mistral project to analyse national infrastructure systems-of-systems, using scenarios of population change generated by ``simim`` [@simim] and connected by a simulation model coupling library, ``smif`` [@smif]. -Increasingly, the modelling capability reported here is being applied internationally, including to provide the analytics for the World Bank's Flagship 5G report. - ## Acknowledgements We would like to acknowledge the funding which has enabled development of cdcam, from the EPSRC via (i) the Infrastructure Transitions Research Consortium Mistral project (EP/N017064/1) and (ii) the EPSRC-funded Researcher in Residence programme at the UK's Digital Catapult. From 22ab5b70a0277224d2b6b2feb06f7faebbbf9754 Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:28:04 +0000 Subject: [PATCH 08/20] Correct typos --- src/cdcam/model.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cdcam/model.py b/src/cdcam/model.py index 59e8959..c2b1722 100644 --- a/src/cdcam/model.py +++ b/src/cdcam/model.py @@ -78,7 +78,7 @@ class NetworkManager(object): * 0: :obj:`int` Population density in persons per km². * 1: :obj:`string` - Settlement type (rban, suburban and rural) + Settlement type (urban, suburban and rural) simulation_parameters: dict Contains all simulation parameters, set in the run script. @@ -283,7 +283,7 @@ class PostcodeSector(object): * id: :obj:`int` Unique ID. * lad_id: :obj:`int` - The Local Authority Disrict which this area is within. + The Local Authority District which this area is within. * population: :obj:`int` Number of inhabitants. * area: :obj:`int` @@ -335,7 +335,7 @@ class PostcodeSector(object): * 0: :obj:`int` Population density in persons per km². * 1: :obj:`string` - Settlement type (rban, suburban and rural) + Settlement type (urban, suburban and rural) simulation_parameters: dict Contains all simulation parameters, set in the run script. @@ -597,7 +597,7 @@ def lookup_clutter_geotype(clutter_lookup, population_density): A list of tuples sorted by population_density_upper_bound ascending (population_density_upper_bound, geotype). population_density : float - The current populaion density requiring the lookup. + The current population density requiring the lookup. """ highest_popd, highest_geotype = clutter_lookup[2] From fc5f4e0a955ec529daecff10cc9d7da33081fe5f Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:29:30 +0000 Subject: [PATCH 09/20] Remove unwanted code from vis scripts --- vis/pcds.r | 40 +++++++++++++++++----------------------- vis/vis.R | 1 + 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/vis/pcds.r b/vis/pcds.r index 727bdca..4b0dbfe 100644 --- a/vis/pcds.r +++ b/vis/pcds.r @@ -18,7 +18,7 @@ library(scales) library(RColorBrewer) #library(ineq) #install.packages("ggpubr") -library(ggpubr) +library(ggpubr) # install.packages("arules") library(arules) # install.packages("ggpolypath") @@ -38,7 +38,7 @@ metric_files <- metric_files[grep("^spend*", metric_files)] #initialised empty dataframe empty_df <- data.frame(year=numeric(), - area_id=character(), + area_id=character(), lad_id=character(), population_density=numeric(), item=character(), @@ -78,7 +78,7 @@ all_scenarios <- all_scenarios[which( all_scenarios$lad_id== 'E07000178' | all_scenarios$lad_id== 'E07000179' | all_scenarios$lad_id== 'E07000180' | - all_scenarios$lad_id== 'E07000181' + all_scenarios$lad_id== 'E07000181' ),] all_scenarios <- all_scenarios %>% separate(file, c("file_type", "scenario", "data_scenario", "strategy"), "_", remove = FALSE) @@ -123,7 +123,7 @@ all_scenarios$geotype = factor(all_scenarios$geotype, levels=c("Urban", all_scenarios$strategy = factor(all_scenarios$strategy, levels=c("minimal.csv", "macrocell.csv", "small-cell.csv", - "small-cell-and-spectrum.csv"), + "small-cell-and-spectrum.csv"), labels=c("No Investment", "Spectrum Integration", "Small Cells", @@ -134,7 +134,7 @@ all_scenarios$item = factor(all_scenarios$item, levels=c("upgrade_to_lte", "carrier_700", "carrier_3500", "carrier_26000", - "small_cells"), + "small_cells"), labels=c("Upgrade to LTE", "Add 700 MHz", "Add 3.5 GHz", @@ -144,13 +144,13 @@ all_scenarios$item = factor(all_scenarios$item, levels=c("upgrade_to_lte", all_scenarios <- all_scenarios[which(all_scenarios$data_scenario== 'Baseline'), ] -costs <- ggplot(all_scenarios, aes(x = factor(year), y = (cost/1000000), fill=item)) + +costs <- ggplot(all_scenarios, aes(x = factor(year), y = (cost/1000000), fill=item)) + scale_fill_brewer(palette="Spectral", name = expression('Cost Type'), direction=1) + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + geom_bar(stat="identity") + labs(title = "Annual Investment Over The Study Period", subtitle = "Results reported by scenario, strategy and cost item", x = NULL, y = "Investment Cost (Millions of Pounds)") + - facet_grid(scenario~strategy) + facet_grid(scenario~strategy) ### EXPORT TO FOLDER setwd(output_directory) @@ -158,13 +158,13 @@ tiff('costs.tiff', units="in", width=8.5, height=8.5, res=500) print(costs) dev.off() -costs_geotypes <- ggplot(all_scenarios, aes(x = factor(year), y = (cost/1000000), fill=geotype)) + +costs_geotypes <- ggplot(all_scenarios, aes(x = factor(year), y = (cost/1000000), fill=geotype)) + scale_fill_brewer(palette="Spectral", name = expression('Geotype')) + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + geom_bar(stat="identity") + labs(title = "Annual Investment Over The Study Period", subtitle = "Results reported by scenario, strategy and geotype", x = NULL, y = "Investment Cost (Millions of Pounds)") + - facet_grid(scenario~strategy) + facet_grid(scenario~strategy) ### EXPORT TO FOLDER @@ -210,7 +210,7 @@ postcode_sectors <- postcode_sectors[which( postcode_sectors$lad== 'E07000178' | postcode_sectors$lad== 'E07000179' | postcode_sectors$lad== 'E07000180' | - postcode_sectors$lad== 'E07000181' + postcode_sectors$lad== 'E07000181' ),] postcode_sectors$pop_density_km2 <- postcode_sectors$population / postcode_sectors$area_km2 @@ -239,11 +239,11 @@ all.shp <- all.shp[order(all.shp$rank), ] all.shp$geotype = ordered( all.shp$geotype, - levels=c( + levels=c( 'Rural 4', 'Rural 3', 'Rural 2', - 'Rural 1', + 'Rural 1', 'Suburban 2', 'Suburban 1', 'Urban' @@ -280,7 +280,7 @@ geotypes <- ggplot() + axis.title.x = element_blank() ) + guides(fill = guide_legend(reverse = TRUE)) + - labs(title = 'Postcode sector by geotype') + labs(title = 'Postcode sector by geotype') ### EXPORT TO FOLDER @@ -307,11 +307,11 @@ all.shp$rank <- 1:nrow(all.shp) all.shp <- merge(subset, all.shp, by = "id") all.shp <- all.shp[order(all.shp$rank), ] -all.shp$capacity <- cut(all.shp$capacity, breaks=c(-Inf,10,20,30,40,50,60,70,80,Inf)) +all.shp$capacity <- cut(all.shp$capacity, breaks=c(-Inf,10,20,30,40,50,60,70,80,Inf)) all.shp$capacity = ordered( all.shp$capacity, - levels=c( + levels=c( '(-Inf,10]', '(10,20]', '(20,30]', @@ -365,7 +365,7 @@ capacity <- ggplot() + axis.title.x = element_blank() ) + guides(fill = guide_legend(reverse = TRUE)) + - labs(title = 'Postcode sector by mean cell edge capacity') + labs(title = 'Postcode sector by mean cell edge capacity') ### EXPORT TO FOLDER @@ -380,7 +380,7 @@ dev.off() ################################################################################ initial_graphic <- ggarrange( - geotypes, + geotypes, capacity, labels = NULL, ncol = 1, @@ -392,9 +392,3 @@ setwd(output_directory) tiff('initial_graphic.tiff', units="in", width=8, height=8.5, res=700) print(initial_graphic) dev.off() - - - - - - diff --git a/vis/vis.R b/vis/vis.R index 52cb750..b75b827 100644 --- a/vis/vis.R +++ b/vis/vis.R @@ -183,6 +183,7 @@ aggregate_metrics_func <- function(mydata) capacity_density_mbps_km2 = round((aggregate_capacity_gbps*1000) / area,1), capacity_margin_density_mbps_km2 = round((aggregate_capacity_deficit_gbps*1000) / area,1), + mean_capacity_per_person_market_share_25 = round( (aggregate_capacity_gbps*1000) / ((pop_density_km2*area) * 0.25 / 50),1) ) %>% From de1438e3f5cbff92779dd3557bb7a5ed8cf2aaeb Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:53:18 +0000 Subject: [PATCH 10/20] Add contributing guidelines --- CONTRIBUTING.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..58d4f74 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,92 @@ +======================= +Contributing Guidelines +======================= + +We welcome contributions to cdcam. + +When submitting a change to the repository, please first create an issue that +covers the item that you'd like to change, update or enhance. Once a discussion +has yielded a vote of support for that addition to the package, you are ready +to submit a pull request. + +If you are proposing a feature: + +* Explain in detail how it would work. +* Keep the scope as narrow as possible, to make it easier to implement. + +Create a branch for local development +------------------------------------- + +Use the ``git checkout`` command to create your own branch, and pick a name +that describes the changes that you are making:: + + $ git checkout -b name-of-your-bugfix-or-feature + +Now you can make your changes locally. + +Test the package +---------------- + +Ensure that the tests pass, and the documentation builds successfully:: + + $ pytest + $ make docs + +Commit and push your changes +---------------------------- + +Once you are sure that all tests are passing, you can commit your changes +and push to GitHub:: + + $ git add . + $ git commit -m "Your detailed description of your changes." + $ git push origin name-of-your-bugfix-or-feature + +Submit a pull request on GitHub +------------------------------- + +When submitting a pull request: + +- All existing tests should pass. Please make sure that the test + suite passes, both locally and on + `Travis CI `_ + Status on + Travis will be visible on a pull request. If you want to enable + Travis CI on your own fork, please read the + `getting started docs `_. + +- New functionality should include tests. Please write reasonable + tests for your code and make sure that they pass on your pull request. + +- Classes, methods, functions, etc. should have docstrings. The first + line of a docstring should be a standalone summary. Parameters and + return values should be documented explicitly. + +- The API documentation is automatically generated from docstrings, which + should conform to NumpPy styling. For examples, see the `Napoleon docs + `_. + +- Please note that tests are also run via Travis-CI on our documentation. + So be sure that any ``.rst`` file submissions are properly formatted and + tests are passing. + + +Documentation Updates +===================== + +Improving the documentation and testing for code already in ``cdcam`` +is a great way to get started if you'd like to make a contribution. Please note +that our documentation files are in +`ReStructuredText (.rst) +`_ +format and format your pull request accordingly. + +To build the documentation, use the command:: + + $ make docs + +By default ``make docs`` will only rebuild the documentation if source +files (e.g., .py or .rst files) have changed. To force a rebuild, use +``make -B docs``. +You can preview the generated documentation by opening +``docs/_build/html/index.html`` in a web browser. From 344e841748e010ef6174faa291780f8815fa9fe5 Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:53:32 +0000 Subject: [PATCH 11/20] Add contributions/support sections --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 85c840a..2c06e09 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,16 @@ If you want to quickly generate results, first download the sample dataset avail More details are provided in the [Getting Started](https://cdcam.readthedocs.io/en/latest/getting-started.html) documentation. +Contributions +------------- + +Contributions to this package are welcomed via the usual pull request mechanism. + +Support +------- + +If you encounter a bug, feel the documentation is incorrect or incomplete, or want to suggest +new features, please post an issue in the [issues](https://github.com/nismod/cdcam/issues) tab. Background and funding ====================== From 8343a0a2a2649384bbcd0e7014ef486d222c8bc2 Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:53:44 +0000 Subject: [PATCH 12/20] Remove statement of need/applications --- docs/getting-started.rst | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/docs/getting-started.rst b/docs/getting-started.rst index 66b2394..2f211eb 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -1,28 +1,3 @@ -================= -Statement of Need -================= - -Every decade a new generation of cellular technology is standardised and released. -Increasingly, given the importance of the Internet of Things, Industry 4.0 and Smart Health -applications, both governments and other digital ecosystem actors want to understand the costs -associated with digital connectivity. - -However, there are very few geospatial open-source tools to help simultaneously understand -both the engineering and cost implications of new connectivity technologies such as 5G. Hence, -``cdcam`` has been developed to address this key research need. - -============ -Applications -============ - -``cdcam`` has already been used to test the capacity, coverage and cost of 5G infrastructure -in Britain [@Oughton:2018a; @Oughton:2018b] and the Netherlands [@Oughton:2019a]. - -The model is one of several infrastructure simulation models being used in ongoing research -as part of the ITRC Mistral project to analyse national infrastructure systems-of-systems, -using scenarios of population change generated by ``simim`` [@simim] and connected by a -simulation model coupling library, ``smif`` [@smif]. - =============== Getting Started =============== From e88dfd65143db07ea76048c9fd2a2ef6509ec612 Mon Sep 17 00:00:00 2001 From: ej550 Date: Mon, 2 Dec 2019 10:53:54 +0000 Subject: [PATCH 13/20] Add statement of need/applications --- docs/index.rst | 80 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index c3e1738..bce544c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -32,6 +32,29 @@ Citations Capacity, Coverage and Cost of 5G Infrastructure Strategies: Analysis of The Netherlands. Telematics and Informatics (January). https://doi.org/10.1016/j.tele.2019.01.003. +Statement of Need +----------------- + +Every decade a new generation of cellular technology is standardised and released. +Increasingly, given the importance of the Internet of Things, Industry 4.0 and Smart Health +applications, both governments and other digital ecosystem actors want to understand the costs +associated with digital connectivity. + +However, there are very few geospatial open-source tools to help simultaneously understand +both the engineering and cost implications of new connectivity technologies such as 5G. Hence, +``cdcam`` has been developed to address this key research need. + +Applications +------------ + +``cdcam`` has already been used to test the capacity, coverage and cost of 5G infrastructure +in Britain [@Oughton:2018a; @Oughton:2018b] and the Netherlands [@Oughton:2019a]. + +The model is one of several infrastructure simulation models being used in ongoing research +as part of the ITRC Mistral project to analyse national infrastructure systems-of-systems, +using scenarios of population change generated by ``simim`` [@simim] and connected by a +simulation model coupling library, ``smif`` [@smif]. + Setup and configuration ----------------------- @@ -42,6 +65,53 @@ All code for ``cdcam`` is written in Python (Python>=3.5) and has a number of de pip install cdcam +Using a virtual environment +--------------------------- + +To set up a virtual environment follow the code below:: + + python -m venv cdcam + cdcam/bin/python cdcam/bin/pip install -r requirements.txt + cdcam/bin/python cdcam/bin/pip install -r requirements-dev.txt + cdcam/bin/python cdcam/bin/pip install cdcam + cdcam/bin/python cdcam/bin/pip install pytest pytest-cov + pytest --cov-report=term --cov=cdcam tests/ + +Using conda +----------- + +The recommended installation method is to use [conda](http://conda.pydata.org/miniconda.html), +which handles packages and virtual environments, along with the +[`conda-forge`](https://conda-forge.org/) channel which has a host of pre-built libraries and +packages. + +Create a conda environment called `cdcam`: + + conda create --name cdcam python=3.7 + +Activate it (run this each time you switch projects): + + conda activate cdcam + +First, install optional packages: + + conda install fiona shapely rtree pyproj tqdm + +Then install `cdcam`: + + pip install cdcam + +Alternatively, for development purposes, clone this repository and run: + + python setup.py develop + +Install test/dev requirements: + + conda install pytest pytest-cov + +Run the tests: + + pytest --cov-report=term --cov=cdcam tests/ Background and funding ---------------------- @@ -63,16 +133,6 @@ Consortium `_ (EP/N017064/1) and (ii) the UK's `Digital Contents -------- -.. toctree:: - :maxdepth: 2 - - Statement of Need - -.. toctree:: - :maxdepth: 2 - - Applications - .. toctree:: :maxdepth: 2 From bd890cb29695492c0c7e9189f8c99fdbe8b9987a Mon Sep 17 00:00:00 2001 From: ej550 Date: Sat, 7 Dec 2019 16:50:13 +0000 Subject: [PATCH 14/20] Add reprex --- scripts/reprex.py | 204 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 scripts/reprex.py diff --git a/scripts/reprex.py b/scripts/reprex.py new file mode 100644 index 0000000..d04576a --- /dev/null +++ b/scripts/reprex.py @@ -0,0 +1,204 @@ + + +from cdcam.model import NetworkManager +from cdcam.interventions import decide_interventions + +lads = [ + { + "id": 1, + "name": "Cambridge", + } + ] + +pcd_sectors = [ + { + "id": "CB11", + "lad_id": 1, + "population": 5000, + "area_km2": 2, + "user_throughput": 2, + }, + { + "id": "CB12", + "lad_id": 1, + "population": 20000, + "area_km2": 2, + "user_throughput": 2, + } + ] + +clutter_lookup = [ + (0.0, 'rural'), (782.0, 'suburban'), (7959.0, 'urban') +] + +population_by_scenario_year_pcd = { + 'baseline':{ + 2020: { + 'CB11': 100000, + 'CB12': 200000, + }, + 2021: { + 'CB11': 110000, + 'CB12': 220000, + }, + } +} + +user_throughput_by_scenario_year = { + 'baseline': { + 2020: 1, + 2021: 2 + } +} + +initial_system = [ + { + "pcd_sector": "CB11", + "site_ngr": "site_100", + "technology": "", + "type": "macrocell_site", + "frequency": [], + "bandwidth": "", + "build_date": 2012, + "sectors": 3, + 'opex': 10000, + }, + { + "pcd_sector": "CB12", + "site_ngr": "site_200", + "technology": "", + "type": "macrocell_site", + "frequency": [], + "bandwidth": "", + "build_date": 2012, + "sectors": 3, + 'opex': 10000, + } + ] + +capacity_lookup_table = { + ('urban', 'macro', '800', '10', '4G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'macro', '2600', '10', '4G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'macro', '700', '10', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'macro', '3500', '40', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'macro', '26000', '200', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'micro', '800', '10', '4G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'micro', '2600', '10', '4G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'micro', '3700', '40', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'micro', '26000', '200', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'micro', '26000', '200', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], +} + +if __name__ == '__main__': + + simulation_parameters = { + 'market_share': 0.3, + 'annual_budget': 1e6, + 'service_obligation_capacity': 10, + 'busy_hour_traffic_percentage': 20, + 'coverage_threshold': 100, + 'penetration': 80, + 'channel_bandwidth_700': '10', + 'channel_bandwidth_800': '10', + 'channel_bandwidth_1800': '10', + 'channel_bandwidth_2600': '10', + 'channel_bandwidth_3500': '40', + 'channel_bandwidth_3700': '40', + 'channel_bandwidth_26000': '200', + 'macro_sectors': 3, + 'small-cell_sectors': 1, + 'mast_height': 30, + } + + BASE_YEAR = 2020 + END_YEAR = 2022 + TIMESTEP_INCREMENT = 1 + TIMESTEPS = range(BASE_YEAR, END_YEAR + 1, TIMESTEP_INCREMENT) + + for pop_scenario, throughput_scenario, intervention_strategy in [ + + ('baseline', 'baseline', 'small-cell-and-spectrum'), + + ]: + print("Running:", pop_scenario, throughput_scenario, intervention_strategy) + + assets = initial_system[:] + + for year in TIMESTEPS: + print('---------------------------------------------') + print(' ') + print("-", year) + print(' ') + + for pcd_sector in pcd_sectors: + try: + pcd_sector_id = pcd_sector["id"] + pcd_sector["population"] = ( + population_by_scenario_year_pcd \ + [pop_scenario][year][pcd_sector_id]) + pcd_sector["user_throughput"] = ( + user_throughput_by_scenario_year \ + [throughput_scenario][year]) + except: + pass + + budget = simulation_parameters['annual_budget'] + service_obligation_capacity = simulation_parameters['service_obligation_capacity'] + + if year == BASE_YEAR: + system = NetworkManager(lads, pcd_sectors, assets, + capacity_lookup_table, clutter_lookup, + simulation_parameters) + + interventions_built, budget, spend = decide_interventions( + intervention_strategy, budget, service_obligation_capacity, + system, year, simulation_parameters) + + print(' ') + print('Built {} new assets in {}:'.format(len(spend), year)) + + print('-- {} LTE Macro Cells'.format( + len([a for a in interventions_built if a['type'] == 'macrocell_site' \ + and a['technology'] == 'LTE']))) + + print('-- {} 5G Macro Cells'.format( + len([a for a in interventions_built if a['type'] == 'macrocell_site' \ + and a['technology'] == '5G']))) + + print('-- {} 5G Small Cells'.format( + len([a for a in interventions_built if a['technology'] == 'small_cell']))) + + print(' ') + + #Add new assets to existing system assets + assets += interventions_built + + system = NetworkManager(lads, pcd_sectors, assets, + capacity_lookup_table, clutter_lookup, + simulation_parameters) + + print(' ') + print('**Financials**') + print('£££ - Spent £{} million'.format(round((simulation_parameters['annual_budget'] - budget) / 1e6, 1))) + print('£££ - Budget remaining £{} million'.format(round(budget / 1e6, 1))) + print(' ') From 9c01c288cc1567caebfe894ffe10fcd4d222874a Mon Sep 17 00:00:00 2001 From: ej550 Date: Sat, 7 Dec 2019 16:50:29 +0000 Subject: [PATCH 15/20] Improve formatting --- src/cdcam/interventions.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/cdcam/interventions.py b/src/cdcam/interventions.py index 22bb441..98deede 100644 --- a/src/cdcam/interventions.py +++ b/src/cdcam/interventions.py @@ -173,7 +173,8 @@ def decide_interventions(strategy, budget, service_obligation_capacity, if service_obligation_capacity > 0: service_built, budget, service_spend = meet_service_obligation(budget, - available_interventions, timestep, service_obligation_capacity, system, simulation_parameters) + available_interventions, timestep, service_obligation_capacity, + system, simulation_parameters) else: service_built = [] service_spend = [] @@ -284,8 +285,11 @@ def _suggest_interventions(budget, available_interventions, areas, timestep, for site_ngr, site_assets in assets_by_site.items(): if site_ngr == 'small_cell_site': continue - if 'LTE' not in [asset['technology'] for asset in site_assets]: + # built_lte = + if ('LTE' not in [asset['technology'] for asset in site_assets] and site_ngr not in + [a['site_ngr'] for a in area_interventions if a['technology'] == 'LTE']): # set both assets to this site_ngr + for option in build_option: to_build = copy.copy(option) to_build['site_ngr'] = site_ngr @@ -307,6 +311,7 @@ def _suggest_interventions(budget, available_interventions, areas, timestep, # integrate_700 if 'carrier_700' in available_interventions and timestep >= 2020: + if _area_satisfied(area, area_interventions, threshold, simulation_parameters): continue @@ -315,8 +320,10 @@ def _suggest_interventions(budget, available_interventions, areas, timestep, for site_ngr, site_assets in assets_by_site.items(): if site_ngr == 'small_cell_site': continue + if 'LTE' in [asset['technology'] for asset in site_assets] and \ '700' not in [asset['frequency'] for asset in site_assets]: + # set both assets to this site_ngr for option in build_option: to_build = copy.copy(option) From e9fe27628a6adec24413546fee22ace822f7c1bf Mon Sep 17 00:00:00 2001 From: ej550 Date: Sat, 7 Dec 2019 16:50:44 +0000 Subject: [PATCH 16/20] Enhance tests --- tests/conftest.py | 80 ++++++++++++++++++++++++++++++ tests/test_mobile_interventions.py | 67 +++++++++++++++++++++---- 2 files changed, 138 insertions(+), 9 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 087cfde..9c01003 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -34,6 +34,26 @@ def setup_pcd_sector(): ] +@fixture(scope='function') +def setup_pcd_sectors2(): + return [ + { + "id": "CB11", + "lad_id": 1, + "population": 100000, + "area_km2": 2, + "user_throughput": 2, + }, + { + "id": "CB12", + "lad_id": 1, + "population": 100000, + "area_km2": 2, + "user_throughput": 2, + } + ] + + @fixture(scope='function') def setup_non_4g_assets(): return [ @@ -217,7 +237,9 @@ def setup_capacity_lookup(): ], ("rural", "macro", "26000", "200", "5G"): [ (0, 0), + (0.1, 10), (2, 100), + (4, 200), ], ("urban", "micro", "700", "10", "5G"): [ (0, 0), @@ -271,10 +293,46 @@ def setup_capacity_lookup(): ], ("rural", "micro", "26000", "200", "5G"): [ (0, 0), + (0.1, 10), (2, 100), + (4, 200), ], } +@fixture(scope='function') +def setup_capacity_lookup_table2(): + return { + ('urban', 'macro', '800', '10', '4G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'macro', '2600', '10', '4G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'macro', '700', '10', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'macro', '3500', '40', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'macro', '26000', '200', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'micro', '800', '10', '4G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'micro', '2600', '10', '4G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'micro', '3700', '40', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'micro', '26000', '200', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], + ('urban', 'micro', '26000', '200', '5G'): [ + (0.01, 1), (0.1, 10), (1, 100), (2, 200) + ], +} @fixture(scope='function') def setup_clutter_lookup(): @@ -305,3 +363,25 @@ def setup_simulation_parameters(): 'small_cell_sectors': 1, 'mast_height': 30, } + + +@pytest.fixture +def setup_simulation_parameters2(): + return { + 'market_share': 0.3, + 'annual_budget': 1e6, + 'service_obligation_capacity': 10, + 'busy_hour_traffic_percentage': 20, + 'coverage_threshold': 100, + 'penetration': 80, + 'channel_bandwidth_700': '10', + 'channel_bandwidth_800': '10', + 'channel_bandwidth_1800': '10', + 'channel_bandwidth_2600': '10', + 'channel_bandwidth_3500': '40', + 'channel_bandwidth_3700': '40', + 'channel_bandwidth_26000': '200', + 'macro_sectors': 3, + 'small-cell_sectors': 1, + 'mast_height': 30, + } diff --git a/tests/test_mobile_interventions.py b/tests/test_mobile_interventions.py index c23cf90..fdd54c4 100644 --- a/tests/test_mobile_interventions.py +++ b/tests/test_mobile_interventions.py @@ -45,8 +45,33 @@ def mixed_system(setup_lad, setup_pcd_sector, setup_mixed_assets, return system +@pytest.fixture +def empty_system(setup_lad, setup_pcd_sectors2, setup_non_4g_assets, + setup_capacity_lookup_table2, setup_clutter_lookup, + setup_simulation_parameters2): + + system = NetworkManager(setup_lad, setup_pcd_sectors2, + setup_non_4g_assets, setup_capacity_lookup_table2, setup_clutter_lookup, + setup_simulation_parameters2) + + return system + + +@pytest.fixture +def high_demand_system(setup_lad, setup_pcd_sectors2, setup_assets, + setup_capacity_lookup_table2, setup_clutter_lookup, + setup_simulation_parameters2): + + system = NetworkManager(setup_lad, setup_pcd_sectors2, + setup_assets, setup_capacity_lookup_table2, setup_clutter_lookup, + setup_simulation_parameters2) + + return system + + def test_decide_interventions(non_4g_system, basic_system, - mixed_system, setup_simulation_parameters): + mixed_system, empty_system, high_demand_system, setup_simulation_parameters, + setup_simulation_parameters2): actual_result = decide_interventions( 'minimal', 250000, 0, @@ -87,14 +112,6 @@ def test_decide_interventions(non_4g_system, basic_system, assert len(actual_result[0]) == 0 assert actual_result[1] == 203668 - # actual_result = decide_interventions( - # 'macrocell_700', 50917, 10, - # mixed_system, 2020, setup_simulation_parameters - # ) - - # assert len(actual_result[0]) == 1 - # assert actual_result[1] == 0 - # #50917 * 2 = 101,834 # #40220 * 3 = £120,660 actual_result = decide_interventions( @@ -104,3 +121,35 @@ def test_decide_interventions(non_4g_system, basic_system, assert len(actual_result[0]) == 4 assert actual_result[1] == 0 + + #test empty_system + actual_result = decide_interventions( + 'small-cell-and-spectrum', 1e7 , 0, + empty_system, 2020, setup_simulation_parameters2 + ) + + macros_to_lte = len([a for a in actual_result[0] if a['type'] == 'macrocell_site' \ + and a['technology'] == 'LTE']) + + assert macros_to_lte == 4 + + #test high_demand_system + actual_result = decide_interventions( + 'small-cell-and-spectrum', 1e7 , 0, + high_demand_system, 2020, setup_simulation_parameters2 + ) + + macros_to_5g = len([a for a in actual_result[0] if a['type'] == 'macrocell_site' \ + and a['technology'] == '5G']) + + assert macros_to_5g == 6 + + #test small cell build + actual_result = decide_interventions( + 'small-cell-and-spectrum', 1e6 , 0, + high_demand_system, 2020, setup_simulation_parameters2 + ) + + small_cells = len([a for a in actual_result[0] if a['type'] == 'small_cell']) + + assert small_cells == 2 From 85ab84c691b62895721f3294bb20245ed06a36fb Mon Sep 17 00:00:00 2001 From: ej550 Date: Sat, 7 Dec 2019 16:51:50 +0000 Subject: [PATCH 17/20] Remove unwanted print statements --- src/cdcam/model.py | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/cdcam/model.py b/src/cdcam/model.py index c2b1722..bcc7f3b 100644 --- a/src/cdcam/model.py +++ b/src/cdcam/model.py @@ -134,7 +134,6 @@ def __init__(self, lads, pcd_sectors, assets, capacity_lookup_table, lad_containing_pcd_sector.add_pcd_sector(pcd_sector) except: print('could not create object for {}'.format(pcd_sector_data["id"])) - print(pcd_sector_data) pass @@ -490,11 +489,13 @@ def _macrocell_site_capacity(self, simulation_parameters): capacity = 0 for frequency in ['700', '800', '1800', '2600', '3500', '26000']: + unique_sites = set() for asset in self.assets: for asset_frequency in asset['frequency']: if asset_frequency == frequency: + unique_sites.add(asset['site_ngr']) site_density = float(len(unique_sites)) / self.area @@ -507,15 +508,18 @@ def _macrocell_site_capacity(self, simulation_parameters): else: generation = '4G' - tech_capacity = lookup_capacity( - self._capacity_lookup_table, - self.clutter_environment, - 'macro', - frequency, - bandwidth, - generation, - site_density, - ) + if site_density > 0: + tech_capacity = lookup_capacity( + self._capacity_lookup_table, + self.clutter_environment, + 'macro', + frequency, + bandwidth, + generation, + site_density, + ) + else: + tech_capacity = 0 capacity += tech_capacity @@ -543,15 +547,18 @@ def small_cell_capacity(self, simulation_parameters): bandwidth = find_frequency_bandwidth(frequency, simulation_parameters) - tech_capacity = lookup_capacity( - self._capacity_lookup_table, - self.clutter_environment, - "micro", - frequency, - bandwidth, - "5G", - site_density, - ) + if site_density > 0 : + tech_capacity = lookup_capacity( + self._capacity_lookup_table, + self.clutter_environment, + "micro", + frequency, + bandwidth, + "5G", + site_density, + ) + else: + tech_capacity = 0 capacity += tech_capacity From 34b4ee44ff499247d2ad5c34f1924fb016c7bf4c Mon Sep 17 00:00:00 2001 From: ej550 Date: Sat, 7 Dec 2019 17:09:55 +0000 Subject: [PATCH 18/20] Update reqs --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index deea9bb..924d1f6 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,8 +1,8 @@ # requirements for running scripts: preprocess and run +shapely>=1.6 fiona>=1.7.13 pyproj>=2 rtree>=0.8 -shapely>=1.6 tqdm # test/lint From 6aa651b48ed9b08a135f082c0cfdef49bbacb120 Mon Sep 17 00:00:00 2001 From: ej550 Date: Sat, 7 Dec 2019 17:20:21 +0000 Subject: [PATCH 19/20] Update --- requirements-dev.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 924d1f6..5f8f4ba 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,7 +1,7 @@ # requirements for running scripts: preprocess and run shapely>=1.6 -fiona>=1.7.13 -pyproj>=2 +fiona>=1.8.13 +pyproj>=2.4 rtree>=0.8 tqdm From 388d98ace9c298fd19fd34d95148cc5d8108bd0b Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Mon, 9 Dec 2019 10:08:22 +0000 Subject: [PATCH 20/20] Move requirements for preprocessing from -dev.txt --- requirements-dev.txt | 7 ------- requirements.txt | 6 ++++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 5f8f4ba..30a7ddd 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,10 +1,3 @@ -# requirements for running scripts: preprocess and run -shapely>=1.6 -fiona>=1.8.13 -pyproj>=2.4 -rtree>=0.8 -tqdm - # test/lint pylint pytest>=3.6 diff --git a/requirements.txt b/requirements.txt index 5d06401..40fecee 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,7 @@ # requirements for cdcam package +# requirements for running scripts: preprocess and run +shapely>=1.6 +fiona>=1.8.13 +pyproj>=2.4 +rtree>=0.8 +tqdm