Skip to content

Commit 189c5dd

Browse files
committed
Change DSM instigator
1 parent 7a60110 commit 189c5dd

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed

cpm/models.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,22 @@ class DSM:
88
one DSM for the likelihood of propagation, and one DSM for the impact of propagation.
99
"""
1010

11-
def __init__(self, matrix: list[list[Optional[float]]], columns: list[str]):
11+
def __init__(self, matrix: list[list[Optional[float]]], columns: list[str], instigator='column'):
1212
"""
1313
Construct a DSM using a matrix and column-header
1414
:param matrix: List matrix containing floats or empty cells
1515
:param columns: Matrix header
16+
:param instigator: Can either be **column** or **row**. Determines directionality of interactions in DSM.
17+
By default, propagation travels from column to row
1618
"""
1719
self.matrix = matrix
1820
self.columns = columns
19-
self.node_network: dict[int, 'GraphNode'] = self.build_node_network()
21+
self.node_network: dict[int, 'GraphNode'] = self.build_node_network(instigator)
2022

2123
def __str__(self):
2224
return f'{self.columns}\n{self.matrix}'
2325

24-
def build_node_network(self) -> dict[int, 'GraphNode']:
26+
def build_node_network(self, instigator: str) -> dict[int, 'GraphNode']:
2527
"""
2628
Construct a node network using the DSM.
2729
This enables path finding to be run on the system.\n
@@ -41,7 +43,12 @@ def build_node_network(self) -> dict[int, 'GraphNode']:
4143
if not col:
4244
continue
4345
# Add interaction to node network
44-
network_dict[j].add_neighbour(network_dict[i], float(col)) # Assumes cell only contains a float.
46+
if instigator == 'column':
47+
network_dict[j].add_neighbour(network_dict[i], float(col)) # Assumes cell only contains a float.
48+
elif instigator == 'row':
49+
network_dict[i].add_neighbour(network_dict[j], float(col))
50+
else:
51+
raise TypeError('Instigator needs to either be "column" or "row".')
4552

4653
return network_dict
4754

cpm/parse.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,18 @@
22
from cpm.models import DSM
33

44

5-
def parse_csv(filepath, delimiter='auto', encoding='utf8'):
5+
def parse_csv(filepath: str, delimiter: str = 'auto', encoding: str = 'utf-8', instigator: str = 'column'):
6+
"""
7+
Parse CSV to DSM
8+
:param filepath: Targeted CSV file
9+
:param delimiter: CSV delimiter. Defaults to auto-detection.
10+
:param encoding: text-encoding. Defaults to utf-8
11+
:param instigator: Determines directionality of DSM. Defaults to columns instigating rows.
12+
:return: DSM
13+
"""
614

715
if delimiter == 'auto':
8-
with open(filepath, 'r') as file:
16+
with open(filepath, 'r', encoding=encoding) as file:
917
delimiter = detect_delimiter(file.read())
1018

1119
# Identify number of rows, and separate header row
@@ -37,12 +45,18 @@ def parse_csv(filepath, delimiter='auto', encoding='utf8'):
3745
except ValueError:
3846
data[i - 1].append(None)
3947

40-
dsm = DSM(matrix=data, columns=column_names)
48+
dsm = DSM(matrix=data, columns=column_names, instigator=instigator)
4149

4250
return dsm
4351

4452

4553
def detect_delimiter(text, look_ahead=1000):
54+
"""
55+
Attempts to determine CSV delmiter based on a certain amount of sample characters
56+
:param text: text from CSV file
57+
:param look_ahead: number of samples from CSV-file used to guess the delimiter
58+
:return:
59+
"""
4660
symbol_map = dict({
4761
",": 0,
4862
";": 0,

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from setuptools import setup, find_packages
22

3-
VERSION = '1.0.6'
3+
VERSION = '1.0.7'
44
DESCRIPTION = 'Tool for calculating risk of change propagation in a system.'
55

66
with open("README.md", "r") as fh:

tests/test_parser.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,20 @@ def test_parse_dsm_network():
4141
assert len(b_neighbours) == 1
4242
assert b_neighbours[0] == 3
4343

44+
45+
def test_parse_dsm_network_instigator_row():
46+
dsm = parse_csv('./tests/test-assets/dsm-network-test.csv', instigator='row')
47+
assert dsm.node_network[3].name == 'D'
48+
d_neighbours = list(dsm.node_network[3].neighbours.keys())
49+
assert len(d_neighbours) == 1 # Should only have one connection
50+
assert d_neighbours[0] == 1 # Has neighbour with B
51+
b_neighbours = list(dsm.node_network[1].neighbours.keys())
52+
assert len(b_neighbours) == 1 # Should only have one
53+
assert b_neighbours[0] == 2 # B should be neighbour with C
54+
c_neighbours = list(dsm.node_network[2].neighbours.keys())
55+
assert len(c_neighbours) == 1
56+
assert c_neighbours[0] == 0
57+
a_neighbours = list(dsm.node_network[0].neighbours.keys())
58+
assert len(a_neighbours) == 1
59+
assert a_neighbours[0] == 3
60+

0 commit comments

Comments
 (0)