MEDfl 0.1.25__py3-none-any.whl → 0.1.27__py3-none-any.whl

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 (52) hide show
  1. MEDfl/LearningManager/__init__.py +13 -0
  2. MEDfl/LearningManager/client.py +150 -0
  3. MEDfl/LearningManager/dynamicModal.py +287 -0
  4. MEDfl/LearningManager/federated_dataset.py +60 -0
  5. MEDfl/LearningManager/flpipeline.py +192 -0
  6. MEDfl/LearningManager/model.py +223 -0
  7. MEDfl/LearningManager/params.yaml +14 -0
  8. MEDfl/LearningManager/params_optimiser.py +442 -0
  9. MEDfl/LearningManager/plot.py +229 -0
  10. MEDfl/LearningManager/server.py +181 -0
  11. MEDfl/LearningManager/strategy.py +82 -0
  12. MEDfl/LearningManager/utils.py +308 -0
  13. MEDfl/NetManager/__init__.py +9 -0
  14. MEDfl/NetManager/database_connector.py +48 -0
  15. MEDfl/NetManager/dataset.py +92 -0
  16. MEDfl/NetManager/flsetup.py +320 -0
  17. MEDfl/NetManager/net_helper.py +248 -0
  18. MEDfl/NetManager/net_manager_queries.py +137 -0
  19. MEDfl/NetManager/network.py +174 -0
  20. MEDfl/NetManager/node.py +178 -0
  21. MEDfl/__init__.py +2 -0
  22. {MEDfl-0.1.25.data → MEDfl-0.1.27.data}/scripts/setup_mysql.sh +22 -22
  23. {MEDfl-0.1.25.dist-info → MEDfl-0.1.27.dist-info}/METADATA +127 -127
  24. MEDfl-0.1.27.dist-info/RECORD +53 -0
  25. {MEDfl-0.1.25.dist-info → MEDfl-0.1.27.dist-info}/WHEEL +1 -1
  26. {MEDfl-0.1.25.dist-info → MEDfl-0.1.27.dist-info}/top_level.txt +1 -1
  27. Medfl/LearningManager/__init__.py +13 -13
  28. Medfl/LearningManager/client.py +150 -150
  29. Medfl/LearningManager/dynamicModal.py +287 -287
  30. Medfl/LearningManager/federated_dataset.py +60 -60
  31. Medfl/LearningManager/flpipeline.py +192 -192
  32. Medfl/LearningManager/model.py +223 -223
  33. Medfl/LearningManager/params.yaml +14 -14
  34. Medfl/LearningManager/params_optimiser.py +442 -442
  35. Medfl/LearningManager/plot.py +229 -229
  36. Medfl/LearningManager/server.py +181 -181
  37. Medfl/LearningManager/strategy.py +82 -82
  38. Medfl/LearningManager/utils.py +308 -308
  39. Medfl/NetManager/__init__.py +9 -9
  40. Medfl/NetManager/database_connector.py +48 -48
  41. Medfl/NetManager/dataset.py +92 -92
  42. Medfl/NetManager/flsetup.py +320 -320
  43. Medfl/NetManager/net_helper.py +248 -248
  44. Medfl/NetManager/net_manager_queries.py +137 -137
  45. Medfl/NetManager/network.py +174 -174
  46. Medfl/NetManager/node.py +178 -178
  47. Medfl/__init__.py +1 -1
  48. alembic/env.py +61 -61
  49. scripts/base.py +29 -29
  50. scripts/config.ini +5 -5
  51. scripts/create_db.py +133 -133
  52. MEDfl-0.1.25.dist-info/RECORD +0 -32
Medfl/NetManager/node.py CHANGED
@@ -1,178 +1,178 @@
1
- import pandas as pd
2
-
3
- from .net_helper import *
4
- from .net_manager_queries import *
5
- from Medfl.LearningManager.utils import params
6
- from Medfl.NetManager.database_connector import DatabaseManager
7
-
8
- class Node:
9
- """
10
- A class representing a node in the network.
11
-
12
- Attributes:
13
- name (str): The name of the node.
14
- train (int): An integer flag representing whether the node is used for training (1) or testing (0).
15
- test_fraction (float, optional): The fraction of data used for testing when train=1. Default is 0.2.
16
- """
17
-
18
- def __init__(
19
- self, name: str, train: int, test_fraction: float = 0.2, engine=None
20
- ):
21
- """
22
- Initialize a Node instance.
23
-
24
- Parameters:
25
- name (str): The name of the node.
26
- train (int): An integer flag representing whether the node is used for training (1) or testing (0).
27
- test_fraction (float, optional): The fraction of data used for testing when train=1. Default is 0.2.
28
- """
29
- self.name = name
30
- self.train = train
31
- self.test_fraction = 1.0 if self.train == 0 else test_fraction
32
-
33
-
34
- db_manager = DatabaseManager() ;
35
- db_manager.connect() ;
36
- self.engine = db_manager.get_connection()
37
-
38
- def validate(self):
39
- """Validate name, train, test_fraction"""
40
- if not isinstance(self.name, str):
41
- raise TypeError("name argument must be a string")
42
-
43
- if not isinstance(self.train, int):
44
- raise TypeError("train argument must be an int")
45
-
46
- if not isinstance(self.test_fraction, float):
47
- raise TypeError("test_fraction argument must be a float")
48
-
49
- def create_node(self, NetId: int):
50
- """Create a node in the database.
51
- Parameters:
52
- NetId (int): The ID of the network to which the node belongs.
53
-
54
- Returns:
55
- None
56
- """
57
- self.engine.execute(
58
- text(INSERT_NODE_QUERY.format(self.name, NetId, self.train))
59
- )
60
-
61
- def delete_node(self):
62
- """Delete the node from the database."""
63
- self.engine.execute(text(DELETE_NODE_QUERY.format(self.name)))
64
-
65
- def check_dataset_compatibility(self, data_df):
66
- """Check if the dataset is compatible with the master dataset.
67
- Parameters:
68
- data_df (DataFrame): The dataset to check.
69
-
70
- Returns:
71
- None
72
- """
73
- if master_table_exists() != 1:
74
- print("MasterDataset doesn't exist")
75
- else:
76
- columns = data_df.columns.tolist()
77
-
78
- # get master_dataset columns
79
- result_proxy = self.engine.execute(SELECT_MASTER_COLUMNS_QUERY)
80
- master_table_columns = result_proxy.keys()
81
-
82
-
83
- assert [x == y for x, y in zip(master_table_columns, columns)]
84
-
85
- def update_node(self):
86
- """Update the node information (not implemented)."""
87
- pass
88
-
89
- def get_dataset(self, column_name: str = None):
90
- """Get the dataset for the node based on the given column name.
91
- Parameters:
92
- column_name (str, optional): The column name to filter the dataset. Default is None.
93
-
94
- Returns:
95
- DataFrame: The dataset associated with the node.
96
- """
97
- NodeId = get_nodeid_from_name(self.name)
98
- if column_name is not None:
99
- query = text(SELECT_DATASET_BY_COLUMN_QUERY.format(column_name, self.name))
100
- else:
101
- query = text(SELECT_DATASET_BY_NODE_ID_QUERY.format(NodeId))
102
-
103
- result_proxy = self.engine.execute(query)
104
- node_dataset = pd.DataFrame(result_proxy.fetchall(), columns=result_proxy.keys())
105
-
106
- return node_dataset
107
-
108
- def upload_dataset(self, dataset_name: str, path_to_csv: str = params['path_to_test_csv']):
109
- """Upload the dataset to the database for the node.
110
- Parameters:
111
- dataset_name (str): The name of the dataset.
112
- path_to_csv (str, optional): Path to the CSV file containing the dataset. Default is the path in params.
113
-
114
- Returns:
115
- None
116
- """
117
- data_df = pd.read_csv(path_to_csv)
118
-
119
- nodeId = get_nodeid_from_name(self.name)
120
- columns = data_df.columns.tolist()
121
- self.check_dataset_compatibility(data_df)
122
-
123
- data_df = process_eicu(data_df)
124
- for index, row in data_df.iterrows():
125
- query_1 = "INSERT INTO DataSets(DataSetName,nodeId," + "".join(
126
- f"{x}," for x in columns
127
- )
128
- query_2 = f" VALUES ('{dataset_name}',{nodeId}, " + "".join(
129
- f"{is_str(data_df, row, x)}," for x in columns
130
- )
131
- query = query_1[:-1] + ")" + query_2[:-1] + ")"
132
- self.engine.execute(text(query))
133
-
134
- def assign_dataset(self, dataset_name:str):
135
- """Assigning existing dataSet to node
136
- Parameters:
137
- dataset_name (str): The name of the dataset to assign.
138
-
139
- Returns:
140
- None
141
- """
142
-
143
- nodeId = get_nodeid_from_name(self.name)
144
- query = f"UPDATE DataSets SET nodeId = {nodeId} WHERE DataSetName = '{dataset_name}'"
145
- self.engine.execute(text(query))
146
-
147
- def unassign_dataset(self, dataset_name:str):
148
- """unssigning existing dataSet to node
149
- Parameters:
150
- dataset_name (str): The name of the dataset to assign.
151
-
152
- Returns:
153
- None
154
- """
155
-
156
- query = f"UPDATE DataSets SET nodeId = {-1} WHERE DataSetName = '{dataset_name}'"
157
- self.engine.execute(text(query))
158
-
159
- def list_alldatasets(self):
160
- """List all datasets associated with the node.
161
- Returns:
162
- DataFrame: A DataFrame containing information about all datasets associated with the node.
163
-
164
- """
165
- return pd.read_sql(
166
- text(SELECT_ALL_DATASETS_QUERY.format(self.name)), my_eng
167
- )
168
-
169
- @staticmethod
170
- def list_allnodes():
171
- """List all nodes in the database.
172
- Returns:
173
- DataFrame: A DataFrame containing information about all nodes in the database.
174
-
175
- """
176
- query = text(SELECT_ALL_NODES_QUERY)
177
- res = pd.read_sql(query, my_eng)
178
- return res
1
+ import pandas as pd
2
+
3
+ from .net_helper import *
4
+ from .net_manager_queries import *
5
+ from MEDfl.LearningManager.utils import params
6
+ from MEDfl.NetManager.database_connector import DatabaseManager
7
+
8
+ class Node:
9
+ """
10
+ A class representing a node in the network.
11
+
12
+ Attributes:
13
+ name (str): The name of the node.
14
+ train (int): An integer flag representing whether the node is used for training (1) or testing (0).
15
+ test_fraction (float, optional): The fraction of data used for testing when train=1. Default is 0.2.
16
+ """
17
+
18
+ def __init__(
19
+ self, name: str, train: int, test_fraction: float = 0.2, engine=None
20
+ ):
21
+ """
22
+ Initialize a Node instance.
23
+
24
+ Parameters:
25
+ name (str): The name of the node.
26
+ train (int): An integer flag representing whether the node is used for training (1) or testing (0).
27
+ test_fraction (float, optional): The fraction of data used for testing when train=1. Default is 0.2.
28
+ """
29
+ self.name = name
30
+ self.train = train
31
+ self.test_fraction = 1.0 if self.train == 0 else test_fraction
32
+
33
+
34
+ db_manager = DatabaseManager() ;
35
+ db_manager.connect() ;
36
+ self.engine = db_manager.get_connection()
37
+
38
+ def validate(self):
39
+ """Validate name, train, test_fraction"""
40
+ if not isinstance(self.name, str):
41
+ raise TypeError("name argument must be a string")
42
+
43
+ if not isinstance(self.train, int):
44
+ raise TypeError("train argument must be an int")
45
+
46
+ if not isinstance(self.test_fraction, float):
47
+ raise TypeError("test_fraction argument must be a float")
48
+
49
+ def create_node(self, NetId: int):
50
+ """Create a node in the database.
51
+ Parameters:
52
+ NetId (int): The ID of the network to which the node belongs.
53
+
54
+ Returns:
55
+ None
56
+ """
57
+ self.engine.execute(
58
+ text(INSERT_NODE_QUERY.format(self.name, NetId, self.train))
59
+ )
60
+
61
+ def delete_node(self):
62
+ """Delete the node from the database."""
63
+ self.engine.execute(text(DELETE_NODE_QUERY.format(self.name)))
64
+
65
+ def check_dataset_compatibility(self, data_df):
66
+ """Check if the dataset is compatible with the master dataset.
67
+ Parameters:
68
+ data_df (DataFrame): The dataset to check.
69
+
70
+ Returns:
71
+ None
72
+ """
73
+ if master_table_exists() != 1:
74
+ print("MasterDataset doesn't exist")
75
+ else:
76
+ columns = data_df.columns.tolist()
77
+
78
+ # get master_dataset columns
79
+ result_proxy = self.engine.execute(SELECT_MASTER_COLUMNS_QUERY)
80
+ master_table_columns = result_proxy.keys()
81
+
82
+
83
+ assert [x == y for x, y in zip(master_table_columns, columns)]
84
+
85
+ def update_node(self):
86
+ """Update the node information (not implemented)."""
87
+ pass
88
+
89
+ def get_dataset(self, column_name: str = None):
90
+ """Get the dataset for the node based on the given column name.
91
+ Parameters:
92
+ column_name (str, optional): The column name to filter the dataset. Default is None.
93
+
94
+ Returns:
95
+ DataFrame: The dataset associated with the node.
96
+ """
97
+ NodeId = get_nodeid_from_name(self.name)
98
+ if column_name is not None:
99
+ query = text(SELECT_DATASET_BY_COLUMN_QUERY.format(column_name, self.name))
100
+ else:
101
+ query = text(SELECT_DATASET_BY_NODE_ID_QUERY.format(NodeId))
102
+
103
+ result_proxy = self.engine.execute(query)
104
+ node_dataset = pd.DataFrame(result_proxy.fetchall(), columns=result_proxy.keys())
105
+
106
+ return node_dataset
107
+
108
+ def upload_dataset(self, dataset_name: str, path_to_csv: str = params['path_to_test_csv']):
109
+ """Upload the dataset to the database for the node.
110
+ Parameters:
111
+ dataset_name (str): The name of the dataset.
112
+ path_to_csv (str, optional): Path to the CSV file containing the dataset. Default is the path in params.
113
+
114
+ Returns:
115
+ None
116
+ """
117
+ data_df = pd.read_csv(path_to_csv)
118
+
119
+ nodeId = get_nodeid_from_name(self.name)
120
+ columns = data_df.columns.tolist()
121
+ self.check_dataset_compatibility(data_df)
122
+
123
+ data_df = process_eicu(data_df)
124
+ for index, row in data_df.iterrows():
125
+ query_1 = "INSERT INTO DataSets(DataSetName,nodeId," + "".join(
126
+ f"{x}," for x in columns
127
+ )
128
+ query_2 = f" VALUES ('{dataset_name}',{nodeId}, " + "".join(
129
+ f"{is_str(data_df, row, x)}," for x in columns
130
+ )
131
+ query = query_1[:-1] + ")" + query_2[:-1] + ")"
132
+ self.engine.execute(text(query))
133
+
134
+ def assign_dataset(self, dataset_name:str):
135
+ """Assigning existing dataSet to node
136
+ Parameters:
137
+ dataset_name (str): The name of the dataset to assign.
138
+
139
+ Returns:
140
+ None
141
+ """
142
+
143
+ nodeId = get_nodeid_from_name(self.name)
144
+ query = f"UPDATE DataSets SET nodeId = {nodeId} WHERE DataSetName = '{dataset_name}'"
145
+ self.engine.execute(text(query))
146
+
147
+ def unassign_dataset(self, dataset_name:str):
148
+ """unssigning existing dataSet to node
149
+ Parameters:
150
+ dataset_name (str): The name of the dataset to assign.
151
+
152
+ Returns:
153
+ None
154
+ """
155
+
156
+ query = f"UPDATE DataSets SET nodeId = {-1} WHERE DataSetName = '{dataset_name}'"
157
+ self.engine.execute(text(query))
158
+
159
+ def list_alldatasets(self):
160
+ """List all datasets associated with the node.
161
+ Returns:
162
+ DataFrame: A DataFrame containing information about all datasets associated with the node.
163
+
164
+ """
165
+ return pd.read_sql(
166
+ text(SELECT_ALL_DATASETS_QUERY.format(self.name)), my_eng
167
+ )
168
+
169
+ @staticmethod
170
+ def list_allnodes():
171
+ """List all nodes in the database.
172
+ Returns:
173
+ DataFrame: A DataFrame containing information about all nodes in the database.
174
+
175
+ """
176
+ query = text(SELECT_ALL_NODES_QUERY)
177
+ res = pd.read_sql(query, my_eng)
178
+ return res
Medfl/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
- from .LearningManager import *
1
+ from .LearningManager import *
2
2
  from .NetManager import *
alembic/env.py CHANGED
@@ -1,61 +1,61 @@
1
- from logging.config import fileConfig
2
- import logging
3
- from sqlalchemy import engine_from_config, create_engine
4
- from sqlalchemy import pool
5
- import sys
6
- import os
7
- from alembic import context
8
-
9
- sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
10
- from scripts.base import my_eng
11
-
12
- # this is the Alembic Config object, which provides
13
- # access to the values within the .ini file in use.
14
- config = context.config
15
-
16
- # Interpret the config file for Python logging.
17
- # This line sets up loggers basically.
18
- fileConfig(config.config_file_name)
19
-
20
- # add your model's MetaData object here
21
- # for 'autogenerate' support
22
- # from myapp import mymodel
23
- # target_metadata = mymodel.Base.metadata
24
- target_metadata = None
25
-
26
- # other values from the config, defined by the needs of env.py,
27
- # can be acquired:
28
- # my_important_option = config.get_main_option("my_important_option")
29
- # ... etc.
30
- def configure_logger(name):
31
- # This is the standard logging configuration
32
- logging.config.fileConfig(
33
- 'alembic_logging.ini', # Path to your logging configuration file
34
- defaults={
35
- 'logfilename': 'alembic.log', # Log file name
36
- },
37
- disable_existing_loggers=False,
38
- )
39
-
40
- return logging.getLogger(name)
41
-
42
-
43
-
44
- def run_migrations_offline():
45
- """Run migrations in 'offline' mode."""
46
- pass
47
-
48
- def run_migrations_online():
49
- """Run migrations in 'online' mode."""
50
- pass
51
-
52
- if context.is_offline_mode():
53
- run_migrations_offline()
54
- else:
55
- run_migrations_online()
56
-
57
-
58
- if context.is_offline_mode():
59
- run_migrations_offline()
60
- else:
61
- run_migrations_online()
1
+ from logging.config import fileConfig
2
+ import logging
3
+ from sqlalchemy import engine_from_config, create_engine
4
+ from sqlalchemy import pool
5
+ import sys
6
+ import os
7
+ from alembic import context
8
+
9
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
10
+ from scripts.base import my_eng
11
+
12
+ # this is the Alembic Config object, which provides
13
+ # access to the values within the .ini file in use.
14
+ config = context.config
15
+
16
+ # Interpret the config file for Python logging.
17
+ # This line sets up loggers basically.
18
+ fileConfig(config.config_file_name)
19
+
20
+ # add your model's MetaData object here
21
+ # for 'autogenerate' support
22
+ # from myapp import mymodel
23
+ # target_metadata = mymodel.Base.metadata
24
+ target_metadata = None
25
+
26
+ # other values from the config, defined by the needs of env.py,
27
+ # can be acquired:
28
+ # my_important_option = config.get_main_option("my_important_option")
29
+ # ... etc.
30
+ def configure_logger(name):
31
+ # This is the standard logging configuration
32
+ logging.config.fileConfig(
33
+ 'alembic_logging.ini', # Path to your logging configuration file
34
+ defaults={
35
+ 'logfilename': 'alembic.log', # Log file name
36
+ },
37
+ disable_existing_loggers=False,
38
+ )
39
+
40
+ return logging.getLogger(name)
41
+
42
+
43
+
44
+ def run_migrations_offline():
45
+ """Run migrations in 'offline' mode."""
46
+ pass
47
+
48
+ def run_migrations_online():
49
+ """Run migrations in 'online' mode."""
50
+ pass
51
+
52
+ if context.is_offline_mode():
53
+ run_migrations_offline()
54
+ else:
55
+ run_migrations_online()
56
+
57
+
58
+ if context.is_offline_mode():
59
+ run_migrations_offline()
60
+ else:
61
+ run_migrations_online()
scripts/base.py CHANGED
@@ -1,30 +1,30 @@
1
- import mysql.connector
2
- from sqlalchemy import create_engine, text
3
- from configparser import ConfigParser
4
- import yaml
5
- import pkg_resources
6
- import os
7
-
8
- # Get the directory of the current script
9
- current_directory = os.path.dirname(os.path.abspath(__file__))
10
-
11
- # Load configuration from the config file
12
- config_file_path = os.path.join(current_directory, 'db_config.ini')
13
-
14
- config = ConfigParser()
15
- config.read(config_file_path)
16
- mysql_config = config['mysql']
17
-
18
-
19
-
20
- connection_string = (
21
- f"mysql+mysqlconnector://{mysql_config['user']}:{mysql_config['password']}@"
22
- f"{mysql_config['host']}:{mysql_config['port']}/{mysql_config['database']}"
23
- )
24
-
25
- eng = create_engine(
26
- connection_string,
27
- execution_options={"autocommit": True},
28
- )
29
-
1
+ import mysql.connector
2
+ from sqlalchemy import create_engine, text
3
+ from configparser import ConfigParser
4
+ import yaml
5
+ import pkg_resources
6
+ import os
7
+
8
+ # Get the directory of the current script
9
+ current_directory = os.path.dirname(os.path.abspath(__file__))
10
+
11
+ # Load configuration from the config file
12
+ config_file_path = os.path.join(current_directory, 'db_config.ini')
13
+
14
+ config = ConfigParser()
15
+ config.read(config_file_path)
16
+ mysql_config = config['mysql']
17
+
18
+
19
+
20
+ connection_string = (
21
+ f"mysql+mysqlconnector://{mysql_config['user']}:{mysql_config['password']}@"
22
+ f"{mysql_config['host']}:{mysql_config['port']}/{mysql_config['database']}"
23
+ )
24
+
25
+ eng = create_engine(
26
+ connection_string,
27
+ execution_options={"autocommit": True},
28
+ )
29
+
30
30
  my_eng = eng.connect()
scripts/config.ini CHANGED
@@ -1,6 +1,6 @@
1
- [mysql]
2
- host = localhost
3
- port = 3306
4
- user = root
5
- password =
1
+ [mysql]
2
+ host = localhost
3
+ port = 3306
4
+ user = root
5
+ password =
6
6
  database = MEDfl