PaIRS-UniNa 0.2.4__cp311-cp311-macosx_10_9_universal2.whl → 0.2.6__cp311-cp311-macosx_10_9_universal2.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.

Potentially problematic release.


This version of PaIRS-UniNa might be problematic. Click here for more details.

Files changed (60) hide show
  1. PaIRS_UniNa/Changes.txt +35 -0
  2. PaIRS_UniNa/Custom_Top.py +1 -1
  3. PaIRS_UniNa/Explorer.py +3063 -3049
  4. PaIRS_UniNa/FolderLoop.py +371 -371
  5. PaIRS_UniNa/Input_Tab.py +717 -709
  6. PaIRS_UniNa/Input_Tab_CalVi.py +4 -4
  7. PaIRS_UniNa/Input_Tab_tools.py +3018 -3009
  8. PaIRS_UniNa/Output_Tab.py +2 -2
  9. PaIRS_UniNa/PaIRS.py +17 -17
  10. PaIRS_UniNa/PaIRS_PIV.py +56 -1
  11. PaIRS_UniNa/PaIRS_pypacks.py +323 -60
  12. PaIRS_UniNa/Process_Tab.py +8 -13
  13. PaIRS_UniNa/Process_Tab_Disp.py +9 -4
  14. PaIRS_UniNa/Saving_tools.py +277 -277
  15. PaIRS_UniNa/TabTools.py +63 -21
  16. PaIRS_UniNa/Vis_Tab.py +293 -115
  17. PaIRS_UniNa/Whatsnew.py +13 -0
  18. PaIRS_UniNa/_PaIRS_PIV.so +0 -0
  19. PaIRS_UniNa/__init__.py +3 -3
  20. PaIRS_UniNa/gPaIRS.py +3825 -3600
  21. PaIRS_UniNa/icons/flaticon_PaIRS_download_warning.png +0 -0
  22. PaIRS_UniNa/icons/pylog.png +0 -0
  23. PaIRS_UniNa/icons/python_warning.png +0 -0
  24. PaIRS_UniNa/icons/queue.png +0 -0
  25. PaIRS_UniNa/icons/uninitialized.png +0 -0
  26. PaIRS_UniNa/icons/window.png +0 -0
  27. PaIRS_UniNa/listLib.py +301 -301
  28. PaIRS_UniNa/parForMulti.py +433 -433
  29. PaIRS_UniNa/parForWorkers.py +46 -1
  30. PaIRS_UniNa/pivParFor.py +1 -1
  31. PaIRS_UniNa/procTools.py +17 -7
  32. PaIRS_UniNa/rqrdpckgs.txt +9 -0
  33. PaIRS_UniNa/stereo.py +683 -683
  34. PaIRS_UniNa/stereoPivParFor.py +1 -1
  35. PaIRS_UniNa/tabSplitter.py +606 -606
  36. PaIRS_UniNa/ui_Calibration_Tab.py +542 -542
  37. PaIRS_UniNa/ui_Custom_Top.py +294 -294
  38. PaIRS_UniNa/ui_Input_Tab.py +1098 -1098
  39. PaIRS_UniNa/ui_Input_Tab_CalVi.py +1280 -1280
  40. PaIRS_UniNa/ui_Log_Tab.py +261 -261
  41. PaIRS_UniNa/ui_Output_Tab.py +2360 -2360
  42. PaIRS_UniNa/ui_Process_Tab.py +3808 -3808
  43. PaIRS_UniNa/ui_Process_Tab_CalVi.py +1547 -1547
  44. PaIRS_UniNa/ui_Process_Tab_Disp.py +1139 -968
  45. PaIRS_UniNa/ui_Process_Tab_Min.py +435 -435
  46. PaIRS_UniNa/ui_ResizePopup.py +203 -203
  47. PaIRS_UniNa/ui_Vis_Tab.py +1626 -1533
  48. PaIRS_UniNa/ui_Vis_Tab_CalVi.py +1249 -1249
  49. PaIRS_UniNa/ui_Whatsnew.py +131 -131
  50. PaIRS_UniNa/ui_gPairs.py +873 -849
  51. PaIRS_UniNa/ui_infoPaIRS.py +550 -428
  52. PaIRS_UniNa/whatsnew.txt +4 -4
  53. {PaIRS_UniNa-0.2.4.dist-info → pairs_unina-0.2.6.dist-info}/METADATA +47 -30
  54. {PaIRS_UniNa-0.2.4.dist-info → pairs_unina-0.2.6.dist-info}/RECORD +56 -54
  55. {PaIRS_UniNa-0.2.4.dist-info → pairs_unina-0.2.6.dist-info}/WHEEL +1 -1
  56. PaIRS_UniNa/icons/order.png +0 -0
  57. PaIRS_UniNa/icons/order_reverse.png +0 -0
  58. PaIRS_UniNa/icons/run_piv.png +0 -0
  59. PaIRS_UniNa-0.2.4.dist-info/LICENSE +0 -19
  60. {PaIRS_UniNa-0.2.4.dist-info → pairs_unina-0.2.6.dist-info}/top_level.txt +0 -0
@@ -1,435 +1,435 @@
1
- ''' Parallel for for PIV '''
2
- #import os
3
- import traceback
4
- import queue
5
- import asyncio
6
- #import random
7
- import multiprocessing as mp
8
- from time import sleep, time
1
+ ''' Parallel for for PIV '''
2
+ #import os
3
+ import traceback
4
+ import queue
5
+ import asyncio
6
+ #import random
7
+ import multiprocessing as mp
8
+ from time import sleep, time
9
9
  from .tAVarie import PrintTA, PrintTAPriority
10
10
  from .__init__ import __version__,__year__,__mail__
11
- #import numpy as np
12
- #import scipy as sc
13
-
14
- prTime=PrintTA(PrintTA.blue, PrintTA.faceStd, PrintTAPriority.medium).prTime
15
- pr=PrintTA(PrintTA.blue, PrintTA.faceStd, PrintTAPriority.medium).prTime
16
- # pylint: disable=unused-argument
17
- lock=None
18
- def prLock( *args,**kwargs):
19
- ''' print in parallel pool without overlap (slower)'''
20
- try:
21
- with lock:
22
- PrintTA(PrintTA.blue, PrintTA.faceStd, PrintTAPriority.medium).pr( *args,**kwargs)
23
- except :
24
- print(ParForMul.printExceptionPFM(flagMessage=True))
25
-
26
- def prTimeLock( *args,**kwargs):
27
- ''' print in parallel pool without overlap (slower)'''
28
- try:
29
- with lock:
30
- PrintTA(PrintTA.blue, PrintTA.faceStd, PrintTAPriority.medium).prTime( *args,**kwargs)
31
- except:
32
- print(ParForMul.printExceptionPFM(flagMessage=True))
33
-
34
- def printExceptionMasterParFor(stringa='',flagMessage=False): #timemilliseconds=-1 ***
35
- ''' used to print when an exception is raised TA has decided that the printing function is a simple
36
- print in this way we cannot have any problems when printing in non-compatible terminals
37
- use with something like
38
-
39
- try:
40
- a=1/0
41
- except :#non need to put a variable al the info are in traceback
42
- printException()
43
- * stringa is an additional string (to specify the point where the error comes from)
44
- * flagMessage is a flag, if true the error message is generated; default value is Flag_DEBUG
45
- * flagDispDialog is a flag, if true a critical dialog appears after the exception
46
- '''
47
- #print(f'***** ParForMul Exception ***** Deltat={time()-PrintTA.startTime}\n{traceback.format_exc()}',*args,**kwargs)
48
- #print(sys.exc_info()[2])
49
- Message=""
50
- if flagMessage:
51
- Message+=f'Please, mail to: {__mail__}\n\n'
52
- Message+=f'***** PaIRS Exception ***** time={time()-PrintTA.startTime}\n'+stringa
53
- Message+=f'***** traceback.print_exc() ***** \n'
54
- Message+=traceback.format_exc()
55
- Message+=f'***** traceback.extract_stack() ***** \n'
56
- # to print all the queue comment if not needed
57
- for st in traceback.format_list( traceback.extract_stack()):
58
- if 'PAIRS_GUI' in st and 'printException'not in st:# limits to files that have PAIRS_GUI in the path
59
- Message+=st
60
- Message+=f'***** PaIRS Exception -> End *****'
61
- return Message
62
-
63
-
64
-
65
- def fakePIV(iImg,procId, p, procTime, flagOutput=False, mes="fakePIV"):
66
- ''' fakePIV'''
67
- startTime = time()
68
- #print(f'reading Img {iImg} pid={os.getpid()} pid={mp.current_process().pid}')
69
- #print(f'reading Img {iImg} pid={mp.current_process().pid} procId={procId}')
70
- #sleep(0.5)
71
- #print(f'Finished reading Img {iImg}')
72
-
73
- a=0
74
- count=1*1000*1000#on my pc 10*1000*1000=1sec
75
- nIt=1
76
- while nIt<2000000:
77
- for _ in range(count):
78
- a+=5#random.random()
79
- if time()-startTime>procTime:
80
- break
81
- nIt+=1
82
- if flagOutput:
83
- print(f'fine proc Img {iImg} Nit={nIt} t={time()-startTime} mes={mes}')
84
- return (0,f'fine proc Img {iImg} Nit={nIt} t={time()-startTime} mes={mes}')
85
-
86
- #return iImg
87
-
88
- class ParForCom():
89
- ''' Comunication varibles used by ParFor'''
90
- def __init__(self):
91
- #prTime(0,'Dentro ParForCom Com')
92
- manager=mp.Manager()#si potrebbe creare un lock al posto della variabile globale qui cercare su internet
93
- #prTime(0,'Dentro ParForCom dopo manager')
94
- self.q = manager.Queue()
95
- self.qOut= manager.Queue()
96
- self.qProcessed= manager.Queue()
97
- self.eventExit = manager.Event()
98
-
99
- def clearAll(self):
100
- ''' Clears all the queues'''
101
- self.clear(self.q)
102
- self.clear(self.qOut)
103
- self.clear(self.qProcessed)
104
-
105
-
106
-
107
- def clear(self,q:queue):
108
- '''clears a Queue'''
109
- try:
110
- while True:
111
- q.get_nowait()
112
- except queue.Empty:
113
- pass
114
-
115
-
116
-
117
- class ParForMul():
118
- ''' class Parallel for for PIV '''
119
- printExceptionPFM=printExceptionMasterParFor #class variable
120
- def __init__(self):
121
- #prTime(0,'Dentro ParForMul inizio')
122
- self.parForCom:ParForCom=ParForCom()
123
- # valori impostabili dall'esterno
124
- self.sleepTime=1. # waiting to do things
125
- self.nonProcessed=0 # waiting to do things
126
- #self.numUsedCores =psutil.cpu_count(logical=False)
127
- ## numUsedCores is the number of cores used fo processing and can be different from numCoresParPool that is the number of cores used in the parPool
128
- self.numCoresParPool=self.numUsedCores = mp.cpu_count()//2#da decidere per intel /2 sono i processori reali
129
- #prTime(0,'Dentro ParForMul fine')
130
- self.numCalledCallbacks=0 # identify the times that the callbacks have been called
131
- self.p=None
132
- self.flagError=False
133
- self.exception=None
134
-
135
-
136
- def initTask(self,eventExit,name,procId,*args,**kwargs):
137
- ''' dummy InitTask sample
138
- id is the id of the task should be a numeber between 1 and numUsedCores
139
- if needed initTask should call the main task with name
140
- '''
141
-
142
- (flag,var)=fakePIV(name, procId,('initTask',2), *args,**kwargs)
143
- return (flag,var,('initTask',2))
144
-
145
- def wrapUp(self,procId,flagHasWorked,P,*args,**kwargs):
146
- ''' Dummy wrapUp function '''
147
- if flagHasWorked:#do something
148
- pass
149
- return P
150
-
151
- def callBack(self,flag,perc,procId,flagOutFromTask, name,varOutFromTask):
152
- ''' Dummy callBack function
153
- perc=percentage of processed images
154
- flag=true new data False just check exit
155
- perc= precentage done
156
- flagOutFromTasks,varOutFromTask Out variables from task e.g.:
157
- flagOutFromTasks= 0 success, 1 skipped, -1 error, -2 blocked from caller
158
- varOutFromTask whatever for now string
159
- name current element in names
160
- to stop the process the return value should be True otherwise sleep '''
161
- if not flag:
162
- return False
163
- return False
164
-
165
- def finalTask(self,procId,*args,**kwargs):
166
- ''' dummy final finalTask function
167
- id is the id of the task should be a numeber between 1 and numUsedCores'''
168
- return ('finalTask',2)
169
-
170
- def launchTask(self,procId,task,initTask,finalTask, *args,**kwargs):
171
- ''' the main parallel function first calls initTask (eventExit is an event that enables the safe exit)
172
- then for all the element in the queue q calls task with the variable returned by initTask
173
- finally calls finalTask puts in the queue qOut the final result '''
174
- # aggiunto try così almeno ci rendiamo conto se c'è un errore
175
- '''
176
- try:
177
- procId=mp.current_process()._identity[0]
178
- except:
179
- procId=0 # '''
180
- #pid=mp.current_process().pid
181
- flagHasWorked=False#if true the task has processed at least one element
182
- #if procId==2: prTimeLock(f"launchTask |||||||||||| Inizio procId={procId} flagHasWorked={flagHasWorked} ")
183
- media=None
184
- try:
185
- i,n=self.parForCom.q.get()# the first time task must be called by initTask
186
- if i!=-1:
187
- flagHasWorked=True
188
- (flag,var,P)=initTask(self.parForCom.eventExit,n,procId,*args,**kwargs)
189
- self.parForCom.qProcessed.put((procId,flag,i,var))
190
- while True:
191
- i,n=self.parForCom.q.get()
192
- if i==-1:
193
- break
194
- (flag,var)=task(n,procId,P,*args,**kwargs)
195
- self.parForCom.qProcessed.put((procId,flag,i,var))
196
- media=finalTask(procId,P,*args,**kwargs)# media should be different from None
197
- except Exception as e:
198
- raise(e) # I do not really care to have a full report if in debug it may be important
199
- #ParForMul.printExceptionPFM()
200
- flagHasWorked=False if media is None else flagHasWorked #if true the task has processed at least one element and media should be different from None
201
- return (procId,flagHasWorked,media)
202
-
203
- def readQOutProcess(self,strOutput,flagProcessed,callBack,names,nElements):
204
- ''' reads the qOut queue save the data and calls callback'''
205
- com=self.parForCom
206
- while not com.qProcessed.empty():
207
- (procId,flag,i,var)=com.qProcessed.get_nowait()
208
- perc=1-(com.q.qsize()-self.numUsedCores)/nElements#
209
- strOutput[i]=var
210
- flagProcessed[i]=flag
211
-
212
- #prLock(f'callBack {i} {perc} {com.q.qsize()}')
213
- if callBack(True,perc,procId,flag,names[i],var):
214
- com.eventExit.set()# in this case the process will stop
215
- self.numCalledCallbacks+=1
216
-
217
- def errorHandler(self,error):
218
- ''' error function '''
219
- #self.errorMessage=ParForMul.printExceptionPFM(flagMessage=True)
220
- self.exception=error
221
- self.flagError=True
222
- self.parForCom.eventExit.set()# in this case the process will stop
223
- #raise(error)
224
- def parForExtPool(self,parPool,task,names,*args,initTask=None,finalTask=None,wrapUp=None,callBack=None,**kwargs):
225
- ''' parallel for main function with external mp pool
226
- task is the main function that is called for each value in names.
227
- optionally initTask and finalTask are called only one time per worker
228
- args and kwargs are passed to all the functions.add()
229
- callBack is called frequently and can be used to stop the parFor
230
- Finally the WrapUp function is called one time per worker to wrap things up
231
- '''
232
- #prTime(0,'Dentro parForExtPool')
233
-
234
- com=self.parForCom
235
- com.eventExit.clear()
236
- initTask=self.initTask if initTask is None else initTask
237
- finalTask=self.finalTask if finalTask is None else finalTask
238
- wrapUp=self.wrapUp if wrapUp is None else wrapUp
239
- callBack=self.callBack if callBack is None else callBack
240
- self.flagError=False
241
- self.numCalledCallbacks=0 # reset the number of called callbacks
242
- nElements=len(names)
243
- flagProcessed=[self.nonProcessed]*nElements #lista delle immagini processate inizialmente tutti -1 ma possiamo modificarla
244
- strOutput = [None]*nElements #lista dei messaggi in output in realtà potrebbe essere di qualunque tipo
245
- def callWrapUp(var):
246
- self.p=wrapUp(*var,*args,**kwargs)
247
- self.parForCom.qOut.put((var[0:2])) #procid , flagHasWorked
248
- #prTime(f"callWrapUp fine procid={var[0]} ")
249
-
250
- # per ora -1 non processato, -2 errore ,numero positivo processato
251
- for i,n in enumerate(names):
252
- com.q.put((i,n))
253
- for _ in range(self.numUsedCores):
254
- com.q.put((-1,-1))
255
-
256
- for i in range(self.numUsedCores):
257
- _=parPool.apply_async(self.launchTask,(i,task, initTask,finalTask)+args,kwargs,callback=callWrapUp, error_callback=self.errorHandler)
258
- #_=parPool.apply_async(self.launchTask,(task, initTask,finalTask)+args,kwargs, error_callback=self.errorHandler)
259
- #prTime(0,'Dopo apply async in parForExtPool ++++++++++++++++++++++++++++++++++')
260
- nThreadEnd=0
261
- while True:
262
- try:
263
- #(procId,flagHasWorked)=com.qOut.get_nowait()
264
- (_,_)=com.qOut.get_nowait()
265
- #p=wrapUp(procId,flagHasWorked,p,*args,**kwargs)
266
- nThreadEnd+=1
267
- #if nThreadEnd==1: prTime(f"fine nThreadEnd={nThreadEnd} procId={procId}")
268
- if nThreadEnd==self.numUsedCores:
269
- break
270
- except queue.Empty :
271
- #prTime(' except queue.Empty Prima ')
272
- if self.flagError : break # in this case a critical exception has been raised we should exit
273
- if com.qProcessed.empty():
274
- if callBack(False,None,None,None,None,None):
275
- com.eventExit.set()# in this case the process will be stopped
276
- #print("com.eventExit.set()# in this case the process will be stopped")
277
- else:
278
- self.readQOutProcess(strOutput,flagProcessed,callBack,names,nElements)
279
- #prTime('********************************\n******************************dopo ')
280
- sleep(self.sleepTime)
281
-
282
- #prTime(f"fine parForExtPool")
283
- # some of the processes may have finished without saving the data
284
- self.readQOutProcess(strOutput,flagProcessed,callBack,names,nElements)
285
- com.clearAll()# just to be sure ideally only needed when self.flagError is True
286
-
287
- return self.p,flagProcessed,strOutput,self.flagError
288
-
289
- def simpleFor(self,parPool,task,names,*args,initTask=None,finalTask=None,wrapUp=None,callBack=None,**kwargs):
290
- ''' parallel for main function
291
- task is the main function that is called for each value in names.
292
- optionally initTask and finalTask are called only one time per worker
293
- args and kwargs are passed to all the functions.add()
294
- Finally the WrapUp function is called one time per worker to wrap things up
295
- '''
296
- com=self.parForCom
297
- com.eventExit.clear()
298
- initTask=self.initTask if initTask is None else initTask
299
- finalTask=self.finalTask if finalTask is None else finalTask
300
- wrapUp=self.wrapUp if wrapUp is None else wrapUp
301
- callBack=self.callBack if callBack is None else callBack
302
- self.flagError=False
303
- self.numCalledCallbacks=0 # reset the number of called callbacks
304
- nElements=len(names)
305
- flagProcessed=[self.nonProcessed]*nElements #lista delle immagini processate inizialmente tutti -1 ma possiamo modificarla
306
- strOutput = [None]*nElements #lista dei messaggi in output in realtà potrebbe essere di qualunque tipo
307
-
308
- def callWrapUp(var):
309
- self.p=wrapUp(*var,*args,**kwargs)
310
- self.parForCom.qOut.put((var[0:2]))
311
-
312
- # per ora -1 non processato, -2 errore ,numero positivo processato
313
- for i,n in enumerate(names):
314
- com.q.put((i,n))
315
- for _ in range(1):
316
- com.q.put((-1,-1))
317
- #with mp.Pool(self.numUsedCores) as pp:
318
- procId=0
319
- var=self.launchTask(procId,task, initTask,finalTask,*args,**kwargs)
320
- callWrapUp(var)
321
- nThreadEnd=0
322
- while True:
323
- try:
324
- #(procId,flagHasWorked)=com.qOut.get_nowait()
325
- (_,_)=com.qOut.get_nowait()
326
- #p=wrapUp(procId,flagHasWorked,p,*args,**kwargs)
327
- nThreadEnd+=1
328
- #prTime(f"fine nThreadEnd={nThreadEnd} procId={procId} flagHasWorked={flagHasWorked}")
329
- if nThreadEnd==1:
330
- break
331
- except queue.Empty :
332
- #prTime('********************************\n******************************Prima ')
333
- if self.flagError : break # in this case a critical exception has been raised we should exit
334
- if com.qProcessed.empty():
335
- if callBack(False,None,None,None,None,None):
336
- com.eventExit.set()# in this case the process will be stopped
337
- #print("com.eventExit.set()# in this case the process will be stopped")
338
- else:
339
- self.readQOutProcess(strOutput,flagProcessed,callBack,names,nElements)
340
- #prTime('********************************\n******************************dopo ')
341
- sleep(self.sleepTime)
342
- # some of the processes may have finished without saving the data
343
- self.readQOutProcess(strOutput,flagProcessed,callBack,names,nElements)
344
- return self.p,flagProcessed,strOutput ,self.flagError
345
-
346
-
347
- def parFor(self,task,names,*args,initTask=None,finalTask=None,wrapUp=None,callBack=None,**kwargs):
348
- ''' parallel for main function
349
- task is the main function that is called for each value in names.
350
- optionally initTask and finalTask are called only one time per worker
351
- args and kwargs are passed to all the functions.add()
352
- callBack is called frequently and can be used to stop the parFor
353
- Finally the WrapUp function is called one time per worker to wrap things up
354
- '''
355
- prTime(0,'Dentro parFor')
356
- pfPool=ParForPool()
357
- pfPool.startParPool(self.numUsedCores)
358
- (p,flagProcessed,strOutput)=self.parForExtPool(pfPool.parPool,task,names,*args,initTask=initTask,finalTask=finalTask,wrapUp=wrapUp,callBack=callBack,**kwargs)
359
- pfPool.closeParPool()
360
- return p,flagProcessed,strOutput
361
-
362
-
363
-
364
- def initPoolProcesses(the_lock):
365
- '''Initialize each process with a global variable lock.
366
- '''
367
- global lock
368
- lock = the_lock
369
-
370
- class ParForPool():
371
- ''' Saves the pool '''
372
- def __init__(self):
373
- self.parPool=None
374
- self.numCoresParPool = mp.cpu_count()//2#da decidere per intel sono /2 son i processori reali
375
- async def startParPoolAsync(self,numCoresParPool):
376
- ''' dummy function to call startParPool in async'''
377
- self.startParPool(numCoresParPool)
378
- def startParPool(self,numCoresParPool):
379
- ''' Starts the pool'''
380
- the_lock = mp.Lock() # neded for prLock and the like
381
- if self.parPool is None:
382
- self.parPool=mp.Pool(numCoresParPool,initializer=initPoolProcesses, initargs=(the_lock,))
383
- elif self.numCoresParPool!=numCoresParPool:
384
- self.parPool.close()# Si potrebbe usare terminate che ammazza tutti i processi in essere
385
- self.parPool=mp.Pool(numCoresParPool)
386
- self.numCoresParPool=numCoresParPool
387
- def closeParPool(self):
388
- ''' Closes the pool'''
389
- if self.parPool is not None:
390
- self.parPool.close()# Si potrebbe usare terminate che ammazza tutti i processi in essere
391
-
392
- async def initParForAsync(numCoresParPool):
393
- ''' initialise the parPool'''
394
- #prTime(0,'PIV_ParFor_Worker init')
395
- pfPool=ParForPool()
396
- t1=asyncio.create_task(pfPool.startParPoolAsync(numCoresParPool))
397
- parForMul=ParForMul()
398
- parForMul.numUsedCores=parForMul.numCoresParPool=numCoresParPool
399
- await t1
400
- #prTime(0,'PIV_ParFor_Worker Dopo ParForPool')
401
- return (pfPool,parForMul)
402
-
403
-
404
- def main():
405
- ''' main '''
406
- prTime(6,'start')
407
-
408
- pp=ParForMul()
409
- #prTime(0,'Dopo ParForMul ****************')
410
-
411
- pp.sleepTime=.1 # time between calls of callBack not used in this example
412
- procTime=.02
413
- nImg= [x for x in range(20)]
414
- #startTime = time()
415
- args=(procTime,)
416
- kwargs={"flagOutput":False, "mes":"fakePIV"}
417
- #pp.initParPool()
418
- #pp.parForCache(fakePIV,nImg,*args,**kwargs)
419
-
420
- pfPool=ParForPool()
421
- pfPool.startParPool(pfPool.numCoresParPool)
422
- #pp.simpleFor(fakePIV,nImg,*args,**kwargs)
423
- pp.numUsedCores =4
424
-
425
- #pp.parForExtPool(pfPool.parPool,fakePIV,nImg,*args,**kwargs)
426
- pp.parForExtPool(pfPool.parPool,fakePIV,nImg,*args,**kwargs)
427
- pfPool.closeParPool()
428
- pp.parFor(fakePIV,nImg,*args,**kwargs)
429
- #pp.parFor(fakePIV,nImg,*args,**kwargs)
430
- prTime(0,'Fine')
431
-
432
-
433
-
434
- if __name__ == "__main__":
435
- main()
11
+ #import numpy as np
12
+ #import scipy as sc
13
+
14
+ prTime=PrintTA(PrintTA.blue, PrintTA.faceStd, PrintTAPriority.medium).prTime
15
+ pr=PrintTA(PrintTA.blue, PrintTA.faceStd, PrintTAPriority.medium).prTime
16
+ # pylint: disable=unused-argument
17
+ lock=None
18
+ def prLock( *args,**kwargs):
19
+ ''' print in parallel pool without overlap (slower)'''
20
+ try:
21
+ with lock:
22
+ PrintTA(PrintTA.blue, PrintTA.faceStd, PrintTAPriority.medium).pr( *args,**kwargs)
23
+ except :
24
+ print(ParForMul.printExceptionPFM(flagMessage=True))
25
+
26
+ def prTimeLock( *args,**kwargs):
27
+ ''' print in parallel pool without overlap (slower)'''
28
+ try:
29
+ with lock:
30
+ PrintTA(PrintTA.blue, PrintTA.faceStd, PrintTAPriority.medium).prTime( *args,**kwargs)
31
+ except:
32
+ print(ParForMul.printExceptionPFM(flagMessage=True))
33
+
34
+ def printExceptionMasterParFor(stringa='',flagMessage=False): #timemilliseconds=-1 ***
35
+ ''' used to print when an exception is raised TA has decided that the printing function is a simple
36
+ print in this way we cannot have any problems when printing in non-compatible terminals
37
+ use with something like
38
+
39
+ try:
40
+ a=1/0
41
+ except :#non need to put a variable al the info are in traceback
42
+ printException()
43
+ * stringa is an additional string (to specify the point where the error comes from)
44
+ * flagMessage is a flag, if true the error message is generated; default value is Flag_DEBUG
45
+ * flagDispDialog is a flag, if true a critical dialog appears after the exception
46
+ '''
47
+ #print(f'***** ParForMul Exception ***** Deltat={time()-PrintTA.startTime}\n{traceback.format_exc()}',*args,**kwargs)
48
+ #print(sys.exc_info()[2])
49
+ Message=""
50
+ if flagMessage:
51
+ Message+=f'Please, mail to: {__mail__}\n\n'
52
+ Message+=f'***** PaIRS Exception ***** time={time()-PrintTA.startTime}\n'+stringa
53
+ Message+=f'***** traceback.print_exc() ***** \n'
54
+ Message+=traceback.format_exc()
55
+ Message+=f'***** traceback.extract_stack() ***** \n'
56
+ # to print all the queue comment if not needed
57
+ for st in traceback.format_list( traceback.extract_stack()):
58
+ if 'PAIRS_GUI' in st and 'printException'not in st:# limits to files that have PAIRS_GUI in the path
59
+ Message+=st
60
+ Message+=f'***** PaIRS Exception -> End *****'
61
+ return Message
62
+
63
+
64
+
65
+ def fakePIV(iImg,procId, p, procTime, flagOutput=False, mes="fakePIV"):
66
+ ''' fakePIV'''
67
+ startTime = time()
68
+ #print(f'reading Img {iImg} pid={os.getpid()} pid={mp.current_process().pid}')
69
+ #print(f'reading Img {iImg} pid={mp.current_process().pid} procId={procId}')
70
+ #sleep(0.5)
71
+ #print(f'Finished reading Img {iImg}')
72
+
73
+ a=0
74
+ count=1*1000*1000#on my pc 10*1000*1000=1sec
75
+ nIt=1
76
+ while nIt<2000000:
77
+ for _ in range(count):
78
+ a+=5#random.random()
79
+ if time()-startTime>procTime:
80
+ break
81
+ nIt+=1
82
+ if flagOutput:
83
+ print(f'fine proc Img {iImg} Nit={nIt} t={time()-startTime} mes={mes}')
84
+ return (0,f'fine proc Img {iImg} Nit={nIt} t={time()-startTime} mes={mes}')
85
+
86
+ #return iImg
87
+
88
+ class ParForCom():
89
+ ''' Comunication varibles used by ParFor'''
90
+ def __init__(self):
91
+ #prTime(0,'Dentro ParForCom Com')
92
+ manager=mp.Manager()#si potrebbe creare un lock al posto della variabile globale qui cercare su internet
93
+ #prTime(0,'Dentro ParForCom dopo manager')
94
+ self.q = manager.Queue()
95
+ self.qOut= manager.Queue()
96
+ self.qProcessed= manager.Queue()
97
+ self.eventExit = manager.Event()
98
+
99
+ def clearAll(self):
100
+ ''' Clears all the queues'''
101
+ self.clear(self.q)
102
+ self.clear(self.qOut)
103
+ self.clear(self.qProcessed)
104
+
105
+
106
+
107
+ def clear(self,q:queue):
108
+ '''clears a Queue'''
109
+ try:
110
+ while True:
111
+ q.get_nowait()
112
+ except queue.Empty:
113
+ pass
114
+
115
+
116
+
117
+ class ParForMul():
118
+ ''' class Parallel for for PIV '''
119
+ printExceptionPFM=printExceptionMasterParFor #class variable
120
+ def __init__(self):
121
+ #prTime(0,'Dentro ParForMul inizio')
122
+ self.parForCom:ParForCom=ParForCom()
123
+ # valori impostabili dall'esterno
124
+ self.sleepTime=1. # waiting to do things
125
+ self.nonProcessed=0 # waiting to do things
126
+ #self.numUsedCores =psutil.cpu_count(logical=False)
127
+ ## numUsedCores is the number of cores used fo processing and can be different from numCoresParPool that is the number of cores used in the parPool
128
+ self.numCoresParPool=self.numUsedCores = mp.cpu_count()//2#da decidere per intel /2 sono i processori reali
129
+ #prTime(0,'Dentro ParForMul fine')
130
+ self.numCalledCallbacks=0 # identify the times that the callbacks have been called
131
+ self.p=None
132
+ self.flagError=False
133
+ self.exception=None
134
+
135
+
136
+ def initTask(self,eventExit,name,procId,*args,**kwargs):
137
+ ''' dummy InitTask sample
138
+ id is the id of the task should be a numeber between 1 and numUsedCores
139
+ if needed initTask should call the main task with name
140
+ '''
141
+
142
+ (flag,var)=fakePIV(name, procId,('initTask',2), *args,**kwargs)
143
+ return (flag,var,('initTask',2))
144
+
145
+ def wrapUp(self,procId,flagHasWorked,P,*args,**kwargs):
146
+ ''' Dummy wrapUp function '''
147
+ if flagHasWorked:#do something
148
+ pass
149
+ return P
150
+
151
+ def callBack(self,flag,perc,procId,flagOutFromTask, name,varOutFromTask):
152
+ ''' Dummy callBack function
153
+ perc=percentage of processed images
154
+ flag=true new data False just check exit
155
+ perc= precentage done
156
+ flagOutFromTasks,varOutFromTask Out variables from task e.g.:
157
+ flagOutFromTasks= 0 success, 1 skipped, -1 error, -2 blocked from caller
158
+ varOutFromTask whatever for now string
159
+ name current element in names
160
+ to stop the process the return value should be True otherwise sleep '''
161
+ if not flag:
162
+ return False
163
+ return False
164
+
165
+ def finalTask(self,procId,*args,**kwargs):
166
+ ''' dummy final finalTask function
167
+ id is the id of the task should be a numeber between 1 and numUsedCores'''
168
+ return ('finalTask',2)
169
+
170
+ def launchTask(self,procId,task,initTask,finalTask, *args,**kwargs):
171
+ ''' the main parallel function first calls initTask (eventExit is an event that enables the safe exit)
172
+ then for all the element in the queue q calls task with the variable returned by initTask
173
+ finally calls finalTask puts in the queue qOut the final result '''
174
+ # aggiunto try così almeno ci rendiamo conto se c'è un errore
175
+ '''
176
+ try:
177
+ procId=mp.current_process()._identity[0]
178
+ except:
179
+ procId=0 # '''
180
+ #pid=mp.current_process().pid
181
+ flagHasWorked=False#if true the task has processed at least one element
182
+ #if procId==2: prTimeLock(f"launchTask |||||||||||| Inizio procId={procId} flagHasWorked={flagHasWorked} ")
183
+ media=None
184
+ try:
185
+ i,n=self.parForCom.q.get()# the first time task must be called by initTask
186
+ if i!=-1:
187
+ flagHasWorked=True
188
+ (flag,var,P)=initTask(self.parForCom.eventExit,n,procId,*args,**kwargs)
189
+ self.parForCom.qProcessed.put((procId,flag,i,var))
190
+ while True:
191
+ i,n=self.parForCom.q.get()
192
+ if i==-1:
193
+ break
194
+ (flag,var)=task(n,procId,P,*args,**kwargs)
195
+ self.parForCom.qProcessed.put((procId,flag,i,var))
196
+ media=finalTask(procId,P,*args,**kwargs)# media should be different from None
197
+ except Exception as e:
198
+ raise(e) # I do not really care to have a full report if in debug it may be important
199
+ #ParForMul.printExceptionPFM()
200
+ flagHasWorked=False if media is None else flagHasWorked #if true the task has processed at least one element and media should be different from None
201
+ return (procId,flagHasWorked,media)
202
+
203
+ def readQOutProcess(self,strOutput,flagProcessed,callBack,names,nElements):
204
+ ''' reads the qOut queue save the data and calls callback'''
205
+ com=self.parForCom
206
+ while not com.qProcessed.empty():
207
+ (procId,flag,i,var)=com.qProcessed.get_nowait()
208
+ perc=1-(com.q.qsize()-self.numUsedCores)/nElements#
209
+ strOutput[i]=var
210
+ flagProcessed[i]=flag
211
+
212
+ #prLock(f'callBack {i} {perc} {com.q.qsize()}')
213
+ if callBack(True,perc,procId,flag,names[i],var):
214
+ com.eventExit.set()# in this case the process will stop
215
+ self.numCalledCallbacks+=1
216
+
217
+ def errorHandler(self,error):
218
+ ''' error function '''
219
+ #self.errorMessage=ParForMul.printExceptionPFM(flagMessage=True)
220
+ self.exception=error
221
+ self.flagError=True
222
+ self.parForCom.eventExit.set()# in this case the process will stop
223
+ #raise(error)
224
+ def parForExtPool(self,parPool,task,names,*args,initTask=None,finalTask=None,wrapUp=None,callBack=None,**kwargs):
225
+ ''' parallel for main function with external mp pool
226
+ task is the main function that is called for each value in names.
227
+ optionally initTask and finalTask are called only one time per worker
228
+ args and kwargs are passed to all the functions.add()
229
+ callBack is called frequently and can be used to stop the parFor
230
+ Finally the WrapUp function is called one time per worker to wrap things up
231
+ '''
232
+ #prTime(0,'Dentro parForExtPool')
233
+
234
+ com=self.parForCom
235
+ com.eventExit.clear()
236
+ initTask=self.initTask if initTask is None else initTask
237
+ finalTask=self.finalTask if finalTask is None else finalTask
238
+ wrapUp=self.wrapUp if wrapUp is None else wrapUp
239
+ callBack=self.callBack if callBack is None else callBack
240
+ self.flagError=False
241
+ self.numCalledCallbacks=0 # reset the number of called callbacks
242
+ nElements=len(names)
243
+ flagProcessed=[self.nonProcessed]*nElements #lista delle immagini processate inizialmente tutti -1 ma possiamo modificarla
244
+ strOutput = [None]*nElements #lista dei messaggi in output in realtà potrebbe essere di qualunque tipo
245
+ def callWrapUp(var):
246
+ self.p=wrapUp(*var,*args,**kwargs)
247
+ self.parForCom.qOut.put((var[0:2])) #procid , flagHasWorked
248
+ #prTime(f"callWrapUp fine procid={var[0]} ")
249
+
250
+ # per ora -1 non processato, -2 errore ,numero positivo processato
251
+ for i,n in enumerate(names):
252
+ com.q.put((i,n))
253
+ for _ in range(self.numUsedCores):
254
+ com.q.put((-1,-1))
255
+
256
+ for i in range(self.numUsedCores):
257
+ _=parPool.apply_async(self.launchTask,(i,task, initTask,finalTask)+args,kwargs,callback=callWrapUp, error_callback=self.errorHandler)
258
+ #_=parPool.apply_async(self.launchTask,(task, initTask,finalTask)+args,kwargs, error_callback=self.errorHandler)
259
+ #prTime(0,'Dopo apply async in parForExtPool ++++++++++++++++++++++++++++++++++')
260
+ nThreadEnd=0
261
+ while True:
262
+ try:
263
+ #(procId,flagHasWorked)=com.qOut.get_nowait()
264
+ (_,_)=com.qOut.get_nowait()
265
+ #p=wrapUp(procId,flagHasWorked,p,*args,**kwargs)
266
+ nThreadEnd+=1
267
+ #if nThreadEnd==1: prTime(f"fine nThreadEnd={nThreadEnd} procId={procId}")
268
+ if nThreadEnd==self.numUsedCores:
269
+ break
270
+ except queue.Empty :
271
+ #prTime(' except queue.Empty Prima ')
272
+ if self.flagError : break # in this case a critical exception has been raised we should exit
273
+ if com.qProcessed.empty():
274
+ if callBack(False,None,None,None,None,None):
275
+ com.eventExit.set()# in this case the process will be stopped
276
+ #print("com.eventExit.set()# in this case the process will be stopped")
277
+ else:
278
+ self.readQOutProcess(strOutput,flagProcessed,callBack,names,nElements)
279
+ #prTime('********************************\n******************************dopo ')
280
+ sleep(self.sleepTime)
281
+
282
+ #prTime(f"fine parForExtPool")
283
+ # some of the processes may have finished without saving the data
284
+ self.readQOutProcess(strOutput,flagProcessed,callBack,names,nElements)
285
+ com.clearAll()# just to be sure ideally only needed when self.flagError is True
286
+
287
+ return self.p,flagProcessed,strOutput,self.flagError
288
+
289
+ def simpleFor(self,parPool,task,names,*args,initTask=None,finalTask=None,wrapUp=None,callBack=None,**kwargs):
290
+ ''' parallel for main function
291
+ task is the main function that is called for each value in names.
292
+ optionally initTask and finalTask are called only one time per worker
293
+ args and kwargs are passed to all the functions.add()
294
+ Finally the WrapUp function is called one time per worker to wrap things up
295
+ '''
296
+ com=self.parForCom
297
+ com.eventExit.clear()
298
+ initTask=self.initTask if initTask is None else initTask
299
+ finalTask=self.finalTask if finalTask is None else finalTask
300
+ wrapUp=self.wrapUp if wrapUp is None else wrapUp
301
+ callBack=self.callBack if callBack is None else callBack
302
+ self.flagError=False
303
+ self.numCalledCallbacks=0 # reset the number of called callbacks
304
+ nElements=len(names)
305
+ flagProcessed=[self.nonProcessed]*nElements #lista delle immagini processate inizialmente tutti -1 ma possiamo modificarla
306
+ strOutput = [None]*nElements #lista dei messaggi in output in realtà potrebbe essere di qualunque tipo
307
+
308
+ def callWrapUp(var):
309
+ self.p=wrapUp(*var,*args,**kwargs)
310
+ self.parForCom.qOut.put((var[0:2]))
311
+
312
+ # per ora -1 non processato, -2 errore ,numero positivo processato
313
+ for i,n in enumerate(names):
314
+ com.q.put((i,n))
315
+ for _ in range(1):
316
+ com.q.put((-1,-1))
317
+ #with mp.Pool(self.numUsedCores) as pp:
318
+ procId=0
319
+ var=self.launchTask(procId,task, initTask,finalTask,*args,**kwargs)
320
+ callWrapUp(var)
321
+ nThreadEnd=0
322
+ while True:
323
+ try:
324
+ #(procId,flagHasWorked)=com.qOut.get_nowait()
325
+ (_,_)=com.qOut.get_nowait()
326
+ #p=wrapUp(procId,flagHasWorked,p,*args,**kwargs)
327
+ nThreadEnd+=1
328
+ #prTime(f"fine nThreadEnd={nThreadEnd} procId={procId} flagHasWorked={flagHasWorked}")
329
+ if nThreadEnd==1:
330
+ break
331
+ except queue.Empty :
332
+ #prTime('********************************\n******************************Prima ')
333
+ if self.flagError : break # in this case a critical exception has been raised we should exit
334
+ if com.qProcessed.empty():
335
+ if callBack(False,None,None,None,None,None):
336
+ com.eventExit.set()# in this case the process will be stopped
337
+ #print("com.eventExit.set()# in this case the process will be stopped")
338
+ else:
339
+ self.readQOutProcess(strOutput,flagProcessed,callBack,names,nElements)
340
+ #prTime('********************************\n******************************dopo ')
341
+ sleep(self.sleepTime)
342
+ # some of the processes may have finished without saving the data
343
+ self.readQOutProcess(strOutput,flagProcessed,callBack,names,nElements)
344
+ return self.p,flagProcessed,strOutput ,self.flagError
345
+
346
+
347
+ def parFor(self,task,names,*args,initTask=None,finalTask=None,wrapUp=None,callBack=None,**kwargs):
348
+ ''' parallel for main function
349
+ task is the main function that is called for each value in names.
350
+ optionally initTask and finalTask are called only one time per worker
351
+ args and kwargs are passed to all the functions.add()
352
+ callBack is called frequently and can be used to stop the parFor
353
+ Finally the WrapUp function is called one time per worker to wrap things up
354
+ '''
355
+ prTime(0,'Dentro parFor')
356
+ pfPool=ParForPool()
357
+ pfPool.startParPool(self.numUsedCores)
358
+ (p,flagProcessed,strOutput)=self.parForExtPool(pfPool.parPool,task,names,*args,initTask=initTask,finalTask=finalTask,wrapUp=wrapUp,callBack=callBack,**kwargs)
359
+ pfPool.closeParPool()
360
+ return p,flagProcessed,strOutput
361
+
362
+
363
+
364
+ def initPoolProcesses(the_lock):
365
+ '''Initialize each process with a global variable lock.
366
+ '''
367
+ global lock
368
+ lock = the_lock
369
+
370
+ class ParForPool():
371
+ ''' Saves the pool '''
372
+ def __init__(self):
373
+ self.parPool=None
374
+ self.numCoresParPool = mp.cpu_count()//2#da decidere per intel sono /2 son i processori reali
375
+ async def startParPoolAsync(self,numCoresParPool):
376
+ ''' dummy function to call startParPool in async'''
377
+ self.startParPool(numCoresParPool)
378
+ def startParPool(self,numCoresParPool):
379
+ ''' Starts the pool'''
380
+ the_lock = mp.Lock() # neded for prLock and the like
381
+ if self.parPool is None:
382
+ self.parPool=mp.Pool(numCoresParPool,initializer=initPoolProcesses, initargs=(the_lock,))
383
+ elif self.numCoresParPool!=numCoresParPool:
384
+ self.parPool.close()# Si potrebbe usare terminate che ammazza tutti i processi in essere
385
+ self.parPool=mp.Pool(numCoresParPool)
386
+ self.numCoresParPool=numCoresParPool
387
+ def closeParPool(self):
388
+ ''' Closes the pool'''
389
+ if self.parPool is not None:
390
+ self.parPool.close()# Si potrebbe usare terminate che ammazza tutti i processi in essere
391
+
392
+ async def initParForAsync(numCoresParPool):
393
+ ''' initialise the parPool'''
394
+ #prTime(0,'PIV_ParFor_Worker init')
395
+ pfPool=ParForPool()
396
+ t1=asyncio.create_task(pfPool.startParPoolAsync(numCoresParPool))
397
+ parForMul=ParForMul()
398
+ parForMul.numUsedCores=parForMul.numCoresParPool=numCoresParPool
399
+ await t1
400
+ #prTime(0,'PIV_ParFor_Worker Dopo ParForPool')
401
+ return (pfPool,parForMul)
402
+
403
+
404
+ def main():
405
+ ''' main '''
406
+ prTime(6,'start')
407
+
408
+ pp=ParForMul()
409
+ #prTime(0,'Dopo ParForMul ****************')
410
+
411
+ pp.sleepTime=.1 # time between calls of callBack not used in this example
412
+ procTime=.02
413
+ nImg= [x for x in range(20)]
414
+ #startTime = time()
415
+ args=(procTime,)
416
+ kwargs={"flagOutput":False, "mes":"fakePIV"}
417
+ #pp.initParPool()
418
+ #pp.parForCache(fakePIV,nImg,*args,**kwargs)
419
+
420
+ pfPool=ParForPool()
421
+ pfPool.startParPool(pfPool.numCoresParPool)
422
+ #pp.simpleFor(fakePIV,nImg,*args,**kwargs)
423
+ pp.numUsedCores =4
424
+
425
+ #pp.parForExtPool(pfPool.parPool,fakePIV,nImg,*args,**kwargs)
426
+ pp.parForExtPool(pfPool.parPool,fakePIV,nImg,*args,**kwargs)
427
+ pfPool.closeParPool()
428
+ pp.parFor(fakePIV,nImg,*args,**kwargs)
429
+ #pp.parFor(fakePIV,nImg,*args,**kwargs)
430
+ prTime(0,'Fine')
431
+
432
+
433
+
434
+ if __name__ == "__main__":
435
+ main()