• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tonegas / nnodely / 16502811447

24 Jul 2025 04:44PM UTC coverage: 97.767% (+0.1%) from 97.651%
16502811447

push

github

web-flow
New version 1.5.0

This pull request introduces version 1.5.0 of **nnodely**, featuring several updates:
1. Improved clarity of documentation and examples.
2. Support for managing multi-dataset features is now available.
3. DataFrames can now be used to create datasets.
4. Datasets can now be resampled.
5. Random data training has been fixed for both classic and recurrent training.
6. The `state` variable has been removed.
7. It is now possible to add or remove a connection or a closed loop.
8. Partial models can now be exported.
9. The `train` function and the result analysis have been separated.
10. A new function, `trainAndAnalyse`, is now available.
11. The report now works across all network types.
12. The training function code has been reorganized.

2901 of 2967 new or added lines in 53 files covered. (97.78%)

16 existing lines in 6 files now uncovered.

12652 of 12941 relevant lines covered (97.77%)

0.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.67
/nnodely/visualizer/textvisualizer.py
1
import numpy as np
1✔
2
from pprint import pformat
1✔
3

4
from nnodely.visualizer.emptyvisualizer import EmptyVisualizer, color, GREEN, RED, BLUE
1✔
5

6
class TextVisualizer(EmptyVisualizer):
1✔
7
    def __init__(self, verbose=1):
1✔
8
        self.verbose = verbose
1✔
9

10
    def __title(self,msg, lenght = 80):
1✔
11
        print(color((msg).center(lenght, '='), GREEN, True))
1✔
12

13
    def __subtitle(self,msg, lenght = 80):
1✔
14
        print(color((msg).center(lenght, '-'), GREEN, True))
×
15

16
    def __line(self):
1✔
17
        print(color('='.center(80, '='),GREEN))
1✔
18

19
    def __singleline(self):
1✔
20
        print(color('-'.center(80, '-'),GREEN))
×
21

22
    def __info(self,name, dim =30):
1✔
23
        print(color((name).ljust(dim),BLUE))
1✔
24

25
    def __paramjson(self,name, value, dim =30):
1✔
26
        lines = pformat(value, width=80 - dim).strip().splitlines()
1✔
27
        vai = ('\n' + (' ' * dim)).join(x for x in lines)
1✔
28
        # pformat(value).strip().splitlines().rjust(40)
29
        print(color((name).ljust(dim) + vai,GREEN))
1✔
30

31
    def __param(self,name, value, dim =30):
1✔
32
        print(color((name).ljust(dim) + value,GREEN))
1✔
33

34
    def showModel(self, model):
1✔
35
        if self.verbose >= 1:
1✔
36
            self.__title(" nnodely Model ")
1✔
37
            print(color(pformat(model),GREEN))
1✔
38
            self.__line()
1✔
39

40
    def showMinimize(self,variable_name):
1✔
41
        if self.verbose >= 2:
1✔
42
            self.__title(f" Minimize Error of {variable_name} between"
1✔
43
                         f" {self.modely._model_def['Minimizers'][variable_name]['A']} and"
44
                         f" {self.modely._model_def['Minimizers'][variable_name]['B']} with {self.modely._model_def['Minimizers'][variable_name]['loss']} ")
45
            self.__line()
1✔
46

47
    def showModelInputWindow(self):
1✔
48
        if self.verbose >= 2:
1✔
49
            input_ns_backward = {key: value['ns'][0] for key, value in self.modely._model_def['Inputs'].items()}
1✔
50
            input_ns_forward = {key: value['ns'][1] for key, value in self.modely._model_def['Inputs'].items()}
1✔
51
            self.__title(" nnodely Model Input Windows ")
1✔
52
            #self.__paramjson("time_window_backward:",self.modely.input_tw_backward)
53
            #self.__paramjson("time_window_forward:",self.modely.input_tw_forward)
54
            self.__paramjson("sample_window_backward:", input_ns_backward)
1✔
55
            self.__paramjson("sample_window_forward:", input_ns_forward)
1✔
56
            self.__paramjson("input_n_samples:", self.modely._input_n_samples)
1✔
57
            self.__param("max_samples [backw, forw]:", f"[{self.modely._model_def['Info']['ns'][0]},{self.modely._model_def['Info']['ns'][1]}]")
1✔
58
            self.__param("max_samples total:",f"{self.modely._max_n_samples}")
1✔
59
            self.__line()
1✔
60

61
    def showModelRelationSamples(self):
1✔
62
        if self.verbose >= 2:
×
63
            self.__title(" nnodely Model Relation Samples ")
×
64
            self.__paramjson("Relation_samples:", self.modely.relation_samples)
×
65
            self.__line()
×
66

67
    def showBuiltModel(self):
1✔
68
        if self.verbose >= 2:
1✔
69
            self.__title(" nnodely Built Model ")
1✔
70
            print(color(pformat(self.modely._model),GREEN))
1✔
71
            self.__line()
1✔
72

73
    def showWeights(self, weights = None):
1✔
74
        self.__title(" nnodely Models Weights ")
1✔
75
        for key, param in self.modely.parameters.items():
1✔
76
            if weights is None or key in weights:
1✔
77
                self.__paramjson(key,param)
1✔
78
        self.__line()
1✔
79

80
    def showWeightsInTrain(self, batch = None, epoch = None, weights = None):
1✔
81
        if self.verbose >= 2:
1✔
82
            par = self.modely.running_parameters
1✔
83
            dim = len(self.modely._model_def['Minimizers'])
1✔
84
            COLOR = BLUE
1✔
85
            if epoch is not None:
1✔
86
                print(color('|' + (f"{epoch + 1}/{par['num_of_epochs']}").center(10, ' ') + '|',COLOR), end='')
1✔
87
                print(color((f' Params end epochs {epoch + 1} ').center(20 * (dim + 1) - 1, '-') + '|',COLOR))
1✔
88

89
            if batch is not None:
1✔
90
                print(color('|' + (f"{batch + 1}").center(10, ' ') + '|', COLOR), end='')
1✔
91
                print(color((f' Params end batch {batch + 1} ').center(20 * (dim + 1) - 1, '-') + '|', COLOR))
1✔
92

93
            for key, param in self.modely.parameters.items():
1✔
94
                if weights is None or key in weights:
1✔
95
                    print(color('|' + (f"{key}").center(10, ' ') + '|', COLOR), end='')
1✔
96
                    print(color((f'{param}').center(20 * (dim + 1) - 1, ' ') + '|', COLOR))
1✔
97

98
            if epoch is not None:
1✔
99
                print(color('|'+(f'').center(10+20*(dim+1), '-') + '|'))
1✔
100

101
    def showDataset(self, name):
1✔
102
        if self.verbose >= 1:
1✔
103
            self.__title(" nnodely Model Dataset ")
1✔
104
            self.__param("Dataset Name:", name)
1✔
105
            self.__param("Number of files:", f'{self.modely._file_count}')
1✔
106
            self.__param("Total number of samples:", f'{self.modely._num_of_samples[name]}')
1✔
107
            for key in self.modely._model_def['Inputs'].keys():
1✔
108
                if key in self.modely._data[name].keys():
1✔
109
                    self.__param(f"Shape of {key}:", f'{self.modely._data[name][key].shape}')
1✔
110
            self.__line()
1✔
111

112
    def showStartTraining(self):
1✔
113
        if self.verbose >= 1:
1✔
114
            par = self.modely.running_parameters
1✔
115
            dim = len(self.modely._model_def['Minimizers'])
1✔
116
            self.__title(" nnodely Training ", 12+(len(self.modely._model_def['Minimizers'])+1)*20)
1✔
117
            print(color('|'+(f'Epoch').center(10,' ')+'|'),end='')
1✔
118
            for key in self.modely._model_def['Minimizers'].keys():
1✔
119
                print(color((f'{key}').center(19, ' ') + '|'), end='')
1✔
120
            print(color((f'Total').center(19, ' ') + '|'))
1✔
121

122
            print(color('|' + (f' ').center(10, ' ') + '|'), end='')
1✔
123
            for key in self.modely._model_def['Minimizers'].keys():
1✔
124
                print(color((f'Loss').center(19, ' ') + '|'),end='')
1✔
125
            print(color((f'Loss').center(19, ' ') + '|'))
1✔
126

127
            print(color('|' + (f' ').center(10, ' ') + '|'), end='')
1✔
128
            for key in self.modely._model_def['Minimizers'].keys():
1✔
129
                if par['n_samples_val']:
1✔
130
                    print(color((f'train').center(9, ' ') + '|'),end='')
1✔
131
                    print(color((f'val').center(9, ' ') + '|'),end='')
1✔
132
                else:
133
                    print(color((f'train').center(19, ' ') + '|'), end='')
1✔
134
            if par['n_samples_val']:
1✔
135
                print(color((f'train').center(9, ' ') + '|'), end='')
1✔
136
                print(color((f'val').center(9, ' ') + '|'))
1✔
137
            else:
138
                print(color((f'train').center(19, ' ') + '|'))
1✔
139

140
            print(color('|'+(f'').center(10+20*(dim+1), '-') + '|'))
1✔
141

142
    def showTraining(self, epoch, train_losses, val_losses):
1✔
143
        if self.verbose >= 1:
1✔
144
            eng = lambda val: np.format_float_scientific(val, precision=3)
1✔
145
            par = self.modely.running_parameters
1✔
146
            show_epoch = 1 if par['num_of_epochs'] <= 20 else 10
1✔
147
            dim = len(self.modely._model_def['Minimizers'])
1✔
148
            if epoch < par['num_of_epochs']:
1✔
149
                print('', end='\r')
1✔
150
                print('|' + (f"{epoch + 1}/{par['num_of_epochs']}").center(10, ' ') + '|', end='')
1✔
151
                train_loss = []
1✔
152
                val_loss = []
1✔
153
                for key in self.modely._model_def['Minimizers'].keys():
1✔
154
                    train_loss.append(train_losses[key][epoch])
1✔
155
                    if val_losses:
1✔
156
                        val_loss.append(val_losses[key][epoch])
1✔
157
                        print((f'{eng(train_losses[key][epoch])}').center(9, ' ') + '|', end='')
1✔
158
                        print((f'{eng(val_losses[key][epoch])}').center(9, ' ') + '|', end='')
1✔
159
                    else:
160
                        print((f'{eng(train_losses[key][epoch])}').center(19, ' ') + '|', end='')
1✔
161

162
                if val_losses:
1✔
163
                    print((f'{eng(np.mean(train_loss))}').center(9, ' ') + '|', end='')
1✔
164
                    print((f'{eng(np.mean(val_loss))}').center(9, ' ') + '|', end='')
1✔
165
                else:
166
                    print((f'{eng(np.mean(train_loss))}').center(19, ' ') + '|', end='')
1✔
167

168
                if (epoch + 1) % show_epoch == 0:
1✔
169
                    print('', end='\r')
1✔
170
                    print(color('|' + (f"{epoch + 1}/{par['num_of_epochs']}").center(10, ' ') + '|'), end='')
1✔
171
                    for key in self.modely._model_def['Minimizers'].keys():
1✔
172
                        if val_losses:
1✔
173
                            print(color((f'{eng(train_losses[key][epoch])}').center(9, ' ') + '|'), end='')
1✔
174
                            print(color((f'{eng(val_losses[key][epoch])}').center(9, ' ') + '|'), end='')
1✔
175
                        else:
176
                            print(color((f'{eng(train_losses[key][epoch])}').center(19, ' ') + '|'), end='')
1✔
177

178
                    if val_losses:
1✔
179
                        print(color((f'{eng(np.mean(train_loss))}').center(9, ' ') + '|'), end='')
1✔
180
                        print(color((f'{eng(np.mean(val_loss))}').center(9, ' ') + '|'))
1✔
181
                    else:
182
                        print(color((f'{eng(np.mean(train_loss))}').center(19, ' ') + '|'))
1✔
183

184
            if epoch+1 == par['num_of_epochs']:
1✔
185
                print(color('|'+(f'').center(10+20*(dim+1), '-') + '|'))
1✔
186

187
    def showTrainingTime(self, time):
1✔
188
        if self.verbose >= 1:
1✔
189
            self.__title(" nnodely Training Time ")
1✔
190
            self.__param("Total time of Training:", f'{time}')
1✔
191
            self.__line()
1✔
192

193
    def showTrainParams(self):
1✔
194
        if self.verbose >= 1:
1✔
195
            self.__title(" nnodely Model Train Parameters ")
1✔
196
            par = self.modely.get_training_info()
1✔
197

198
            self.__paramjson("models:", par['models'])
1✔
199
            self.__param("num of epochs:", str(par['num_of_epochs']))
1✔
200
            self.__param("update per epochs:", str(par['update_per_epochs']))
1✔
201
            if par['prediction_samples'] >= 0:
1✔
202
                self.__info("└>len(train_indexes)//(batch_size+step)")
1✔
203
            else:
204
                self.__info("└>(n_samples-batch_size)/batch_size+1")
1✔
205

206
            if par['shuffle_data']:
1✔
207
                self.__param('shuffle data:', str(par['shuffle_data']))
1✔
208

209
            if 'early_stopping' in par and  par['early_stopping']:
1✔
210
                self.__param('early stopping:', par['early_stopping'])
×
211
                self.__paramjson('early stopping params:', par['early_stopping_params'])
×
212

213
            if par['prediction_samples'] >= 0:
1✔
214
                self.__param("prediction samples:", f"{par['prediction_samples']}")
1✔
215
                self.__param("step:", f"{par['train_step']}")
1✔
216
                self.__paramjson("closed loop:", par['closed_loop'])
1✔
217
                self.__paramjson("connect:", par['connect'])
1✔
218

219
            self.__param("train dataset:", f"{par['train_tag']}")
1✔
220
            self.__param("\t- batch size:", f"{par['train_batch_size']}")
1✔
221
            self.__param("\t- num of samples:", f"{par['n_samples_train']}")
1✔
222
            if par['prediction_samples'] >= 0:
1✔
223
                self.__param("\t- num of first samples:", f"{par['n_first_samples_train']}")
1✔
224

225
            if par['n_samples_val'] > 0:
1✔
226
                self.__param("validation dataset:", f"{par['val_tag']}")
1✔
227
                self.__param("\t- batch size:", f"{par['val_batch_size']}")
1✔
228
                self.__param("\t- num of samples:", f"{par['n_samples_val']}")
1✔
229
                if par['prediction_samples'] >= 0:
1✔
NEW
230
                    self.__param("\t- num of first samples:", f"{par['n_first_samples_val']}")
×
231

232
            if par['n_samples_test'] > 0:
1✔
233
                self.__param("test dataset:", f"{par['test_tag']}")
1✔
234
                self.__param("\t- num of samples:", f"{par['n_samples_test']}")
1✔
235
                if 'test_batch_size' in par:
1✔
NEW
236
                    self.__param("\t- batch size:", f"{par['test_batch_size']}")
×
237
                if par['prediction_samples'] >= 0:
1✔
NEW
238
                    self.__param("\t- num of first samples:", f"{par['n_first_samples_test']}")
×
239

240
            self.__paramjson('minimizers:', par['minimizers'])
1✔
241

242
            self.__param("optimizer:", par['optimizer'])
1✔
243
            self.__paramjson("optimizer defaults:", par['optimizer_defaults'])
1✔
244
            if par['optimizer_params'] is not None:
1✔
245
                self.__paramjson("optimizer params:", par['optimizer_params'])
1✔
246

247
            self.__line()
1✔
248

249
    def showResult(self, name_data):
1✔
250
        eng = lambda val: np.format_float_scientific(val, precision=3)
1✔
251
        if self.verbose >= 1:
1✔
252
            dim_loss = len(max(self.modely._model_def['Minimizers'].keys(),key=len))
1✔
253
            loss_type_list = set([value["loss"] for ind, (key, value) in enumerate(self.modely._model_def['Minimizers'].items())])
1✔
254
            self.__title(f" nnodely Model Results for {name_data} ", dim_loss + 2 + (len(loss_type_list) + 2) * 20)
1✔
255
            print(color('|' + (f'Loss').center(dim_loss, ' ') + '|'), end='')
1✔
256
            for loss in loss_type_list:
1✔
257
                print(color((f'{loss}').center(19, ' ') + '|'), end='')
1✔
258
            print(color((f'FVU').center(19, ' ') + '|'), end='')
1✔
259
            print(color((f'AIC').center(19, ' ') + '|'))
1✔
260

261
            print(color('|' + (f'').center(dim_loss, ' ') + '|'), end='')
1✔
262
            for i in range(len(loss_type_list)):
1✔
263
                print(color((f'small better').center(19, ' ') + '|'), end='')
1✔
264
            print(color((f'small better').center(19, ' ') + '|'), end='')
1✔
265
            print(color((f'lower better').center(19, ' ') + '|'))
1✔
266

267
            print(color('|' + (f'').center(dim_loss + 20 * (len(loss_type_list) + 2), '-') + '|'))
1✔
268
            for ind, (key, value) in enumerate(self.modely._model_def['Minimizers'].items()):
1✔
269
                print(color('|'+(f'{key}').center(dim_loss, ' ') + '|'), end='')
1✔
270
                for loss in list(loss_type_list):
1✔
271
                    if value["loss"] == loss:
1✔
272
                        print(color((f'{eng(self.modely.performance[name_data][key][value["loss"]])}').center(19, ' ') + '|'), end='')
1✔
273
                    else:
274
                        print(color((f' ').center(19, ' ') + '|'), end='')
1✔
275
                print(color((f'{eng(self.modely.performance[name_data][key]["fvu"]["total"])}').center(19, ' ') + '|'), end='')
1✔
276
                print(color((f'{eng(self.modely.performance[name_data][key]["aic"]["value"])}').center(19, ' ') + '|'))
1✔
277

278
            print(color('|' + (f'').center(dim_loss + 20 * (len(loss_type_list) + 2), '-') + '|'))
1✔
279
            print(color('|'+(f'Total').center(dim_loss, ' ') + '|'), end='')
1✔
280
            print(color((f'{eng(self.modely.performance[name_data]["total"]["mean_error"])}').center(len(loss_type_list)*20-1, ' ') + '|'), end='')
1✔
281
            print(color((f'{eng(self.modely.performance[name_data]["total"]["fvu"])}').center(19, ' ') + '|'), end='')
1✔
282
            print(color((f'{eng(self.modely.performance[name_data]["total"]["aic"])}').center(19, ' ') + '|'))
1✔
283

284
            print(color('|' + (f'').center(dim_loss + 20 * (len(loss_type_list) + 2), '-') + '|'))
1✔
285

286
        if self.verbose >= 2:
1✔
287
            self.__title(" Detalied Results ")
1✔
288
            print(color(pformat(self.modely.performance), GREEN))
1✔
289
            self.__line()
1✔
290

291
    def saveModel(self, name, path):
1✔
292
        if self.verbose >= 1:
1✔
293
            self.__title(f" Save {name} ")
1✔
294
            self.__param("Model saved in:", path)
1✔
295
            self.__line()
1✔
296

297
    def loadModel(self, name, path):
1✔
298
        if self.verbose >= 1:
1✔
299
            self.__title(f" Load {name} ")
1✔
300
            self.__param("Model loaded from:", path)
1✔
301
            self.__line()
1✔
302

303
    def exportModel(self, name, path):
1✔
304
        if self.verbose >= 1:
1✔
305
            self.__title(f" Export {name} ")
1✔
306
            self.__param("Model exported in:", path)
1✔
307
            self.__line()
1✔
308

309
    def importModel(self, name, path):
1✔
310
        if self.verbose >= 1:
1✔
311
            self.__title(f" Import {name} ")
1✔
312
            self.__param("Model imported from:", path)
1✔
313
            self.__line()
1✔
314

315
    def exportReport(self, name, path):
1✔
316
        if self.verbose >= 1:
1✔
317
            self.__title(f" Export {name} Report ")
1✔
318
            self.__param("Report exported in:", path)
1✔
319
            self.__line()
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc