huff 1.1.1__tar.gz → 1.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {huff-1.1.1 → huff-1.1.2}/PKG-INFO +2 -1
  2. {huff-1.1.1 → huff-1.1.2}/README.md +1 -0
  3. {huff-1.1.1 → huff-1.1.2}/huff/gistools.py +50 -3
  4. {huff-1.1.1 → huff-1.1.2}/huff/models.py +69 -46
  5. {huff-1.1.1 → huff-1.1.2}/huff/ors.py +2 -2
  6. {huff-1.1.1 → huff-1.1.2}/huff/tests/tests_huff.py +2 -2
  7. {huff-1.1.1 → huff-1.1.2}/huff.egg-info/PKG-INFO +2 -1
  8. {huff-1.1.1 → huff-1.1.2}/setup.py +1 -1
  9. {huff-1.1.1 → huff-1.1.2}/MANIFEST.in +0 -0
  10. {huff-1.1.1 → huff-1.1.2}/huff/__init__.py +0 -0
  11. {huff-1.1.1 → huff-1.1.2}/huff/tests/__init__.py +0 -0
  12. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach.cpg +0 -0
  13. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach.dbf +0 -0
  14. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach.prj +0 -0
  15. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach.qmd +0 -0
  16. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach.shp +0 -0
  17. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach.shx +0 -0
  18. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach_supermarkets.cpg +0 -0
  19. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach_supermarkets.dbf +0 -0
  20. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach_supermarkets.prj +0 -0
  21. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach_supermarkets.qmd +0 -0
  22. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach_supermarkets.shp +0 -0
  23. {huff-1.1.1 → huff-1.1.2}/huff/tests/data/Haslach_supermarkets.shx +0 -0
  24. {huff-1.1.1 → huff-1.1.2}/huff.egg-info/SOURCES.txt +0 -0
  25. {huff-1.1.1 → huff-1.1.2}/huff.egg-info/dependency_links.txt +0 -0
  26. {huff-1.1.1 → huff-1.1.2}/huff.egg-info/requires.txt +0 -0
  27. {huff-1.1.1 → huff-1.1.2}/huff.egg-info/top_level.txt +0 -0
  28. {huff-1.1.1 → huff-1.1.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: huff
3
- Version: 1.1.1
3
+ Version: 1.1.2
4
4
  Summary: huff: Huff Model Market Area Analysis
5
5
  Author: Thomas Wieland
6
6
  Author-email: geowieland@googlemail.com
@@ -29,6 +29,7 @@ See the /tests directory for usage examples of most of the included functions.
29
29
 
30
30
  Attribution of OpenRouteService:
31
31
  © openrouteservice.org by HeiGIT | Map data © OpenStreetMap contributors
32
+
32
33
  Visit https://openrouteservice.org/
33
34
 
34
35
  ## Literature
@@ -21,6 +21,7 @@ See the /tests directory for usage examples of most of the included functions.
21
21
 
22
22
  Attribution of OpenRouteService:
23
23
  © openrouteservice.org by HeiGIT | Map data © OpenStreetMap contributors
24
+
24
25
  Visit https://openrouteservice.org/
25
26
 
26
27
  ## Literature
@@ -4,13 +4,60 @@
4
4
  # Author: Thomas Wieland
5
5
  # ORCID: 0000-0001-5168-9846
6
6
  # mail: geowieland@googlemail.com
7
- # Version: 1.1.1
8
- # Last update: 2025-04-29 18:12
7
+ # Version: 1.1.2
8
+ # Last update: 2025-05-03 13:30
9
9
  # Copyright (c) 2025 Thomas Wieland
10
10
  #-----------------------------------------------------------------------
11
11
 
12
12
 
13
- import geopandas as gp
13
+ import geopandas as gp
14
+ from math import pi, sin, cos, acos
15
+
16
+
17
+ def distance_matrix(
18
+ sources: list,
19
+ destinations: list,
20
+ unit: str = "m",
21
+ ):
22
+
23
+ def euclidean_distance (
24
+ source: list,
25
+ destination: list,
26
+ unit: str = "m"
27
+ ):
28
+
29
+ lon1 = source[0]
30
+ lat1 = source[1]
31
+ lon2 = destination[0]
32
+ lat2 = destination[1]
33
+
34
+ lat1_r = lat1*pi/180
35
+ lon1_r = lon1*pi/180
36
+ lat2_r = lat2*pi/180
37
+ lon2_r = lon2*pi/180
38
+
39
+ distance = 6378 * (acos(sin(lat1_r) * sin(lat2_r) + cos(lat1_r) * cos(lat2_r) * cos(lon2_r - lon1_r)))
40
+ if unit == "m":
41
+ distance = distance*1000
42
+ if unit == "mile":
43
+ distance = distance/1.60934
44
+
45
+ return distance
46
+
47
+ matrix = []
48
+
49
+ for source in sources:
50
+ row = []
51
+ for destination in destinations:
52
+ dist = euclidean_distance(
53
+ source,
54
+ destination,
55
+ unit
56
+ )
57
+ row.append(dist)
58
+ matrix.append(row)
59
+
60
+ return matrix
14
61
 
15
62
 
16
63
  def overlay_difference(
@@ -4,8 +4,8 @@
4
4
  # Author: Thomas Wieland
5
5
  # ORCID: 0000-0001-5168-9846
6
6
  # mail: geowieland@googlemail.com
7
- # Version: 1.1.1
8
- # Last update: 2025-04-29 18:12
7
+ # Version: 1.1.2
8
+ # Last update: 2025-05-03 13:29
9
9
  # Copyright (c) 2025 Thomas Wieland
10
10
  #-----------------------------------------------------------------------
11
11
 
@@ -15,7 +15,7 @@ import geopandas as gp
15
15
  import numpy as np
16
16
  import time
17
17
  from huff.ors import Client, TimeDistanceMatrix, Isochrone
18
- from huff.gistools import overlay_difference
18
+ from huff.gistools import overlay_difference, distance_matrix
19
19
 
20
20
 
21
21
  class CustomerOrigins:
@@ -373,13 +373,19 @@ class InteractionMatrix:
373
373
 
374
374
  def transport_costs(
375
375
  self,
376
+ network: bool = True,
376
377
  range_type: str = "time",
377
378
  time_unit: str = "minutes",
379
+ distance_unit: str = "kilometers",
378
380
  ors_server: str = "https://api.openrouteservice.org/v2/",
379
381
  ors_auth: str = None,
380
382
  save_output: bool = False,
381
383
  output_filepath: str = "transport_costs_matrix.csv"
382
384
  ):
385
+
386
+ if not network and range_type == "time":
387
+ print ("Calculating euclidean distances (network = False). Setting range_type = 'distance'")
388
+ range_type = "distance"
383
389
 
384
390
  interaction_matrix_df = self.get_interaction_matrix_df()
385
391
 
@@ -401,53 +407,70 @@ class InteractionMatrix:
401
407
 
402
408
  customer_origins_index = list(range(len(customer_origins_coords)))
403
409
  locations_coords_index = list(range(len(customer_origins_index), len(locations_coords)))
404
-
405
- ors_client = Client(
406
- server = ors_server,
407
- auth = ors_auth
408
- )
409
- time_distance_matrix = ors_client.matrix(
410
- locations = locations_coords,
411
- save_output = save_output,
412
- output_filepath = output_filepath,
413
- sources = customer_origins_index,
414
- destinations = locations_coords_index,
415
- range_type = range_type
416
- )
417
-
418
- if time_distance_matrix.get_metadata() is None:
419
- raise ValueError ("No transport costs matrix was built.")
420
410
 
421
- transport_costs_matrix = time_distance_matrix.get_matrix()
422
- transport_costs_matrix_config = time_distance_matrix.get_config()
423
- range_type = transport_costs_matrix_config["range_type"]
411
+ if network:
424
412
 
425
- transport_costs_matrix["source"] = transport_costs_matrix["source"].astype(int)
426
- transport_costs_matrix["source"] = transport_costs_matrix["source"].map(
427
- dict(enumerate(customer_origins_ids))
428
- )
429
-
430
- transport_costs_matrix["destination"] = transport_costs_matrix["destination"].astype(int)
431
- transport_costs_matrix["destination"] = transport_costs_matrix["destination"].map(
432
- dict(enumerate(supply_locations_ids))
433
- )
434
-
435
- transport_costs_matrix["source_destination"] = transport_costs_matrix["source"].astype(str)+"_"+transport_costs_matrix["destination"].astype(str)
436
- transport_costs_matrix = transport_costs_matrix[["source_destination", range_type]]
413
+ ors_client = Client(
414
+ server = ors_server,
415
+ auth = ors_auth
416
+ )
417
+ time_distance_matrix = ors_client.matrix(
418
+ locations = locations_coords,
419
+ save_output = save_output,
420
+ output_filepath = output_filepath,
421
+ sources = customer_origins_index,
422
+ destinations = locations_coords_index,
423
+ range_type = range_type
424
+ )
425
+
426
+ if time_distance_matrix.get_metadata() is None:
427
+ raise ValueError ("No transport costs matrix was built.")
437
428
 
438
- interaction_matrix_df = interaction_matrix_df.merge(
439
- transport_costs_matrix,
440
- left_on="ij",
441
- right_on="source_destination"
442
- )
443
-
444
- interaction_matrix_df["t_ij"] = interaction_matrix_df[range_type]
445
- if time_unit == "minutes":
446
- interaction_matrix_df["t_ij"] = interaction_matrix_df["t_ij"]/60
447
- if time_unit == "hours":
448
- interaction_matrix_df["t_ij"] = interaction_matrix_df["t_ij"]/60/60
429
+ transport_costs_matrix = time_distance_matrix.get_matrix()
430
+ transport_costs_matrix_config = time_distance_matrix.get_config()
431
+ range_type = transport_costs_matrix_config["range_type"]
432
+
433
+ transport_costs_matrix["source"] = transport_costs_matrix["source"].astype(int)
434
+ transport_costs_matrix["source"] = transport_costs_matrix["source"].map(
435
+ dict(enumerate(customer_origins_ids))
436
+ )
437
+
438
+ transport_costs_matrix["destination"] = transport_costs_matrix["destination"].astype(int)
439
+ transport_costs_matrix["destination"] = transport_costs_matrix["destination"].map(
440
+ dict(enumerate(supply_locations_ids))
441
+ )
442
+
443
+ transport_costs_matrix["source_destination"] = transport_costs_matrix["source"].astype(str)+"_"+transport_costs_matrix["destination"].astype(str)
444
+ transport_costs_matrix = transport_costs_matrix[["source_destination", range_type]]
445
+
446
+ interaction_matrix_df = interaction_matrix_df.merge(
447
+ transport_costs_matrix,
448
+ left_on="ij",
449
+ right_on="source_destination"
450
+ )
451
+
452
+ interaction_matrix_df["t_ij"] = interaction_matrix_df[range_type]
453
+ if time_unit == "minutes":
454
+ interaction_matrix_df["t_ij"] = interaction_matrix_df["t_ij"]/60
455
+ if time_unit == "hours":
456
+ interaction_matrix_df["t_ij"] = interaction_matrix_df["t_ij"]/60/60
457
+
458
+ interaction_matrix_df = interaction_matrix_df.drop(columns=["source_destination", range_type])
459
+
460
+ else:
461
+
462
+ distance_matrix_result = distance_matrix(
463
+ sources = customer_origins_coords,
464
+ destinations = supply_locations_coords,
465
+ unit = "m"
466
+ )
467
+
468
+ distance_matrix_result_flat = [distance for sublist in distance_matrix_result for distance in sublist]
469
+
470
+ interaction_matrix_df["t_ij"] = distance_matrix_result_flat
449
471
 
450
- interaction_matrix_df = interaction_matrix_df.drop(columns=["source_destination", range_type])
472
+ if distance_unit == "kilometers":
473
+ interaction_matrix_df["t_ij"] = interaction_matrix_df["t_ij"]/1000
451
474
 
452
475
  self.interaction_matrix_df = interaction_matrix_df
453
476
 
@@ -4,8 +4,8 @@
4
4
  # Author: Thomas Wieland
5
5
  # ORCID: 0000-0001-5168-9846
6
6
  # mail: geowieland@googlemail.com
7
- # Version: 1.1.1
8
- # Last update: 2025-04-29 18:12
7
+ # Version: 1.1.2
8
+ # Last update: 2025-05-03 13:33
9
9
  # Copyright (c) 2025 Thomas Wieland
10
10
  #-----------------------------------------------------------------------
11
11
 
@@ -4,8 +4,8 @@
4
4
  # Author: Thomas Wieland
5
5
  # ORCID: 0000-0001-5168-9846
6
6
  # mail: geowieland@googlemail.com
7
- # Version: 1.1.1
8
- # Last update: 2025-04-29 18:12
7
+ # Version: 1.1.2
8
+ # Last update: 2025-05-03 13:32
9
9
  # Copyright (c) 2025 Thomas Wieland
10
10
  #-----------------------------------------------------------------------
11
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: huff
3
- Version: 1.1.1
3
+ Version: 1.1.2
4
4
  Summary: huff: Huff Model Market Area Analysis
5
5
  Author: Thomas Wieland
6
6
  Author-email: geowieland@googlemail.com
@@ -29,6 +29,7 @@ See the /tests directory for usage examples of most of the included functions.
29
29
 
30
30
  Attribution of OpenRouteService:
31
31
  © openrouteservice.org by HeiGIT | Map data © OpenStreetMap contributors
32
+
32
33
  Visit https://openrouteservice.org/
33
34
 
34
35
  ## Literature
@@ -7,7 +7,7 @@ def read_README():
7
7
 
8
8
  setup(
9
9
  name='huff',
10
- version='1.1.1',
10
+ version='1.1.2',
11
11
  description='huff: Huff Model Market Area Analysis',
12
12
  packages=find_packages(include=["huff", "huff.tests"]),
13
13
  include_package_data=True,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes