python-microscopy 25.11.20__cp313-cp313-win_amd64.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 (1278) hide show
  1. PYME/Acquire/ActionManager.py +450 -0
  2. PYME/Acquire/ExecTools.py +235 -0
  3. PYME/Acquire/Hardware/AAOptoelectronics/MDS.py +175 -0
  4. PYME/Acquire/Hardware/AAOptoelectronics/__init__.py +0 -0
  5. PYME/Acquire/Hardware/ARCoptix/__init__.py +0 -0
  6. PYME/Acquire/Hardware/ARCoptix/lcdriver.py +149 -0
  7. PYME/Acquire/Hardware/ARCoptix/lcserver32.py +123 -0
  8. PYME/Acquire/Hardware/AndorIXon/AndorCam.py +1095 -0
  9. PYME/Acquire/Hardware/AndorIXon/AndorControlFrame.py +312 -0
  10. PYME/Acquire/Hardware/AndorIXon/AndorIXon.py +737 -0
  11. PYME/Acquire/Hardware/AndorIXon/__init__.py +27 -0
  12. PYME/Acquire/Hardware/AndorNeo/AndorNeo.py +644 -0
  13. PYME/Acquire/Hardware/AndorNeo/AndorNeoControlFrame.py +161 -0
  14. PYME/Acquire/Hardware/AndorNeo/AndorZyla.py +761 -0
  15. PYME/Acquire/Hardware/AndorNeo/SDK3.py +307 -0
  16. PYME/Acquire/Hardware/AndorNeo/SDK3Cam.py +171 -0
  17. PYME/Acquire/Hardware/AndorNeo/ZylaControlPanel.py +105 -0
  18. PYME/Acquire/Hardware/AndorNeo/__init__.py +22 -0
  19. PYME/Acquire/Hardware/AndorNeo/parseAtdebug.py +46 -0
  20. PYME/Acquire/Hardware/AndorNeo/plotTimings.py +73 -0
  21. PYME/Acquire/Hardware/AndorNeo/testNeo.py +62 -0
  22. PYME/Acquire/Hardware/Camera.py +1199 -0
  23. PYME/Acquire/Hardware/CameraSkeleton.py +642 -0
  24. PYME/Acquire/Hardware/Coherent/OBIS.py +147 -0
  25. PYME/Acquire/Hardware/Coherent/Sapphire.py +162 -0
  26. PYME/Acquire/Hardware/Coherent/__init__.py +0 -0
  27. PYME/Acquire/Hardware/DMDGui.py +198 -0
  28. PYME/Acquire/Hardware/DigiData/DigiData.py +95 -0
  29. PYME/Acquire/Hardware/DigiData/DigiDataClient.py +30 -0
  30. PYME/Acquire/Hardware/DigiData/RemoteDigiData.py +51 -0
  31. PYME/Acquire/Hardware/DigiData/__init__.py +24 -0
  32. PYME/Acquire/Hardware/DigiData/axDD132x.py +348 -0
  33. PYME/Acquire/Hardware/EMCCDTheory.py +41 -0
  34. PYME/Acquire/Hardware/ExciterWheel.py +167 -0
  35. PYME/Acquire/Hardware/FilterWheel.py +184 -0
  36. PYME/Acquire/Hardware/FocCorr.py +106 -0
  37. PYME/Acquire/Hardware/FocCorrR.py +196 -0
  38. PYME/Acquire/Hardware/FrFilter.py +51 -0
  39. PYME/Acquire/Hardware/GCS/GCS_DLL.py +370 -0
  40. PYME/Acquire/Hardware/GCS/__init__.py +0 -0
  41. PYME/Acquire/Hardware/GCS/gcs.py +210 -0
  42. PYME/Acquire/Hardware/HamamatsuDCAM/HamamatsuDCAM.py +662 -0
  43. PYME/Acquire/Hardware/HamamatsuDCAM/HamamatsuORCA.py +602 -0
  44. PYME/Acquire/Hardware/HamamatsuDCAM/Hamamatsu_control_panel.py +54 -0
  45. PYME/Acquire/Hardware/HamamatsuDCAM/__init__.py +23 -0
  46. PYME/Acquire/Hardware/LaserControlFrame.py +160 -0
  47. PYME/Acquire/Hardware/MPBCommunications/MPBCW.py +132 -0
  48. PYME/Acquire/Hardware/MPBCommunications/__init__.py +0 -0
  49. PYME/Acquire/Hardware/Mercury/Mercury.py +269 -0
  50. PYME/Acquire/Hardware/Mercury/PI_Mercury_GCS_DLL.py +857 -0
  51. PYME/Acquire/Hardware/Mercury/__init__.py +22 -0
  52. PYME/Acquire/Hardware/Mercury/mercuryStepper.py +203 -0
  53. PYME/Acquire/Hardware/Mercury/mercuryStepperGCS.py +281 -0
  54. PYME/Acquire/Hardware/NikonTE2000.py +68 -0
  55. PYME/Acquire/Hardware/NikonTi.py +214 -0
  56. PYME/Acquire/Hardware/NikonTiGUI.py +81 -0
  57. PYME/Acquire/Hardware/OrielCornerstone.py +125 -0
  58. PYME/Acquire/Hardware/PM100USB.py +51 -0
  59. PYME/Acquire/Hardware/Piezos/__init__.py +22 -0
  60. PYME/Acquire/Hardware/Piezos/base_piezo.py +108 -0
  61. PYME/Acquire/Hardware/Piezos/offsetPiezo.py +162 -0
  62. PYME/Acquire/Hardware/Piezos/offsetPiezoREST.py +308 -0
  63. PYME/Acquire/Hardware/Piezos/piezo_c867.py +486 -0
  64. PYME/Acquire/Hardware/Piezos/piezo_e255.py +68 -0
  65. PYME/Acquire/Hardware/Piezos/piezo_e662.py +61 -0
  66. PYME/Acquire/Hardware/Piezos/piezo_e709.py +434 -0
  67. PYME/Acquire/Hardware/Piezos/piezo_e816.py +452 -0
  68. PYME/Acquire/Hardware/Piezos/piezo_e816_corr.py +70 -0
  69. PYME/Acquire/Hardware/Piezos/piezo_e816_dll.py +518 -0
  70. PYME/Acquire/Hardware/Piezos/piezo_e816b.py +70 -0
  71. PYME/Acquire/Hardware/Piezos/piezo_pipython_gcs.py +560 -0
  72. PYME/Acquire/Hardware/Piezos/piezo_test.py +55 -0
  73. PYME/Acquire/Hardware/Simulator/EmpiricalHist.py +273 -0
  74. PYME/Acquire/Hardware/Simulator/__init__.py +22 -0
  75. PYME/Acquire/Hardware/Simulator/dSimControl.py +961 -0
  76. PYME/Acquire/Hardware/Simulator/fakeCam.py +651 -0
  77. PYME/Acquire/Hardware/Simulator/fakePiezo.py +95 -0
  78. PYME/Acquire/Hardware/Simulator/fluor.py +336 -0
  79. PYME/Acquire/Hardware/Simulator/illuminate.cp313-win_amd64.dll.a +0 -0
  80. PYME/Acquire/Hardware/Simulator/illuminate.cp313-win_amd64.pyd +0 -0
  81. PYME/Acquire/Hardware/Simulator/illuminate.pyx +93 -0
  82. PYME/Acquire/Hardware/Simulator/lasersliders.py +90 -0
  83. PYME/Acquire/Hardware/Simulator/rend_im.py +446 -0
  84. PYME/Acquire/Hardware/Simulator/setup.py +69 -0
  85. PYME/Acquire/Hardware/Simulator/simcontrol.py +348 -0
  86. PYME/Acquire/Hardware/Simulator/simui_wx.py +794 -0
  87. PYME/Acquire/Hardware/Tango/__init__.py +0 -0
  88. PYME/Acquire/Hardware/Tango/marzhauser_tango.py +583 -0
  89. PYME/Acquire/Hardware/TiLightCrafter.py +388 -0
  90. PYME/Acquire/Hardware/__init__.py +22 -0
  91. PYME/Acquire/Hardware/aotf.py +271 -0
  92. PYME/Acquire/Hardware/arclampshutterpanel.py +71 -0
  93. PYME/Acquire/Hardware/cameraSoftwareBuffer.py +215 -0
  94. PYME/Acquire/Hardware/camera_noise.py +270 -0
  95. PYME/Acquire/Hardware/ccdAdjPanel.py +188 -0
  96. PYME/Acquire/Hardware/ccdCalibrator.py +161 -0
  97. PYME/Acquire/Hardware/cobaltLaser.py +108 -0
  98. PYME/Acquire/Hardware/cobaltLaser561.py +94 -0
  99. PYME/Acquire/Hardware/comports.py +26 -0
  100. PYME/Acquire/Hardware/driftTrackGUI.py +488 -0
  101. PYME/Acquire/Hardware/driftTracking.py +595 -0
  102. PYME/Acquire/Hardware/fakeShutters.py +52 -0
  103. PYME/Acquire/Hardware/focusKeys.py +204 -0
  104. PYME/Acquire/Hardware/focus_locks/__init__.py +0 -0
  105. PYME/Acquire/Hardware/focus_locks/reflection_focus_lock.py +684 -0
  106. PYME/Acquire/Hardware/frZStage.py +117 -0
  107. PYME/Acquire/Hardware/fw102.py +38 -0
  108. PYME/Acquire/Hardware/ids_peak_cam.py +561 -0
  109. PYME/Acquire/Hardware/ioslave.py +305 -0
  110. PYME/Acquire/Hardware/lasers.py +292 -0
  111. PYME/Acquire/Hardware/matchboxLaser.py +58 -0
  112. PYME/Acquire/Hardware/microscope_adapter.py +104 -0
  113. PYME/Acquire/Hardware/mpd_picosecond_delayer.py +395 -0
  114. PYME/Acquire/Hardware/multiview.py +287 -0
  115. PYME/Acquire/Hardware/olympusix81.py +59 -0
  116. PYME/Acquire/Hardware/pco/__init__.py +0 -0
  117. PYME/Acquire/Hardware/pco/pco_cam.py +348 -0
  118. PYME/Acquire/Hardware/pco/pco_edge_42_lt.py +34 -0
  119. PYME/Acquire/Hardware/pco/pco_sdk.py +1645 -0
  120. PYME/Acquire/Hardware/pco/pco_sdk_cam.py +518 -0
  121. PYME/Acquire/Hardware/pco/pco_sdk_cam_control_panel.py +54 -0
  122. PYME/Acquire/Hardware/phoxxLaser.py +199 -0
  123. PYME/Acquire/Hardware/phoxxLaserOLD.py +242 -0
  124. PYME/Acquire/Hardware/priorLumen.py +102 -0
  125. PYME/Acquire/Hardware/priorarclampshutter.py +52 -0
  126. PYME/Acquire/Hardware/setup.py +50 -0
  127. PYME/Acquire/Hardware/spacenav.py +148 -0
  128. PYME/Acquire/Hardware/splitter.py +394 -0
  129. PYME/Acquire/Hardware/thorlabsPiezo.py +98 -0
  130. PYME/Acquire/Hardware/thorlabs_cam.py +136 -0
  131. PYME/Acquire/Hardware/thorlabs_mff_flipper.py +400 -0
  132. PYME/Acquire/Hardware/toptica_ibeam.py +51 -0
  133. PYME/Acquire/Hardware/uc480/AndorControlFrame.py +308 -0
  134. PYME/Acquire/Hardware/uc480/__init__.py +27 -0
  135. PYME/Acquire/Hardware/uc480/uCam480.py +695 -0
  136. PYME/Acquire/Hardware/uc480/uc480.py +189 -0
  137. PYME/Acquire/Hardware/uc480/uc480Deprecated.py +87 -0
  138. PYME/Acquire/Hardware/uc480/uc480_h.py +767 -0
  139. PYME/Acquire/Hardware/uc480/uc480_h_gen.py +62 -0
  140. PYME/Acquire/Hardware/uc480/ucCamControlFrame.py +83 -0
  141. PYME/Acquire/Hardware/ueye.py +702 -0
  142. PYME/Acquire/PYMEAcquire.py +186 -0
  143. PYME/Acquire/Protocols/DMDMFM.py +74 -0
  144. PYME/Acquire/Protocols/__init__.py +22 -0
  145. PYME/Acquire/Protocols/darkCalibrate.py +56 -0
  146. PYME/Acquire/Protocols/dual671_470.py +45 -0
  147. PYME/Acquire/Protocols/dual671_488.py +46 -0
  148. PYME/Acquire/Protocols/gainCal.py +53 -0
  149. PYME/Acquire/Protocols/htsms-cal-psf.py +32 -0
  150. PYME/Acquire/Protocols/htsms-cal-registration.py +52 -0
  151. PYME/Acquire/Protocols/htsms-flow.py +29 -0
  152. PYME/Acquire/Protocols/htsms-staggered.py +31 -0
  153. PYME/Acquire/Protocols/htsms-tile.py +68 -0
  154. PYME/Acquire/Protocols/htsms-two-color.py +29 -0
  155. PYME/Acquire/Protocols/htsms-widefield.py +32 -0
  156. PYME/Acquire/Protocols/paint671.py +61 -0
  157. PYME/Acquire/Protocols/photoconversion.py +52 -0
  158. PYME/Acquire/Protocols/photoconversion2.py +55 -0
  159. PYME/Acquire/Protocols/prebleach488.py +70 -0
  160. PYME/Acquire/Protocols/prebleach490.py +69 -0
  161. PYME/Acquire/Protocols/prebleach561.py +72 -0
  162. PYME/Acquire/Protocols/prebleach561NeomEos2.py +70 -0
  163. PYME/Acquire/Protocols/prebleach561NeomEos2ND1.py +70 -0
  164. PYME/Acquire/Protocols/prebleach642.py +70 -0
  165. PYME/Acquire/Protocols/prebleach671.py +69 -0
  166. PYME/Acquire/Protocols/prebleach671ND1.py +58 -0
  167. PYME/Acquire/Protocols/prebleach671ND2.py +57 -0
  168. PYME/Acquire/Protocols/prebleach671Neo.py +69 -0
  169. PYME/Acquire/Protocols/recover671.py +62 -0
  170. PYME/Acquire/Protocols/sequence642_488.py +85 -0
  171. PYME/Acquire/Protocols/sequence642_561.py +87 -0
  172. PYME/Acquire/Protocols/shiftfield.py +198 -0
  173. PYME/Acquire/Protocols/simul488.py +59 -0
  174. PYME/Acquire/Protocols/simul642.py +63 -0
  175. PYME/Acquire/Protocols/simul642HTSMS.py +63 -0
  176. PYME/Acquire/Protocols/simulPA.py +37 -0
  177. PYME/Acquire/Protocols/simulSIM.py +76 -0
  178. PYME/Acquire/Protocols/simulStep.py +62 -0
  179. PYME/Acquire/Protocols/spdscan.py +178 -0
  180. PYME/Acquire/Protocols/standard470.py +45 -0
  181. PYME/Acquire/Protocols/standard488.py +47 -0
  182. PYME/Acquire/Protocols/standard671.py +48 -0
  183. PYME/Acquire/Protocols/standard671_no532.py +47 -0
  184. PYME/Acquire/Protocols/standardArclamp.py +46 -0
  185. PYME/Acquire/Protocols/strip_tile.py +204 -0
  186. PYME/Acquire/Protocols/tile.py +204 -0
  187. PYME/Acquire/Protocols/tile3D.py +192 -0
  188. PYME/Acquire/Protocols/tile671.py +190 -0
  189. PYME/Acquire/Protocols/tile_triggered.py +189 -0
  190. PYME/Acquire/Scripts/init.py +232 -0
  191. PYME/Acquire/Scripts/init_N1_Ti_Exeter_ZIx.py +374 -0
  192. PYME/Acquire/Scripts/init_N2_Ti_Zyla_lasers.py +290 -0
  193. PYME/Acquire/Scripts/init_Neo.py +266 -0
  194. PYME/Acquire/Scripts/init_NeoSim.py +159 -0
  195. PYME/Acquire/Scripts/init_TIRF.py +232 -0
  196. PYME/Acquire/Scripts/init_TIRF_Neo.py +242 -0
  197. PYME/Acquire/Scripts/init_TIRF_NeoO.py +241 -0
  198. PYME/Acquire/Scripts/init_TIRF_onecam.py +233 -0
  199. PYME/Acquire/Scripts/init_Ti.py +257 -0
  200. PYME/Acquire/Scripts/init_UOA_n.py +256 -0
  201. PYME/Acquire/Scripts/init_UOA_n2.py +246 -0
  202. PYME/Acquire/Scripts/init_Y1.py +249 -0
  203. PYME/Acquire/Scripts/init_Zyla.py +260 -0
  204. PYME/Acquire/Scripts/init_drift_tracking.py +80 -0
  205. PYME/Acquire/Scripts/init_emccd_basic.py +277 -0
  206. PYME/Acquire/Scripts/init_htsms.py +277 -0
  207. PYME/Acquire/Scripts/init_htsms_focus_lock.py +132 -0
  208. PYME/Acquire/Scripts/init_micrpi.py +45 -0
  209. PYME/Acquire/Scripts/init_orca.py +70 -0
  210. PYME/Acquire/Scripts/init_pco.py +49 -0
  211. PYME/Acquire/Scripts/init_rev.py +74 -0
  212. PYME/Acquire/Scripts/init_sim100.py +169 -0
  213. PYME/Acquire/Scripts/init_sim103.py +169 -0
  214. PYME/Acquire/Scripts/init_sim2.py +211 -0
  215. PYME/Acquire/Scripts/init_sim50.py +169 -0
  216. PYME/Acquire/Scripts/init_sim75.py +169 -0
  217. PYME/Acquire/Scripts/init_sim_drift_tracking.py +166 -0
  218. PYME/Acquire/Scripts/init_sim_htsms.py +224 -0
  219. PYME/Acquire/Scripts/init_sim_htsms_n.py +233 -0
  220. PYME/Acquire/Scripts/init_sim_main.py +229 -0
  221. PYME/Acquire/Scripts/init_sim_min.py +197 -0
  222. PYME/Acquire/Scripts/init_sim_rem.py +176 -0
  223. PYME/Acquire/Scripts/init_smi1.py +110 -0
  224. PYME/Acquire/Scripts/init_spectro.py +78 -0
  225. PYME/Acquire/Scripts/init_spim.py +116 -0
  226. PYME/Acquire/Scripts/init_thorcam.py +62 -0
  227. PYME/Acquire/Scripts/init_twophoton.py +112 -0
  228. PYME/Acquire/Scripts/init_uc480.py +262 -0
  229. PYME/Acquire/Scripts/init_ueye.py +261 -0
  230. PYME/Acquire/SpoolController.py +958 -0
  231. PYME/Acquire/Utils/MultiPointScanner.py +80 -0
  232. PYME/Acquire/Utils/__init__.py +13 -0
  233. PYME/Acquire/Utils/failsafe.py +157 -0
  234. PYME/Acquire/Utils/fastTiler.py +153 -0
  235. PYME/Acquire/Utils/pointScanner.py +496 -0
  236. PYME/Acquire/Utils/sarcSpacing.py +86 -0
  237. PYME/Acquire/Utils/strip_tiler.py +93 -0
  238. PYME/Acquire/Utils/tiler.py +464 -0
  239. PYME/Acquire/Utils/vibrationAnalysis.py +65 -0
  240. PYME/Acquire/__init__.py +44 -0
  241. PYME/Acquire/acquire_client.py +90 -0
  242. PYME/Acquire/acquire_server.py +316 -0
  243. PYME/Acquire/acquirebase.py +139 -0
  244. PYME/Acquire/acquiremainframe.py +716 -0
  245. PYME/Acquire/acquirewx.py +61 -0
  246. PYME/Acquire/acquisition_base.py +148 -0
  247. PYME/Acquire/actions.py +209 -0
  248. PYME/Acquire/autofocus.py +54 -0
  249. PYME/Acquire/eventLog.py +95 -0
  250. PYME/Acquire/event_loop.py +119 -0
  251. PYME/Acquire/frameWrangler.py +530 -0
  252. PYME/Acquire/htsms/__init__.py +8 -0
  253. PYME/Acquire/htsms/rule_ui.py +970 -0
  254. PYME/Acquire/htsms/rule_ui_v2.py +573 -0
  255. PYME/Acquire/htsms/tweeter.py +222 -0
  256. PYME/Acquire/microscope.py +1050 -0
  257. PYME/Acquire/positionTracker.py +181 -0
  258. PYME/Acquire/protocol.py +299 -0
  259. PYME/Acquire/protocol_acquisition.py +404 -0
  260. PYME/Acquire/sampleInformation.py +591 -0
  261. PYME/Acquire/sampleInformationDjangoDirect.py +446 -0
  262. PYME/Acquire/setup.py +52 -0
  263. PYME/Acquire/stackSettings.py +295 -0
  264. PYME/Acquire/stage_leveling.py +285 -0
  265. PYME/Acquire/ui/AnalysisSettingsUI.py +184 -0
  266. PYME/Acquire/ui/HDFSpoolFrame.py +584 -0
  267. PYME/Acquire/ui/__init__.py +0 -0
  268. PYME/Acquire/ui/actionUI.py +892 -0
  269. PYME/Acquire/ui/focus_lock_gui.py +149 -0
  270. PYME/Acquire/ui/intensity_trace.py +143 -0
  271. PYME/Acquire/ui/intsliders.py +222 -0
  272. PYME/Acquire/ui/lasersliders.py +329 -0
  273. PYME/Acquire/ui/mpd_picosecond_delay_panel.py +69 -0
  274. PYME/Acquire/ui/multiview_select.py +77 -0
  275. PYME/Acquire/ui/positionUI.py +519 -0
  276. PYME/Acquire/ui/preflight.py +58 -0
  277. PYME/Acquire/ui/scanner_panel.py +41 -0
  278. PYME/Acquire/ui/selectCameraPanel.py +46 -0
  279. PYME/Acquire/ui/seqdialog.py +501 -0
  280. PYME/Acquire/ui/splashScreen.py +175 -0
  281. PYME/Acquire/ui/spool_panel.py +830 -0
  282. PYME/Acquire/ui/tile_panel.py +556 -0
  283. PYME/Acquire/ui/tilesettingsui.py +91 -0
  284. PYME/Acquire/ui/voxelSizeDialog.py +149 -0
  285. PYME/Acquire/webui/__init__.py +36 -0
  286. PYME/Acquire/webui/ipy.py +361 -0
  287. PYME/Acquire/webui/static/css/pyme-bootstrap.css +9908 -0
  288. PYME/Acquire/webui/static/css/pymeacquire.css +85 -0
  289. PYME/Acquire/webui/static/js/pymeacquire.js +375 -0
  290. PYME/Acquire/webui/static/js/pzf.js +95 -0
  291. PYME/Acquire/webui/templates/PYMEAcquire.html +232 -0
  292. PYME/Acquire/webui/templates/login.html +84 -0
  293. PYME/Acquire/webui/templates/xtermpage.html +106 -0
  294. PYME/Acquire/xyztc.py +418 -0
  295. PYME/Acquire/zScanner.py +287 -0
  296. PYME/Analysis/BleachProfile/__init__.py +26 -0
  297. PYME/Analysis/BleachProfile/deMod.py +91 -0
  298. PYME/Analysis/BleachProfile/fitRecover.py +90 -0
  299. PYME/Analysis/BleachProfile/intensProf.py +519 -0
  300. PYME/Analysis/BleachProfile/kinModels.py +507 -0
  301. PYME/Analysis/BleachProfile/rawIntensity.py +227 -0
  302. PYME/Analysis/BleachProfile/rollins.py +555 -0
  303. PYME/Analysis/Colocalisation/__init__.py +27 -0
  304. PYME/Analysis/Colocalisation/colocScaleDep.py +126 -0
  305. PYME/Analysis/Colocalisation/correlationCoeffs.py +198 -0
  306. PYME/Analysis/Colocalisation/distColoc.py +110 -0
  307. PYME/Analysis/Colocalisation/edtColoc.py +191 -0
  308. PYME/Analysis/MetaData.py +278 -0
  309. PYME/Analysis/PSFEst/__init__.py +27 -0
  310. PYME/Analysis/PSFEst/dec.py +283 -0
  311. PYME/Analysis/PSFEst/extractImages.py +316 -0
  312. PYME/Analysis/PSFEst/fit_psf_zernikes.py +194 -0
  313. PYME/Analysis/PSFEst/psfQuality.py +225 -0
  314. PYME/Analysis/PSFGen/__init__.py +40 -0
  315. PYME/Analysis/PSFGen/fourier.py +138 -0
  316. PYME/Analysis/PSFGen/fourierHNA.py +1108 -0
  317. PYME/Analysis/PSFGen/fourierHNA2.py +979 -0
  318. PYME/Analysis/PSFGen/genCRBcurves.py +185 -0
  319. PYME/Analysis/PSFGen/nijboer_zernike.py +79 -0
  320. PYME/Analysis/PSFGen/ps_app.cp313-win_amd64.dll.a +0 -0
  321. PYME/Analysis/PSFGen/ps_app.cp313-win_amd64.pyd +0 -0
  322. PYME/Analysis/PSFGen/test_ps_app.py +24 -0
  323. PYME/Analysis/Tracking/__init__.py +3 -0
  324. PYME/Analysis/Tracking/msd.py +57 -0
  325. PYME/Analysis/Tracking/trackUtils.py +528 -0
  326. PYME/Analysis/Tracking/tracking.py +152 -0
  327. PYME/Analysis/__init__.py +30 -0
  328. PYME/Analysis/_fithelpers.py +161 -0
  329. PYME/Analysis/angleFilter.py +287 -0
  330. PYME/Analysis/annealThresh.py +157 -0
  331. PYME/Analysis/autoencoder_classifier.py +45 -0
  332. PYME/Analysis/binAvg.py +144 -0
  333. PYME/Analysis/composite.py +183 -0
  334. PYME/Analysis/cramerRao.py +259 -0
  335. PYME/Analysis/deTile.py +441 -0
  336. PYME/Analysis/density_filter.py +45 -0
  337. PYME/Analysis/distributed_pyramid.py +426 -0
  338. PYME/Analysis/fiducial_matching.py +220 -0
  339. PYME/Analysis/gen_sCMOS_maps.py +355 -0
  340. PYME/Analysis/graphing_filters.py +311 -0
  341. PYME/Analysis/implicitFilter.py +359 -0
  342. PYME/Analysis/keep_pairs.py +69 -0
  343. PYME/Analysis/optic_flow.py +108 -0
  344. PYME/Analysis/piecewise.py +36 -0
  345. PYME/Analysis/piecewiseMapping.py +304 -0
  346. PYME/Analysis/piezo_movement_correction.py +153 -0
  347. PYME/Analysis/points/DeClump/__init__.py +78 -0
  348. PYME/Analysis/points/DeClump/deClump.cp313-win_amd64.dll.a +0 -0
  349. PYME/Analysis/points/DeClump/deClump.cp313-win_amd64.pyd +0 -0
  350. PYME/Analysis/points/DeClump/deClumpGUI.py +87 -0
  351. PYME/Analysis/points/DeClump/pyDeClump.py +284 -0
  352. PYME/Analysis/points/DeClump/testClump.py +40 -0
  353. PYME/Analysis/points/DistHist/__init__.py +25 -0
  354. PYME/Analysis/points/DistHist/distHist.cp313-win_amd64.dll.a +0 -0
  355. PYME/Analysis/points/DistHist/distHist.cp313-win_amd64.pyd +0 -0
  356. PYME/Analysis/points/DistHist/distHistThreaded.py +71 -0
  357. PYME/Analysis/points/DistHist/setup.py +54 -0
  358. PYME/Analysis/points/EdgeDB/__init__.py +24 -0
  359. PYME/Analysis/points/EdgeDB/edgeDB.cp313-win_amd64.dll.a +0 -0
  360. PYME/Analysis/points/EdgeDB/edgeDB.cp313-win_amd64.pyd +0 -0
  361. PYME/Analysis/points/EdgeDB/edgeTest.py +66 -0
  362. PYME/Analysis/points/EdgeDB/edges.py +102 -0
  363. PYME/Analysis/points/EdgeDB/segment.py +75 -0
  364. PYME/Analysis/points/EdgeDB/setup.py +54 -0
  365. PYME/Analysis/points/QuadTree/QTrend.py +232 -0
  366. PYME/Analysis/points/QuadTree/__init__.py +25 -0
  367. PYME/Analysis/points/QuadTree/pointQT.py +227 -0
  368. PYME/Analysis/points/QuadTree/pointQTF.py +254 -0
  369. PYME/Analysis/points/QuadTree/qtUtils.py +36 -0
  370. PYME/Analysis/points/QuadTree/rendQT.py +118 -0
  371. PYME/Analysis/points/SoftRend/__init__.py +24 -0
  372. PYME/Analysis/points/SoftRend/setup.py +61 -0
  373. PYME/Analysis/points/SoftRend/testTetrahedra.py +41 -0
  374. PYME/Analysis/points/SoftRend/triRend.cp313-win_amd64.dll.a +0 -0
  375. PYME/Analysis/points/SoftRend/triRend.cp313-win_amd64.pyd +0 -0
  376. PYME/Analysis/points/__init__.py +3 -0
  377. PYME/Analysis/points/arcfit/__init__.py +1 -0
  378. PYME/Analysis/points/arcfit/arcmf.cp313-win_amd64.dll.a +0 -0
  379. PYME/Analysis/points/arcfit/arcmf.cp313-win_amd64.pyd +0 -0
  380. PYME/Analysis/points/arcfit/setup.py +51 -0
  381. PYME/Analysis/points/astigmatism/__init__.py +0 -0
  382. PYME/Analysis/points/astigmatism/astigTools.py +338 -0
  383. PYME/Analysis/points/astigmatism/astiglookup.cp313-win_amd64.dll.a +0 -0
  384. PYME/Analysis/points/astigmatism/astiglookup.cp313-win_amd64.pyd +0 -0
  385. PYME/Analysis/points/astigmatism/setup.py +54 -0
  386. PYME/Analysis/points/cluster_morphology.py +199 -0
  387. PYME/Analysis/points/coordinate_tools.py +278 -0
  388. PYME/Analysis/points/features/__init__.py +0 -0
  389. PYME/Analysis/points/features/metal.py +46 -0
  390. PYME/Analysis/points/features/shaders/vect_feat_3d.metal +49 -0
  391. PYME/Analysis/points/fiducials.py +142 -0
  392. PYME/Analysis/points/gen3DTriangs.py +796 -0
  393. PYME/Analysis/points/moments.py +143 -0
  394. PYME/Analysis/points/multiview.py +458 -0
  395. PYME/Analysis/points/objectMeasure.py +206 -0
  396. PYME/Analysis/points/qpaint.py +97 -0
  397. PYME/Analysis/points/rings.py +372 -0
  398. PYME/Analysis/points/ripleys.py +427 -0
  399. PYME/Analysis/points/segmentLL.py +134 -0
  400. PYME/Analysis/points/setup.py +56 -0
  401. PYME/Analysis/points/spherical_harmonics.py +909 -0
  402. PYME/Analysis/points/surfit.py +829 -0
  403. PYME/Analysis/points/tCluster.py +75 -0
  404. PYME/Analysis/points/traveling_salesperson/__init__.py +0 -0
  405. PYME/Analysis/points/traveling_salesperson/queue_opt.py +117 -0
  406. PYME/Analysis/points/traveling_salesperson/sectioned_two_opt.py +327 -0
  407. PYME/Analysis/points/traveling_salesperson/setup.py +40 -0
  408. PYME/Analysis/points/traveling_salesperson/sort.py +78 -0
  409. PYME/Analysis/points/traveling_salesperson/two_opt.py +189 -0
  410. PYME/Analysis/points/traveling_salesperson/two_opt_utils.cp313-win_amd64.dll.a +0 -0
  411. PYME/Analysis/points/traveling_salesperson/two_opt_utils.cp313-win_amd64.pyd +0 -0
  412. PYME/Analysis/points/traveling_salesperson/two_opt_utils.pyx +41 -0
  413. PYME/Analysis/points/twoColour.py +572 -0
  414. PYME/Analysis/points/twoColourPlot.py +107 -0
  415. PYME/Analysis/processLogger.py +129 -0
  416. PYME/Analysis/profile_extraction.py +72 -0
  417. PYME/Analysis/setup.py +60 -0
  418. PYME/Analysis/splitting.py +372 -0
  419. PYME/Analysis/svmSegment.py +214 -0
  420. PYME/Analysis/thresholding.py +192 -0
  421. PYME/Analysis/tile_pyramid.py +938 -0
  422. PYME/Analysis/widefieldify.py +54 -0
  423. PYME/DSView/DisplayOptionsPanel.py +503 -0
  424. PYME/DSView/LUT/__init__.py +33 -0
  425. PYME/DSView/LUT/lut.cp313-win_amd64.dll.a +0 -0
  426. PYME/DSView/LUT/lut.cp313-win_amd64.pyd +0 -0
  427. PYME/DSView/LUT/setup.py +54 -0
  428. PYME/DSView/OpenSequenceDialog.py +83 -0
  429. PYME/DSView/OverlaysPanel.py +111 -0
  430. PYME/DSView/__init__.py +32 -0
  431. PYME/DSView/arrayViewPanel.py +1035 -0
  432. PYME/DSView/displayOptions.py +453 -0
  433. PYME/DSView/displaySettingsPanel.py +271 -0
  434. PYME/DSView/dsviewer.py +542 -0
  435. PYME/DSView/eventLogViewer.py +805 -0
  436. PYME/DSView/fitInfo.py +486 -0
  437. PYME/DSView/htmlServe.py +72 -0
  438. PYME/DSView/logparser.py +100 -0
  439. PYME/DSView/modules/LMAnalysis.py +1053 -0
  440. PYME/DSView/modules/LMDisplay.py +194 -0
  441. PYME/DSView/modules/__init__.py +162 -0
  442. PYME/DSView/modules/_base.py +39 -0
  443. PYME/DSView/modules/annotation.py +725 -0
  444. PYME/DSView/modules/arrayView.py +71 -0
  445. PYME/DSView/modules/blobFinding.py +455 -0
  446. PYME/DSView/modules/blobMeasure.py +1093 -0
  447. PYME/DSView/modules/camera_maps.py +38 -0
  448. PYME/DSView/modules/coloc.py +414 -0
  449. PYME/DSView/modules/composite.py +715 -0
  450. PYME/DSView/modules/convnet.py +24 -0
  451. PYME/DSView/modules/cropping.py +133 -0
  452. PYME/DSView/modules/dark_and_flatfield.py +31 -0
  453. PYME/DSView/modules/deconvolution.py +499 -0
  454. PYME/DSView/modules/eventView.py +80 -0
  455. PYME/DSView/modules/extractBlobs.py +46 -0
  456. PYME/DSView/modules/fastGraphPanel.py +85 -0
  457. PYME/DSView/modules/filtering.py +335 -0
  458. PYME/DSView/modules/flowView.py +268 -0
  459. PYME/DSView/modules/fourierRingCorrelation.py +172 -0
  460. PYME/DSView/modules/gl_image_view.py +12 -0
  461. PYME/DSView/modules/graphViewPanel.py +272 -0
  462. PYME/DSView/modules/measure/__init__.py +1 -0
  463. PYME/DSView/modules/measure/filterPan.py +239 -0
  464. PYME/DSView/modules/metadataView.py +28 -0
  465. PYME/DSView/modules/multithreshold.py +98 -0
  466. PYME/DSView/modules/neuroglancer.py +129 -0
  467. PYME/DSView/modules/object_tagging.py +157 -0
  468. PYME/DSView/modules/particleTracking.py +463 -0
  469. PYME/DSView/modules/playback.py +256 -0
  470. PYME/DSView/modules/prebleachExtraction.py +75 -0
  471. PYME/DSView/modules/profileFitting.py +137 -0
  472. PYME/DSView/modules/profilePlotting.py +408 -0
  473. PYME/DSView/modules/projections.py +48 -0
  474. PYME/DSView/modules/psfExtraction.py +570 -0
  475. PYME/DSView/modules/psfGeneration.py +138 -0
  476. PYME/DSView/modules/psfTools.py +661 -0
  477. PYME/DSView/modules/pupilTools.py +204 -0
  478. PYME/DSView/modules/pupilView.py +139 -0
  479. PYME/DSView/modules/recipes.py +266 -0
  480. PYME/DSView/modules/redimension.py +75 -0
  481. PYME/DSView/modules/segmentation.py +192 -0
  482. PYME/DSView/modules/sheetView.py +24 -0
  483. PYME/DSView/modules/shell.py +39 -0
  484. PYME/DSView/modules/shiftfield_estimation.py +433 -0
  485. PYME/DSView/modules/sparkprepare.py +94 -0
  486. PYME/DSView/modules/splitter.py +148 -0
  487. PYME/DSView/modules/synchronise.py +64 -0
  488. PYME/DSView/modules/templates/astigCal.html +42 -0
  489. PYME/DSView/modules/templates/measureView.html +69 -0
  490. PYME/DSView/modules/templates/measureView2.html +48 -0
  491. PYME/DSView/modules/templates/measureView3.html +98 -0
  492. PYME/DSView/modules/templates/trackView.html +139 -0
  493. PYME/DSView/modules/templates/tracksOverview.html +21 -0
  494. PYME/DSView/modules/tiling.py +147 -0
  495. PYME/DSView/modules/unmixing.py +148 -0
  496. PYME/DSView/modules/vis3D.py +320 -0
  497. PYME/DSView/modules/visgui.py +163 -0
  498. PYME/DSView/modules/webview.py +14 -0
  499. PYME/DSView/overlays.py +295 -0
  500. PYME/DSView/scrolledImagePanel.py +188 -0
  501. PYME/DSView/setup.py +53 -0
  502. PYME/DSView/splashScreen.py +158 -0
  503. PYME/DSView/voxSizeDialog.py +84 -0
  504. PYME/Deconv/__init__.py +35 -0
  505. PYME/Deconv/beadGen.py +55 -0
  506. PYME/Deconv/dec.py +659 -0
  507. PYME/Deconv/decTask.py +65 -0
  508. PYME/Deconv/decThread.py +113 -0
  509. PYME/Deconv/dec_test.py +47 -0
  510. PYME/Deconv/deconvDialogs.py +417 -0
  511. PYME/Deconv/fftwWisdom.py +62 -0
  512. PYME/Deconv/richardsonLucy.py +141 -0
  513. PYME/Deconv/richardsonLucyMV.py +151 -0
  514. PYME/Deconv/richardsonLucyMVM.py +218 -0
  515. PYME/Deconv/test_block_dec.py +46 -0
  516. PYME/Deconv/tq_block_dec.py +331 -0
  517. PYME/Deconv/wiener.py +163 -0
  518. PYME/IO/DataSources/AlignDataSource.py +91 -0
  519. PYME/IO/DataSources/ArrayDataSource.py +260 -0
  520. PYME/IO/DataSources/BGSDataSource.py +353 -0
  521. PYME/IO/DataSources/BaseDataSource.py +457 -0
  522. PYME/IO/DataSources/BioformatsDataSource.py +178 -0
  523. PYME/IO/DataSources/BufferedDataSource.py +99 -0
  524. PYME/IO/DataSources/ClusterPZFDataSource.py +124 -0
  525. PYME/IO/DataSources/ConcatenatedDataSource.py +56 -0
  526. PYME/IO/DataSources/CropDataSource.py +243 -0
  527. PYME/IO/DataSources/DcimgDataSource.py +54 -0
  528. PYME/IO/DataSources/ElectronsPerSecondDataSource.py +61 -0
  529. PYME/IO/DataSources/FlatFieldDataSource.py +77 -0
  530. PYME/IO/DataSources/HDFDataSource.py +160 -0
  531. PYME/IO/DataSources/HTTPDataSource.py +80 -0
  532. PYME/IO/DataSources/ImageSeriesDataSource.py +123 -0
  533. PYME/IO/DataSources/MultiviewDataSource.py +99 -0
  534. PYME/IO/DataSources/OBFDataSource.py +67 -0
  535. PYME/IO/DataSources/RandomDataSource.py +23 -0
  536. PYME/IO/DataSources/SupertileDatasource.py +148 -0
  537. PYME/IO/DataSources/TQDataSource.py +41 -0
  538. PYME/IO/DataSources/TiffDataSource.py +193 -0
  539. PYME/IO/DataSources/TileDataSource.py +91 -0
  540. PYME/IO/DataSources/UnsplitDataSource.py +92 -0
  541. PYME/IO/DataSources/__init__.py +59 -0
  542. PYME/IO/FileUtils/IJLut.py +43 -0
  543. PYME/IO/FileUtils/RawToHdf5.py +105 -0
  544. PYME/IO/FileUtils/SPAD.py +54 -0
  545. PYME/IO/FileUtils/TiffSeqToHdf5.py +87 -0
  546. PYME/IO/FileUtils/__init__.py +24 -0
  547. PYME/IO/FileUtils/compHdf.py +39 -0
  548. PYME/IO/FileUtils/fileID.py +246 -0
  549. PYME/IO/FileUtils/fnlGen.py +40 -0
  550. PYME/IO/FileUtils/freeSpace.py +59 -0
  551. PYME/IO/FileUtils/h5-thumbnailer.py +85 -0
  552. PYME/IO/FileUtils/h5ExFrames.py +98 -0
  553. PYME/IO/FileUtils/h5ToTiffSeries.py +50 -0
  554. PYME/IO/FileUtils/h5r-thumbnailer.py +118 -0
  555. PYME/IO/FileUtils/h5rFormatDef.py +99 -0
  556. PYME/IO/FileUtils/h5rToTxt.py +77 -0
  557. PYME/IO/FileUtils/nameUtils.py +300 -0
  558. PYME/IO/FileUtils/obf_support.py +538 -0
  559. PYME/IO/FileUtils/ply.py +147 -0
  560. PYME/IO/FileUtils/readSpeckle.py +78 -0
  561. PYME/IO/FileUtils/readTiff.py +64 -0
  562. PYME/IO/FileUtils/saveTiffStack.py +137 -0
  563. PYME/IO/FileUtils/setup.py +36 -0
  564. PYME/IO/FileUtils/sf-thumbnailer.py +76 -0
  565. PYME/IO/FileUtils/stl.py +44 -0
  566. PYME/IO/FileUtils/thumbnailDatabase.py +104 -0
  567. PYME/IO/HTTPSpooler_v2.py +141 -0
  568. PYME/IO/MetaDataHandler.py +1072 -0
  569. PYME/IO/PZFFormat.py +375 -0
  570. PYME/IO/Spooler.py +279 -0
  571. PYME/IO/__init__.py +12 -0
  572. PYME/IO/acquisition_backends.py +353 -0
  573. PYME/IO/buffer_helpers.cp313-win_amd64.dll.a +0 -0
  574. PYME/IO/buffer_helpers.cp313-win_amd64.pyd +0 -0
  575. PYME/IO/buffer_helpers.pyx +190 -0
  576. PYME/IO/buffers.py +291 -0
  577. PYME/IO/clusterDuplication.py +204 -0
  578. PYME/IO/clusterExport.py +152 -0
  579. PYME/IO/clusterGlob.py +108 -0
  580. PYME/IO/clusterIO.py +1076 -0
  581. PYME/IO/clusterListing.py +232 -0
  582. PYME/IO/clusterResults.py +206 -0
  583. PYME/IO/clusterUpload.py +49 -0
  584. PYME/IO/cluster_directory.py +419 -0
  585. PYME/IO/cluster_streaming.py +216 -0
  586. PYME/IO/compatibility.py +12 -0
  587. PYME/IO/countdir/__init__.py +5 -0
  588. PYME/IO/countdir/setup.py +58 -0
  589. PYME/IO/csv_flavours.py +251 -0
  590. PYME/IO/dataExporter.py +470 -0
  591. PYME/IO/dataWrap.py +108 -0
  592. PYME/IO/dcimg.py +167 -0
  593. PYME/IO/events.py +161 -0
  594. PYME/IO/h5File.py +148 -0
  595. PYME/IO/h5rFile.py +323 -0
  596. PYME/IO/image.py +1447 -0
  597. PYME/IO/load_psf.py +26 -0
  598. PYME/IO/pyme_h5ls.py +58 -0
  599. PYME/IO/ragged.py +138 -0
  600. PYME/IO/rgb_image.py +94 -0
  601. PYME/IO/tabular.py +1338 -0
  602. PYME/IO/testClusterSpooling.py +199 -0
  603. PYME/IO/unifiedIO.py +301 -0
  604. PYME/LMVis/Extras/QPobjectSegment.py +220 -0
  605. PYME/LMVis/Extras/__init__.py +55 -0
  606. PYME/LMVis/Extras/animation.py +359 -0
  607. PYME/LMVis/Extras/annotation.py +78 -0
  608. PYME/LMVis/Extras/clusterAnalysis.py +460 -0
  609. PYME/LMVis/Extras/dockedPanel.py +69 -0
  610. PYME/LMVis/Extras/extra_layers.py +373 -0
  611. PYME/LMVis/Extras/fiducial.py +230 -0
  612. PYME/LMVis/Extras/flagZMotionArtifacts.py +60 -0
  613. PYME/LMVis/Extras/fusionUtils.py +9 -0
  614. PYME/LMVis/Extras/multiColourAnalysis.py +103 -0
  615. PYME/LMVis/Extras/multiviewMapping.py +489 -0
  616. PYME/LMVis/Extras/objectMeasurements.py +246 -0
  617. PYME/LMVis/Extras/particleTracking.py +272 -0
  618. PYME/LMVis/Extras/perFrameVariable.py +77 -0
  619. PYME/LMVis/Extras/photophysics.py +72 -0
  620. PYME/LMVis/Extras/pointSetGeneration.py +232 -0
  621. PYME/LMVis/Extras/pointwiseColoc.py +54 -0
  622. PYME/LMVis/Extras/saved_views.py +125 -0
  623. PYME/LMVis/Extras/scaleBox.py +115 -0
  624. PYME/LMVis/Extras/sequentialSpecies.py +125 -0
  625. PYME/LMVis/Extras/setBGImage.py +74 -0
  626. PYME/LMVis/Extras/shiftmapGenerator.py +138 -0
  627. PYME/LMVis/Extras/showShortcuts.py +69 -0
  628. PYME/LMVis/Extras/snapshot.py +135 -0
  629. PYME/LMVis/Extras/spherical_harmonics.py +98 -0
  630. PYME/LMVis/Extras/subsets.py +15 -0
  631. PYME/LMVis/Extras/surface_fitting.py +52 -0
  632. PYME/LMVis/Extras/temperaturePlot.py +53 -0
  633. PYME/LMVis/Extras/vibration.py +112 -0
  634. PYME/LMVis/VisGUI.py +506 -0
  635. PYME/LMVis/__init__.py +39 -0
  636. PYME/LMVis/colourFilterGUI.py +77 -0
  637. PYME/LMVis/colourPanel.py +491 -0
  638. PYME/LMVis/displayPane.py +462 -0
  639. PYME/LMVis/dyeRatios.py +116 -0
  640. PYME/LMVis/genImageDialog.py +298 -0
  641. PYME/LMVis/gl_offScreenHandler.py +134 -0
  642. PYME/LMVis/gl_render.py +1302 -0
  643. PYME/LMVis/gl_render3D.py +1453 -0
  644. PYME/LMVis/gl_render3D_shaders.py +1213 -0
  645. PYME/LMVis/glcanvas_core.py +1157 -0
  646. PYME/LMVis/imageView.py +752 -0
  647. PYME/LMVis/imageView2.py +372 -0
  648. PYME/LMVis/importTextDialog.py +342 -0
  649. PYME/LMVis/layer_panel.py +231 -0
  650. PYME/LMVis/layers/AxesOverlayLayer.py +126 -0
  651. PYME/LMVis/layers/LUTOverlayLayer.py +346 -0
  652. PYME/LMVis/layers/OverlayLayer.py +46 -0
  653. PYME/LMVis/layers/ScaleBarOverlayLayer.py +97 -0
  654. PYME/LMVis/layers/ScaleBoxOverlayLayer.py +181 -0
  655. PYME/LMVis/layers/SelectionOverlayLayer.py +124 -0
  656. PYME/LMVis/layers/__init__.py +53 -0
  657. PYME/LMVis/layers/base.py +319 -0
  658. PYME/LMVis/layers/image_layer.py +363 -0
  659. PYME/LMVis/layers/labels.py +186 -0
  660. PYME/LMVis/layers/layer_defaults.py +97 -0
  661. PYME/LMVis/layers/mesh.py +378 -0
  662. PYME/LMVis/layers/octree.py +194 -0
  663. PYME/LMVis/layers/pointcloud.py +372 -0
  664. PYME/LMVis/layers/quiver.py +271 -0
  665. PYME/LMVis/layers/text.py +250 -0
  666. PYME/LMVis/layers/tracks.py +309 -0
  667. PYME/LMVis/mv_math.py +78 -0
  668. PYME/LMVis/objectDarkMeasure.py +120 -0
  669. PYME/LMVis/pipeline.py +1227 -0
  670. PYME/LMVis/pipelineView.py +115 -0
  671. PYME/LMVis/pointSettingsPanel.py +135 -0
  672. PYME/LMVis/progGraph.py +59 -0
  673. PYME/LMVis/quadTreeSettings.py +90 -0
  674. PYME/LMVis/rendGauss.py +158 -0
  675. PYME/LMVis/renderers.py +576 -0
  676. PYME/LMVis/sessionpaths.py +136 -0
  677. PYME/LMVis/setup.py +39 -0
  678. PYME/LMVis/setup_exe.py +71 -0
  679. PYME/LMVis/shader_programs/DefaultShaderProgram.py +149 -0
  680. PYME/LMVis/shader_programs/GLProgram.py +119 -0
  681. PYME/LMVis/shader_programs/GouraudShaderProgram.py +157 -0
  682. PYME/LMVis/shader_programs/PointSpriteShaderProgram.py +163 -0
  683. PYME/LMVis/shader_programs/ShaderProgramFactory.py +54 -0
  684. PYME/LMVis/shader_programs/TesselShaderProgram.py +47 -0
  685. PYME/LMVis/shader_programs/WireFrameShaderProgram.py +50 -0
  686. PYME/LMVis/shader_programs/__init__.py +20 -0
  687. PYME/LMVis/shader_programs/oit_compositor.py +23 -0
  688. PYME/LMVis/shader_programs/shader_loader.py +84 -0
  689. PYME/LMVis/shader_programs/shader_program.py +168 -0
  690. PYME/LMVis/shader_programs/shaders/bigflatpoints_fs.glsl +16 -0
  691. PYME/LMVis/shader_programs/shaders/bigpoints_gs.glsl +40 -0
  692. PYME/LMVis/shader_programs/shaders/bigpointsprites_fs.glsl +20 -0
  693. PYME/LMVis/shader_programs/shaders/bigspheres_fs.glsl +53 -0
  694. PYME/LMVis/shader_programs/shaders/compose_fs.glsl +41 -0
  695. PYME/LMVis/shader_programs/shaders/compose_vs.glsl +25 -0
  696. PYME/LMVis/shader_programs/shaders/default_fs.glsl +27 -0
  697. PYME/LMVis/shader_programs/shaders/default_vs.glsl +88 -0
  698. PYME/LMVis/shader_programs/shaders/flatpoints_fs.glsl +27 -0
  699. PYME/LMVis/shader_programs/shaders/gouraud_flatpoints_fs.glsl +30 -0
  700. PYME/LMVis/shader_programs/shaders/gouraud_fs.glsl +26 -0
  701. PYME/LMVis/shader_programs/shaders/gouraud_oit_fs.glsl +68 -0
  702. PYME/LMVis/shader_programs/shaders/gouraud_vs.glsl +135 -0
  703. PYME/LMVis/shader_programs/shaders/image_fs.glsl +60 -0
  704. PYME/LMVis/shader_programs/shaders/image_vs.glsl +79 -0
  705. PYME/LMVis/shader_programs/shaders/phong_fs.glsl +43 -0
  706. PYME/LMVis/shader_programs/shaders/phong_vs.glsl +45 -0
  707. PYME/LMVis/shader_programs/shaders/pointsprites_fs.glsl +33 -0
  708. PYME/LMVis/shader_programs/shaders/pointsprites_vs.glsl +77 -0
  709. PYME/LMVis/shader_programs/shaders/spheres_fs.glsl +102 -0
  710. PYME/LMVis/shader_programs/shaders/tessel_fs.glsl +23 -0
  711. PYME/LMVis/shader_programs/shaders/tessel_vs.glsl +37 -0
  712. PYME/LMVis/shader_programs/shaders/text_fs.glsl +42 -0
  713. PYME/LMVis/shader_programs/shaders/text_vs.glsl +84 -0
  714. PYME/LMVis/shader_programs/shaders/widelines_fs.glsl +19 -0
  715. PYME/LMVis/shader_programs/shaders/widelines_gs.glsl +56 -0
  716. PYME/LMVis/shader_programs/shaders/widelines_vs.glsl +51 -0
  717. PYME/LMVis/statusLog.py +57 -0
  718. PYME/LMVis/triBlobs.py +142 -0
  719. PYME/LMVis/view_clipping_pane.py +429 -0
  720. PYME/LMVis/views.py +275 -0
  721. PYME/LMVis/visCore.py +1005 -0
  722. PYME/LMVis/visHelpers.py +880 -0
  723. PYME/LMVis/visHelpersMin.py +230 -0
  724. PYME/LMVis/workspaceTree.py +238 -0
  725. PYME/__init__.py +22 -0
  726. PYME/cluster/HTTPDataServer.py +1063 -0
  727. PYME/cluster/HTTPRulePusher.py +382 -0
  728. PYME/cluster/HTTPTaskPusher.py +377 -0
  729. PYME/cluster/PYMERuleNodeServer.py +192 -0
  730. PYME/cluster/PYMERuleServer.py +109 -0
  731. PYME/cluster/__init__.py +0 -0
  732. PYME/cluster/clusterUI/accounts/__init__.py +0 -0
  733. PYME/cluster/clusterUI/accounts/admin.py +85 -0
  734. PYME/cluster/clusterUI/accounts/forms.py +8 -0
  735. PYME/cluster/clusterUI/accounts/migrations/0001_initial.py +31 -0
  736. PYME/cluster/clusterUI/accounts/migrations/__init__.py +0 -0
  737. PYME/cluster/clusterUI/accounts/models.py +44 -0
  738. PYME/cluster/clusterUI/accounts/templates/accounts/user_form.html +13 -0
  739. PYME/cluster/clusterUI/accounts/templates/registration/initial_complete.html +6 -0
  740. PYME/cluster/clusterUI/accounts/templates/registration/initial_confirm.html +13 -0
  741. PYME/cluster/clusterUI/accounts/templates/registration/initial_done.html +7 -0
  742. PYME/cluster/clusterUI/accounts/templates/registration/verification.html +2 -0
  743. PYME/cluster/clusterUI/accounts/templates/registration/verification_subject.txt +1 -0
  744. PYME/cluster/clusterUI/accounts/urls.py +19 -0
  745. PYME/cluster/clusterUI/accounts/views.py +36 -0
  746. PYME/cluster/clusterUI/clusterUI/__init__.py +0 -0
  747. PYME/cluster/clusterUI/clusterUI/settings.py +147 -0
  748. PYME/cluster/clusterUI/clusterUI/urls.py +31 -0
  749. PYME/cluster/clusterUI/clusterUI/wsgi.py +16 -0
  750. PYME/cluster/clusterUI/clusterbrowser/__init__.py +0 -0
  751. PYME/cluster/clusterUI/clusterbrowser/admin.py +3 -0
  752. PYME/cluster/clusterUI/clusterbrowser/apps.py +7 -0
  753. PYME/cluster/clusterUI/clusterbrowser/migrations/__init__.py +0 -0
  754. PYME/cluster/clusterUI/clusterbrowser/models.py +5 -0
  755. PYME/cluster/clusterUI/clusterbrowser/templates/base.html +129 -0
  756. PYME/cluster/clusterUI/clusterbrowser/templates/clusterbrowser/dirlisting.html +231 -0
  757. PYME/cluster/clusterUI/clusterbrowser/templates/clusterbrowser/form_new_folder.html +18 -0
  758. PYME/cluster/clusterUI/clusterbrowser/templates/clusterbrowser/form_upload_file.html +17 -0
  759. PYME/cluster/clusterUI/clusterbrowser/templates/clusterbrowser/lightlisting.html +25 -0
  760. PYME/cluster/clusterUI/clusterbrowser/templates/registration/login.html +38 -0
  761. PYME/cluster/clusterUI/clusterbrowser/urls.py +10 -0
  762. PYME/cluster/clusterUI/clusterbrowser/views.py +148 -0
  763. PYME/cluster/clusterUI/clusterstatus/__init__.py +0 -0
  764. PYME/cluster/clusterUI/clusterstatus/admin.py +3 -0
  765. PYME/cluster/clusterUI/clusterstatus/apps.py +7 -0
  766. PYME/cluster/clusterUI/clusterstatus/migrations/__init__.py +0 -0
  767. PYME/cluster/clusterUI/clusterstatus/models.py +5 -0
  768. PYME/cluster/clusterUI/clusterstatus/templates/clusterstatus/load_content.html +29 -0
  769. PYME/cluster/clusterUI/clusterstatus/templates/clusterstatus/queue_info.html +28 -0
  770. PYME/cluster/clusterUI/clusterstatus/templates/clusterstatus/queue_info_content.html +50 -0
  771. PYME/cluster/clusterUI/clusterstatus/templates/clusterstatus/status_dash.html +29 -0
  772. PYME/cluster/clusterUI/clusterstatus/templates/clusterstatus/status_dash_content.html +90 -0
  773. PYME/cluster/clusterUI/clusterstatus/urls.py +9 -0
  774. PYME/cluster/clusterUI/clusterstatus/views.py +69 -0
  775. PYME/cluster/clusterUI/clusterui_tornado.py +117 -0
  776. PYME/cluster/clusterUI/deploy.py +62 -0
  777. PYME/cluster/clusterUI/localization/__init__.py +0 -0
  778. PYME/cluster/clusterUI/localization/admin.py +3 -0
  779. PYME/cluster/clusterUI/localization/apps.py +7 -0
  780. PYME/cluster/clusterUI/localization/migrations/__init__.py +0 -0
  781. PYME/cluster/clusterUI/localization/models.py +5 -0
  782. PYME/cluster/clusterUI/localization/templates/localization/settings_form.html +67 -0
  783. PYME/cluster/clusterUI/localization/urls.py +10 -0
  784. PYME/cluster/clusterUI/localization/views.py +170 -0
  785. PYME/cluster/clusterUI/manage.py +17 -0
  786. PYME/cluster/clusterUI/recipes/__init__.py +0 -0
  787. PYME/cluster/clusterUI/recipes/admin.py +3 -0
  788. PYME/cluster/clusterUI/recipes/migrations/__init__.py +0 -0
  789. PYME/cluster/clusterUI/recipes/models.py +3 -0
  790. PYME/cluster/clusterUI/recipes/templates/recipes/extra_inputs.html +35 -0
  791. PYME/cluster/clusterUI/recipes/templates/recipes/form_recipe.html +82 -0
  792. PYME/cluster/clusterUI/recipes/templates/recipes/input_list.html +7 -0
  793. PYME/cluster/clusterUI/recipes/templates/recipes/recipe_editor.html +28 -0
  794. PYME/cluster/clusterUI/recipes/templates/recipes/recipe_editor_common.html +46 -0
  795. PYME/cluster/clusterUI/recipes/templates/recipes/recipe_editrun.html +93 -0
  796. PYME/cluster/clusterUI/recipes/templates/recipes/recipe_standalone.html +100 -0
  797. PYME/cluster/clusterUI/recipes/templates/recipes/recipe_template.html +109 -0
  798. PYME/cluster/clusterUI/recipes/urls.py +17 -0
  799. PYME/cluster/clusterUI/recipes/views.py +109 -0
  800. PYME/cluster/cluster_of_one.py +204 -0
  801. PYME/cluster/dataserver_wsgi.py +615 -0
  802. PYME/cluster/distribution.py +71 -0
  803. PYME/cluster/rulenodeserver.py +487 -0
  804. PYME/cluster/rules.py +979 -0
  805. PYME/cluster/ruleserver.py +1106 -0
  806. PYME/cluster/status.py +101 -0
  807. PYME/cluster/taskWorkerHTTP.py +522 -0
  808. PYME/cluster/webdav.py +1102 -0
  809. PYME/config.py +659 -0
  810. PYME/contrib/TextCtrlAutoComplete.py +582 -0
  811. PYME/contrib/__init__.py +7 -0
  812. PYME/contrib/aniso/__init__.py +2 -0
  813. PYME/contrib/aniso/aniso.py +268 -0
  814. PYME/contrib/auiFloatBook.py +94 -0
  815. PYME/contrib/congrid.py +127 -0
  816. PYME/contrib/dispatch/__init__.py +19 -0
  817. PYME/contrib/dispatch/dispatcher.py +289 -0
  818. PYME/contrib/gohlke/__init__.py +1 -0
  819. PYME/contrib/gohlke/_tifffile.cp313-win_amd64.dll.a +0 -0
  820. PYME/contrib/gohlke/_tifffile.cp313-win_amd64.pyd +0 -0
  821. PYME/contrib/gohlke/czifile.py +1289 -0
  822. PYME/contrib/gohlke/fcsfiles.py +514 -0
  823. PYME/contrib/gohlke/setup.py +54 -0
  824. PYME/contrib/gohlke/tifffile.py +3095 -0
  825. PYME/contrib/listctrlMixins.py +896 -0
  826. PYME/contrib/lzw.py +838 -0
  827. PYME/contrib/pad/__init__.py +13 -0
  828. PYME/contrib/pad/info_pad.py +18 -0
  829. PYME/contrib/pad/pad.py +670 -0
  830. PYME/contrib/setup.py +38 -0
  831. PYME/contrib/wxPlotPanel.py +137 -0
  832. PYME/experimental/SimReconstruction.py +49 -0
  833. PYME/experimental/__init__.pxd +0 -0
  834. PYME/experimental/__init__.py +4 -0
  835. PYME/experimental/_octree.cp313-win_amd64.dll.a +0 -0
  836. PYME/experimental/_octree.cp313-win_amd64.pyd +0 -0
  837. PYME/experimental/_octree.pyx +477 -0
  838. PYME/experimental/_treap.cp313-win_amd64.dll.a +0 -0
  839. PYME/experimental/_treap.cp313-win_amd64.pyd +0 -0
  840. PYME/experimental/_treap.pyx +267 -0
  841. PYME/experimental/_triangle_mesh.cp313-win_amd64.dll.a +0 -0
  842. PYME/experimental/_triangle_mesh.cp313-win_amd64.pyd +0 -0
  843. PYME/experimental/_triangle_mesh.pxd +149 -0
  844. PYME/experimental/_triangle_mesh.pyx +2787 -0
  845. PYME/experimental/aqavg.py +40 -0
  846. PYME/experimental/dcimgFileChucker.py +375 -0
  847. PYME/experimental/dcimgSpoolShim.py +174 -0
  848. PYME/experimental/dcimg_chuck_test.py +78 -0
  849. PYME/experimental/dual_marching_cubes.py +801 -0
  850. PYME/experimental/dual_marching_cubes_v2.py +645 -0
  851. PYME/experimental/expectationMaximisation.py +298 -0
  852. PYME/experimental/func_octree.cp313-win_amd64.dll.a +0 -0
  853. PYME/experimental/func_octree.cp313-win_amd64.pyd +0 -0
  854. PYME/experimental/func_octree.pyx +381 -0
  855. PYME/experimental/fusionRadial.py +520 -0
  856. PYME/experimental/fusionUtils.py +522 -0
  857. PYME/experimental/isosurface.py +147 -0
  858. PYME/experimental/labview_spooling_hacks.py +48 -0
  859. PYME/experimental/marching_cubes.py +811 -0
  860. PYME/experimental/marching_tetrahedra.py +343 -0
  861. PYME/experimental/modified_marching_cubes.py +1245 -0
  862. PYME/experimental/music.py +25 -0
  863. PYME/experimental/octree.py +188 -0
  864. PYME/experimental/pSpaceMap.py +34 -0
  865. PYME/experimental/pointFitConfoc.py +112 -0
  866. PYME/experimental/scanner_control.py +107 -0
  867. PYME/experimental/setup.py +109 -0
  868. PYME/experimental/spark.py +31 -0
  869. PYME/experimental/tcHist.py +71 -0
  870. PYME/experimental/treap.py +262 -0
  871. PYME/experimental/triangle_mesh.py +2287 -0
  872. PYME/experimental/triangle_mesh_utils.cp313-win_amd64.dll.a +0 -0
  873. PYME/experimental/triangle_mesh_utils.cp313-win_amd64.pyd +0 -0
  874. PYME/experimental/triangle_utils.py +87 -0
  875. PYME/experimental/triangular_mesh.py +2255 -0
  876. PYME/experimental/zMotionArtifactUtils.py +55 -0
  877. PYME/localization/FitFactories/AstigGaussFitFR.py +175 -0
  878. PYME/localization/FitFactories/AstigGaussGPUFitFR.py +326 -0
  879. PYME/localization/FitFactories/BeadConvolvedAstigGaussFit.py +206 -0
  880. PYME/localization/FitFactories/ChecksumFR.py +82 -0
  881. PYME/localization/FitFactories/ChecksumGPUFR.py +213 -0
  882. PYME/localization/FitFactories/ChecksumMultifitSR.py +86 -0
  883. PYME/localization/FitFactories/ConfocCOIR.py +93 -0
  884. PYME/localization/FitFactories/Dumbell3DFitR.py +193 -0
  885. PYME/localization/FitFactories/DumbellFitR.py +163 -0
  886. PYME/localization/FitFactories/FFBase.py +403 -0
  887. PYME/localization/FitFactories/Gauss3DFitR.py +213 -0
  888. PYME/localization/FitFactories/GaussFitConstrR.py +177 -0
  889. PYME/localization/FitFactories/GaussMultifitLinesR.py +351 -0
  890. PYME/localization/FitFactories/GaussMultifitR.py +326 -0
  891. PYME/localization/FitFactories/GaussMultifitSR.py +373 -0
  892. PYME/localization/FitFactories/InterpFitR.py +236 -0
  893. PYME/localization/FitFactories/InterpFitWFR.py +111 -0
  894. PYME/localization/FitFactories/Interpolators/CSInterpolator.py +148 -0
  895. PYME/localization/FitFactories/Interpolators/CubeSInterpolatorP.py +121 -0
  896. PYME/localization/FitFactories/Interpolators/CubicSplineInterpolator.py +69 -0
  897. PYME/localization/FitFactories/Interpolators/LinearInterpolator.py +135 -0
  898. PYME/localization/FitFactories/Interpolators/LinearPInterpolatorP.py +95 -0
  899. PYME/localization/FitFactories/Interpolators/__init__.py +33 -0
  900. PYME/localization/FitFactories/Interpolators/baseInterpolator.py +202 -0
  901. PYME/localization/FitFactories/LatFitCOIR.py +82 -0
  902. PYME/localization/FitFactories/LatGaussFitFR.py +220 -0
  903. PYME/localization/FitFactories/LatObjFindFR.py +85 -0
  904. PYME/localization/FitFactories/LatPSFFitR.py +142 -0
  905. PYME/localization/FitFactories/MultiviewFitInterpNR.py +400 -0
  906. PYME/localization/FitFactories/PRInterpFitQR.py +192 -0
  907. PYME/localization/FitFactories/PRInterpFitR.py +223 -0
  908. PYME/localization/FitFactories/ROIExtractNR.py +93 -0
  909. PYME/localization/FitFactories/SpecGaussFitFR.py +174 -0
  910. PYME/localization/FitFactories/SplitterFitCOIR.py +142 -0
  911. PYME/localization/FitFactories/SplitterFitFNR.py +312 -0
  912. PYME/localization/FitFactories/SplitterFitFusionR.py +318 -0
  913. PYME/localization/FitFactories/SplitterFitInterpBNR.py +357 -0
  914. PYME/localization/FitFactories/SplitterFitInterpNR.py +343 -0
  915. PYME/localization/FitFactories/SplitterFitScavNR.py +352 -0
  916. PYME/localization/FitFactories/SplitterMultifitSR.py +410 -0
  917. PYME/localization/FitFactories/SplitterObjFindR.py +194 -0
  918. PYME/localization/FitFactories/SplitterROIExtractNR.py +91 -0
  919. PYME/localization/FitFactories/SplitterShiftEstFR.py +230 -0
  920. PYME/localization/FitFactories/__init__.py +103 -0
  921. PYME/localization/FitFactories/fitCommon.py +195 -0
  922. PYME/localization/FitFactories/zEstimators/__init__.py +29 -0
  923. PYME/localization/FitFactories/zEstimators/astigEstimator.py +173 -0
  924. PYME/localization/FitFactories/zEstimators/biplaneEstimator.py +209 -0
  925. PYME/localization/FitFactories/zEstimators/genericDualEstimator.py +232 -0
  926. PYME/localization/FitFactories/zEstimators/genericEstimator.py +224 -0
  927. PYME/localization/FitFactories/zEstimators/priEstimator.py +255 -0
  928. PYME/localization/MetaDataEdit.py +543 -0
  929. PYME/localization/Test/30_9_series_A_1.sf +0 -0
  930. PYME/localization/Test/PRI.md +45 -0
  931. PYME/localization/Test/PRI_qr.md +52 -0
  932. PYME/localization/Test/PRI_r.md +52 -0
  933. PYME/localization/Test/__init__.py +22 -0
  934. PYME/localization/Test/astig.md +50 -0
  935. PYME/localization/Test/astigCOI.md +50 -0
  936. PYME/localization/Test/astig_gauss.md +52 -0
  937. PYME/localization/Test/astig_pe.md +50 -0
  938. PYME/localization/Test/astig_splitter.md +66 -0
  939. PYME/localization/Test/astig_splitterCOI.md +67 -0
  940. PYME/localization/Test/astig_splitterQ.md +66 -0
  941. PYME/localization/Test/astig_theory.md +50 -0
  942. PYME/localization/Test/astig_theory.psf +0 -0
  943. PYME/localization/Test/astig_theory.tif +0 -0
  944. PYME/localization/Test/beads1.psf +0 -0
  945. PYME/localization/Test/beads1.tif +0 -0
  946. PYME/localization/Test/biplane_splitter.md +75 -0
  947. PYME/localization/Test/biplane_splitter2.md +103 -0
  948. PYME/localization/Test/biplane_splitter3.md +115 -0
  949. PYME/localization/Test/defoc.md +48 -0
  950. PYME/localization/Test/dumbell_3d.md +52 -0
  951. PYME/localization/Test/fitTestJig.py +172 -0
  952. PYME/localization/Test/fitTestJigSCMOS.py +487 -0
  953. PYME/localization/Test/fitTestJigWC.py +225 -0
  954. PYME/localization/Test/gauss.md +50 -0
  955. PYME/localization/Test/gaussCOI.md +50 -0
  956. PYME/localization/Test/pri_pe.md +50 -0
  957. PYME/localization/Test/pri_theory.md +51 -0
  958. PYME/localization/Test/pri_theory.psf +0 -0
  959. PYME/localization/Test/pri_theory.tif +0 -0
  960. PYME/localization/Test/psf_astig.psf +0 -0
  961. PYME/localization/Test/psf_astig.tif +0 -0
  962. PYME/localization/Test/psf_astig_bg_d.psf +0 -0
  963. PYME/localization/Test/psf_astig_bg_d.tif +0 -0
  964. PYME/localization/Test/psf_astig_pe.psf +0 -0
  965. PYME/localization/Test/psf_astig_pe.tif +0 -0
  966. PYME/localization/Test/psf_decon.psf +0 -0
  967. PYME/localization/Test/psf_decon.tif +0 -0
  968. PYME/localization/Test/psf_decon_pe.psf +0 -0
  969. PYME/localization/Test/psf_decon_pe.tif +0 -0
  970. PYME/localization/Test/psf_guess.psf +0 -0
  971. PYME/localization/Test/splitter.md +63 -0
  972. PYME/localization/Test/splitter_scav.md +63 -0
  973. PYME/localization/Test/test.psf +0 -0
  974. PYME/localization/Test/test.tif +0 -0
  975. PYME/localization/Test/test_decon.psf +0 -0
  976. PYME/localization/Test/test_decon.tif +0 -0
  977. PYME/localization/Test/test_pe.psf +0 -0
  978. PYME/localization/Test/test_pe.tif +0 -0
  979. PYME/localization/Test/wf_theory.psf +0 -0
  980. PYME/localization/Test/wf_theory2.psf +0 -0
  981. PYME/localization/__init__.py +17 -0
  982. PYME/localization/autopsf/__init__.py +1 -0
  983. PYME/localization/autopsf/autopsf.py +486 -0
  984. PYME/localization/autopsf/roifit.py +310 -0
  985. PYME/localization/cInterp/__init__.py +24 -0
  986. PYME/localization/cInterp/cInterp.cp313-win_amd64.dll.a +0 -0
  987. PYME/localization/cInterp/cInterp.cp313-win_amd64.pyd +0 -0
  988. PYME/localization/cInterp/setup.py +54 -0
  989. PYME/localization/cModels/__init__.py +24 -0
  990. PYME/localization/cModels/gauss_app.cp313-win_amd64.dll.a +0 -0
  991. PYME/localization/cModels/gauss_app.cp313-win_amd64.pyd +0 -0
  992. PYME/localization/ofind.py +444 -0
  993. PYME/localization/ofind3d.py +306 -0
  994. PYME/localization/ofind_nofilt.py +128 -0
  995. PYME/localization/ofind_pri.py +478 -0
  996. PYME/localization/ofind_split.py +399 -0
  997. PYME/localization/ofind_xcorr.py +351 -0
  998. PYME/localization/ofind_xcorr_fw.py +441 -0
  999. PYME/localization/remFitBuf.py +657 -0
  1000. PYME/localization/setup.py +56 -0
  1001. PYME/localization/splitting.py +240 -0
  1002. PYME/localization/twist.py +60 -0
  1003. PYME/misc/TiSettings.py +36 -0
  1004. PYME/misc/TiffImagePlugin.py +838 -0
  1005. PYME/misc/VolProj.py +144 -0
  1006. PYME/misc/__init__.py +25 -0
  1007. PYME/misc/aligned_array.py +10 -0
  1008. PYME/misc/aniso.py +29 -0
  1009. PYME/misc/big_sur_fix.py +20 -0
  1010. PYME/misc/check_for_updates.py +139 -0
  1011. PYME/misc/colormaps.py +199 -0
  1012. PYME/misc/colorsys.py +201 -0
  1013. PYME/misc/computerName.py +33 -0
  1014. PYME/misc/coverslipGeometries.py +60 -0
  1015. PYME/misc/cython_numpy_monkey.py +40 -0
  1016. PYME/misc/depGraph.py +406 -0
  1017. PYME/misc/dirSize.py +31 -0
  1018. PYME/misc/diskCleanup.py +64 -0
  1019. PYME/misc/djangoRecarray.py +57 -0
  1020. PYME/misc/django_widgets.py +27 -0
  1021. PYME/misc/editgrid.py +101 -0
  1022. PYME/misc/eventSpy.py +122 -0
  1023. PYME/misc/exceptions.py +30 -0
  1024. PYME/misc/facsPlot.py +89 -0
  1025. PYME/misc/fbpIcons.py +90 -0
  1026. PYME/misc/fftw_compat.py +28 -0
  1027. PYME/misc/findCycles.py +91 -0
  1028. PYME/misc/fortran_interrupt_defeat.py +43 -0
  1029. PYME/misc/glassModel.py +64 -0
  1030. PYME/misc/hash32.py +41 -0
  1031. PYME/misc/hillcurve.py +88 -0
  1032. PYME/misc/hybrid_ns.py +84 -0
  1033. PYME/misc/kdFit.py +72 -0
  1034. PYME/misc/locate.py +10 -0
  1035. PYME/misc/memUsage.py +65 -0
  1036. PYME/misc/memmap.py +52 -0
  1037. PYME/misc/mock_ctypes.py +28 -0
  1038. PYME/misc/mock_traits.py +59 -0
  1039. PYME/misc/mock_traitsui.py +29 -0
  1040. PYME/misc/pyme_zeroconf.py +287 -0
  1041. PYME/misc/pyro_tracebacks.py +32 -0
  1042. PYME/misc/read_agf.py +605 -0
  1043. PYME/misc/sffake.py +16 -0
  1044. PYME/misc/snells.py +71 -0
  1045. PYME/misc/sqlite_ns.py +132 -0
  1046. PYME/misc/sqlitendarray.py +56 -0
  1047. PYME/misc/taskDef.py +44 -0
  1048. PYME/misc/tempDB.py +56 -0
  1049. PYME/misc/wxThread.py +33 -0
  1050. PYME/misc/zemax.py +259 -0
  1051. PYME/misc/zernike.py +151 -0
  1052. PYME/pyme_warnings.py +70 -0
  1053. PYME/recipes/Recipes/STEDDeconvolution.yaml +14 -0
  1054. PYME/recipes/Recipes/STEDMinistacks.yaml +15 -0
  1055. PYME/recipes/Recipes/STED_COP3.yaml +25 -0
  1056. PYME/recipes/Recipes/blobMeas.yaml +19 -0
  1057. PYME/recipes/Recipes/blobMeas2.yaml +37 -0
  1058. PYME/recipes/Recipes/blobMeasSR.yaml +66 -0
  1059. PYME/recipes/Recipes/coloc.yaml +43 -0
  1060. PYME/recipes/Recipes/coloc_roi_masked.yaml +46 -0
  1061. PYME/recipes/Recipes/multiblob.yaml +38 -0
  1062. PYME/recipes/Recipes/pre_particleTracking.yaml +30 -0
  1063. PYME/recipes/Recipes/segmentAndMeasureLoci.yaml +41 -0
  1064. PYME/recipes/__init__.py +6 -0
  1065. PYME/recipes/acquisition.py +158 -0
  1066. PYME/recipes/bakeshop.py +32 -0
  1067. PYME/recipes/base.py +1393 -0
  1068. PYME/recipes/batchProcess.py +147 -0
  1069. PYME/recipes/filters.py +394 -0
  1070. PYME/recipes/fudges.py +41 -0
  1071. PYME/recipes/graphing.py +108 -0
  1072. PYME/recipes/html_recipe_editor.py +90 -0
  1073. PYME/recipes/localisations.py +1386 -0
  1074. PYME/recipes/machine_learning.py +286 -0
  1075. PYME/recipes/measurement.py +1062 -0
  1076. PYME/recipes/modules.py +50 -0
  1077. PYME/recipes/multiview.py +435 -0
  1078. PYME/recipes/output.py +667 -0
  1079. PYME/recipes/pointcloud.py +510 -0
  1080. PYME/recipes/processing.py +2954 -0
  1081. PYME/recipes/pyramid.py +206 -0
  1082. PYME/recipes/recipe.py +965 -0
  1083. PYME/recipes/recipeGui.py +1029 -0
  1084. PYME/recipes/recipeLayout.py +499 -0
  1085. PYME/recipes/runRecipe.py +140 -0
  1086. PYME/recipes/setup.py +37 -0
  1087. PYME/recipes/simulation.py +91 -0
  1088. PYME/recipes/skfilters.py +143 -0
  1089. PYME/recipes/surface_fitting.py +776 -0
  1090. PYME/recipes/tablefilters.py +275 -0
  1091. PYME/recipes/tracking.py +343 -0
  1092. PYME/recipes/traits.py +157 -0
  1093. PYME/recipes/vertical_recipe_display.py +373 -0
  1094. PYME/resources/__init__.py +23 -0
  1095. PYME/resources/config_template/distributor.yaml +14 -0
  1096. PYME/resources/config_template/nodeserver.yaml +15 -0
  1097. PYME/resources/icons/LUT.png +0 -0
  1098. PYME/resources/icons/YSM_Shield.png +0 -0
  1099. PYME/resources/icons/YSM_logo.png +0 -0
  1100. PYME/resources/icons/arrow.png +0 -0
  1101. PYME/resources/icons/crosshairs.png +0 -0
  1102. PYME/resources/icons/line_select.png +0 -0
  1103. PYME/resources/icons/logo_fmhs.png +0 -0
  1104. PYME/resources/icons/media-playback-pause.png +0 -0
  1105. PYME/resources/icons/media-playback-start.png +0 -0
  1106. PYME/resources/icons/media-skip-backward.png +0 -0
  1107. PYME/resources/icons/media-skip-forward.png +0 -0
  1108. PYME/resources/icons/mesh.png +0 -0
  1109. PYME/resources/icons/mesh.svg +28 -0
  1110. PYME/resources/icons/pmacquire.icns +0 -0
  1111. PYME/resources/icons/pmacquire.ico +0 -0
  1112. PYME/resources/icons/pmanal.icns +0 -0
  1113. PYME/resources/icons/pmanal.ico +0 -0
  1114. PYME/resources/icons/pmvis.icns +0 -0
  1115. PYME/resources/icons/pmvis.ico +0 -0
  1116. PYME/resources/icons/points.png +0 -0
  1117. PYME/resources/icons/points.svg +16 -0
  1118. PYME/resources/icons/pymeLogo.png +0 -0
  1119. PYME/resources/icons/rect_select.png +0 -0
  1120. PYME/resources/icons/squiggle_select.png +0 -0
  1121. PYME/resources/icons/text3800.icns +0 -0
  1122. PYME/resources/icons/text3800.ico +0 -0
  1123. PYME/resources/icons/text3800.png +0 -0
  1124. PYME/resources/icons/text3800.tif +0 -0
  1125. PYME/resources/icons/text5377.icns +0 -0
  1126. PYME/resources/icons/text5377.ico +0 -0
  1127. PYME/resources/icons/text5377.png +0 -0
  1128. PYME/resources/icons/tracks.png +0 -0
  1129. PYME/resources/icons/tracks.svg +19 -0
  1130. PYME/resources/icons/view-front.png +0 -0
  1131. PYME/resources/icons/view-home.png +0 -0
  1132. PYME/resources/icons/view-right.png +0 -0
  1133. PYME/resources/icons/view-top.png +0 -0
  1134. PYME/resources/test_datasets/README.md +8 -0
  1135. PYME/resources/test_datasets/t_im.tif +0 -0
  1136. PYME/resources/test_datasets/test_csv.csv +4282 -0
  1137. PYME/resources/test_datasets/test_hdf.hdf +0 -0
  1138. PYME/resources/web/rule_inline.html +21 -0
  1139. PYME/resources/web/ruleserver.html +75 -0
  1140. PYME/resources/web/static/bootstrap.min.js +7 -0
  1141. PYME/resources/web/static/cluster.css +137 -0
  1142. PYME/resources/web/static/css/bootstrap-theme.css +587 -0
  1143. PYME/resources/web/static/css/bootstrap-theme.min.css +6 -0
  1144. PYME/resources/web/static/css/bootstrap.css +6757 -0
  1145. PYME/resources/web/static/css/bootstrap.min.css +6 -0
  1146. PYME/resources/web/static/css/flat_design_colors_full.css +306 -0
  1147. PYME/resources/web/static/css/recipe_editor.css +106 -0
  1148. PYME/resources/web/static/dashboard.css +106 -0
  1149. PYME/resources/web/static/fileselector.js +77 -0
  1150. PYME/resources/web/static/fonts/glyphicons-halflings-regular.eot +0 -0
  1151. PYME/resources/web/static/fonts/glyphicons-halflings-regular.svg +288 -0
  1152. PYME/resources/web/static/fonts/glyphicons-halflings-regular.ttf +0 -0
  1153. PYME/resources/web/static/fonts/glyphicons-halflings-regular.woff +0 -0
  1154. PYME/resources/web/static/fonts/glyphicons-halflings-regular.woff2 +0 -0
  1155. PYME/resources/web/static/images/osd_flat/LICENSE.txt +116 -0
  1156. PYME/resources/web/static/images/osd_flat/README.md +9 -0
  1157. PYME/resources/web/static/images/osd_flat/fullpage_grouphover.png +0 -0
  1158. PYME/resources/web/static/images/osd_flat/fullpage_hover.png +0 -0
  1159. PYME/resources/web/static/images/osd_flat/fullpage_pressed.png +0 -0
  1160. PYME/resources/web/static/images/osd_flat/fullpage_rest.png +0 -0
  1161. PYME/resources/web/static/images/osd_flat/home_grouphover.png +0 -0
  1162. PYME/resources/web/static/images/osd_flat/home_hover.png +0 -0
  1163. PYME/resources/web/static/images/osd_flat/home_pressed.png +0 -0
  1164. PYME/resources/web/static/images/osd_flat/home_rest.png +0 -0
  1165. PYME/resources/web/static/images/osd_flat/next_grouphover.png +0 -0
  1166. PYME/resources/web/static/images/osd_flat/next_hover.png +0 -0
  1167. PYME/resources/web/static/images/osd_flat/next_pressed.png +0 -0
  1168. PYME/resources/web/static/images/osd_flat/next_rest.png +0 -0
  1169. PYME/resources/web/static/images/osd_flat/previous_grouphover.png +0 -0
  1170. PYME/resources/web/static/images/osd_flat/previous_hover.png +0 -0
  1171. PYME/resources/web/static/images/osd_flat/previous_pressed.png +0 -0
  1172. PYME/resources/web/static/images/osd_flat/previous_rest.png +0 -0
  1173. PYME/resources/web/static/images/osd_flat/rotateleft_grouphover.png +0 -0
  1174. PYME/resources/web/static/images/osd_flat/rotateleft_hover.png +0 -0
  1175. PYME/resources/web/static/images/osd_flat/rotateleft_pressed.png +0 -0
  1176. PYME/resources/web/static/images/osd_flat/rotateleft_rest.png +0 -0
  1177. PYME/resources/web/static/images/osd_flat/rotateright_grouphover.png +0 -0
  1178. PYME/resources/web/static/images/osd_flat/rotateright_hover.png +0 -0
  1179. PYME/resources/web/static/images/osd_flat/rotateright_pressed.png +0 -0
  1180. PYME/resources/web/static/images/osd_flat/rotateright_rest.png +0 -0
  1181. PYME/resources/web/static/images/osd_flat/zoomin_grouphover.png +0 -0
  1182. PYME/resources/web/static/images/osd_flat/zoomin_hover.png +0 -0
  1183. PYME/resources/web/static/images/osd_flat/zoomin_pressed.png +0 -0
  1184. PYME/resources/web/static/images/osd_flat/zoomin_rest.png +0 -0
  1185. PYME/resources/web/static/images/osd_flat/zoomout_grouphover.png +0 -0
  1186. PYME/resources/web/static/images/osd_flat/zoomout_hover.png +0 -0
  1187. PYME/resources/web/static/images/osd_flat/zoomout_pressed.png +0 -0
  1188. PYME/resources/web/static/images/osd_flat/zoomout_rest.png +0 -0
  1189. PYME/resources/web/static/jigna-vue-bare.js +1395 -0
  1190. PYME/resources/web/static/jquery.min.js +2 -0
  1191. PYME/resources/web/static/jstree.min.js +6 -0
  1192. PYME/resources/web/static/openSeadragonGL.js +102 -0
  1193. PYME/resources/web/static/openseadragon-svg-overlay.js +103 -0
  1194. PYME/resources/web/static/openseadragon-viewerinputhook.min.js +6 -0
  1195. PYME/resources/web/static/openseadragon.min.js +9 -0
  1196. PYME/resources/web/static/recipe_editor.js +119 -0
  1197. PYME/resources/web/static/shaders/fragment/lut.glsl +20 -0
  1198. PYME/resources/web/static/shaders/fragment/none.glsl +17 -0
  1199. PYME/resources/web/static/shaders/fragment/outline.glsl +43 -0
  1200. PYME/resources/web/static/shaders/fragment/rect.glsl +7 -0
  1201. PYME/resources/web/static/shaders/fragment/sobel3.glsl +71 -0
  1202. PYME/resources/web/static/shaders/fragment/white.glsl +4 -0
  1203. PYME/resources/web/static/shaders/vertex/rect.glsl +22 -0
  1204. PYME/resources/web/static/shaders/vertex/square.glsl +9 -0
  1205. PYME/resources/web/static/utils.js +3 -0
  1206. PYME/resources/web/static/viaWebGL.js +217 -0
  1207. PYME/setup.py +109 -0
  1208. PYME/setup_exe.py +57 -0
  1209. PYME/simulation/__init__.py +0 -0
  1210. PYME/simulation/locify.py +319 -0
  1211. PYME/simulation/pointsets.py +279 -0
  1212. PYME/simulation/wormlike.py +99 -0
  1213. PYME/simulation/wormlike2.py +198 -0
  1214. PYME/simulation/wormlike3.py +197 -0
  1215. PYME/simulation/wormlike_curled.py +104 -0
  1216. PYME/tileviewer/__init__.py +0 -0
  1217. PYME/tileviewer/templates/roi_list.html +12 -0
  1218. PYME/tileviewer/templates/tileviewer.html +247 -0
  1219. PYME/tileviewer/tileviewer.py +207 -0
  1220. PYME/ui/AUIFrame.py +279 -0
  1221. PYME/ui/MetadataTree.py +469 -0
  1222. PYME/ui/__init__.py +4 -0
  1223. PYME/ui/about_dlg.py +29 -0
  1224. PYME/ui/autoFoldPanel.py +643 -0
  1225. PYME/ui/cascading_layout.py +45 -0
  1226. PYME/ui/crop_dialog.py +145 -0
  1227. PYME/ui/custom_traits_editors.py +508 -0
  1228. PYME/ui/editFilterDialog.py +80 -0
  1229. PYME/ui/editList.py +40 -0
  1230. PYME/ui/fastGraph.py +240 -0
  1231. PYME/ui/filterPane.py +348 -0
  1232. PYME/ui/histLimits.py +543 -0
  1233. PYME/ui/layerFoldPanel.py +232 -0
  1234. PYME/ui/manualFoldPanel.py +870 -0
  1235. PYME/ui/mytimer.py +116 -0
  1236. PYME/ui/patch_traitsui.py +151 -0
  1237. PYME/ui/progress.py +160 -0
  1238. PYME/ui/recArrayView.py +145 -0
  1239. PYME/ui/selection.py +71 -0
  1240. PYME/ui/shell.py +37 -0
  1241. PYME/ui/traitsui_constants.py +91 -0
  1242. PYME/ui/wx_compat.py +43 -0
  1243. PYME/update_version.py +159 -0
  1244. PYME/util/__init__.py +3 -0
  1245. PYME/util/authenticate.py +164 -0
  1246. PYME/util/execfile.py +21 -0
  1247. PYME/util/fProfile/__init__.py +1 -0
  1248. PYME/util/fProfile/convertProfile.py +117 -0
  1249. PYME/util/fProfile/fProfile.py +162 -0
  1250. PYME/util/fProfile/html/404.html +60 -0
  1251. PYME/util/fProfile/html/css/main.css +258 -0
  1252. PYME/util/fProfile/html/css/normalize.css +427 -0
  1253. PYME/util/fProfile/html/css/normalize.min.css +1 -0
  1254. PYME/util/fProfile/html/index.html +64 -0
  1255. PYME/util/fProfile/html/js/main.js +492 -0
  1256. PYME/util/fProfile/html/js/plugins.js +24 -0
  1257. PYME/util/fProfile/html/js/vendor/crossfilter.min.js +1 -0
  1258. PYME/util/fProfile/html/js/vendor/jquery-1.11.2.min.js +4 -0
  1259. PYME/util/fProfile/html/js/vendor/modernizr-2.8.3.min.js +4 -0
  1260. PYME/util/fProfile/html/js/vendor/tinycolor-min.js +4 -0
  1261. PYME/util/fProfile/viewProfile.py +30 -0
  1262. PYME/util/install_dependencies.py +95 -0
  1263. PYME/util/log_verbosity.py +11 -0
  1264. PYME/util/mProfile/__init__.py +1 -0
  1265. PYME/util/mProfile/colorize_db_t.py +297 -0
  1266. PYME/util/mProfile/mProfile.py +164 -0
  1267. PYME/util/mProfile/p.py +101 -0
  1268. PYME/util/mProfile/tProfile.py +165 -0
  1269. PYME/util/pymelauncher.py +47 -0
  1270. PYME/util/shmarray/__init__.py +0 -0
  1271. PYME/util/shmarray/shmTest.py +74 -0
  1272. PYME/util/shmarray/shmarray.py +165 -0
  1273. PYME/util/webframework.py +365 -0
  1274. PYME/version.py +62 -0
  1275. python_microscopy-25.11.20.dist-info/METADATA +68 -0
  1276. python_microscopy-25.11.20.dist-info/RECORD +1278 -0
  1277. python_microscopy-25.11.20.dist-info/WHEEL +4 -0
  1278. python_microscopy-25.11.20.dist-info/entry_points.txt +18 -0
@@ -0,0 +1,1106 @@
1
+ """
2
+ This module defines a RESTful HTTP server, the PYME Rule Server, which manages task distribution across a cluster through the use of rules.
3
+ Rules are essentially a json template which defines how tasks may be generated (by substitution into the template on the
4
+ client side). Generation of individual tasks on the client has the dual benefits of a) reducing the CPU load and memory
5
+ requirements on the server and b) dramatically decreasing the network bandwidth used for task distribution.
6
+
7
+ The exposed REST API is as follows:
8
+
9
+ ============================================================= ====== ========================================
10
+ Endpoint Verb Brief Description
11
+ ============================================================= ====== ========================================
12
+ :meth:`/add_integer_id_rule <RuleServer.add_integer_id_rule>` POST Add a new rule
13
+ :meth:`/release_rule_tasks <RuleServer.release_rule_tasks>` POST Release tasks IDs associated with a rule
14
+ :meth:`/task_advertisments <RuleServer.task_advertisements>` GET Retrieve a list of advertisements
15
+ :meth:`/bid_on_tasks <RuleServer.bid_on_tasks>` POST Submit bids on advertised tasks
16
+ :meth:`/handin <RuleServer.handin>` POST Advise rule server of task completion
17
+ :meth:`/distributor/queues <Ruleserver.get_queues>` GET Get status information
18
+ ============================================================= ====== ========================================
19
+
20
+ Implementation details follow. The json format and parameters for the REST calls are defined in the docstrings of the
21
+ python functions defining that method (linked from the table above). The server is launched by the ``PYMERuleServer``
22
+ command (see :mod:`PYME.cluster.PYMERuleServer`) which loads this in a separate thread and takes care of logging and zeroconf
23
+ registration, rather than by directly running this file.
24
+ """
25
+ #import cherrypy
26
+ import threading
27
+ import requests
28
+ import queue as Queue
29
+ from six.moves import xrange
30
+
31
+ import logging
32
+ logging.basicConfig(level=logging.WARN)
33
+ logger = logging.getLogger('ruleserver')
34
+ logger.setLevel(logging.DEBUG)
35
+
36
+ import time
37
+ import sys
38
+ import ujson as json
39
+ #import json
40
+ import os
41
+
42
+ from PYME.misc import computerName
43
+ from PYME import config
44
+ from PYME import resources
45
+ #from PYME.IO import clusterIO
46
+ from PYME.util import webframework
47
+ import collections
48
+
49
+ import uuid
50
+
51
+ import numpy as np
52
+
53
+ class Rule(object):
54
+ pass
55
+
56
+ STATUS_UNAVAILABLE, STATUS_AVAILABLE, STATUS_ASSIGNED, STATUS_COMPLETE, STATUS_FAILED = range(5)
57
+
58
+ Bid = collections.namedtuple('Bid', 'bidder_id, cost')
59
+
60
+ DEFAULT_BID = Bid(0, sys.maxsize)
61
+
62
+ class IntegerIDRule(Rule):
63
+ """
64
+ A rule which generates tasks based on a template.
65
+
66
+ Parameters
67
+ ----------
68
+ ruleID : str
69
+ A unique ID for this rule
70
+ task_template : str
71
+ A json template for generating tasks (see templates section below)
72
+ inputs_by_task : list of dict
73
+ A list of dictionaries mapping recipe variable names to URIs to treat as inputs (recipes only)
74
+ max_task_ID : int
75
+ The maximum number of tasks that can be generated by this rule. If the final number of tasks is not known at
76
+ creation, set this to a value which is garuanteed to be higher and then call `mark_release_complete()` after all tasks
77
+ have been released / made available.
78
+ task_timeout: float
79
+ A timeout in seconds for each task. If a task takes longer than task_timeout seconds it is assumed that
80
+ the node executing it has fallen over and we retry on a different node (up to a maximum number of times
81
+ set by the 'ruleserver-retries` config option).
82
+ rule_timeout : float
83
+ A timeout in seconds from the last task we processed after which we assume that no more tasks are coming and
84
+ we can delete the rule (to keep memory down in a long-term usage scenario).
85
+
86
+
87
+ Notes
88
+ -----
89
+
90
+ *Templates*
91
+
92
+ Templates are a string which can be substituted to generate tasks. There are currently two supported formats for
93
+ templates, those for localization tasks, and those for recipes. Each take the form of a json dictionary:
94
+
95
+ **Localization**
96
+
97
+ .. code-block:: json
98
+
99
+ {
100
+ "id" : "{{ruleID}}~{{taskID}}",
101
+ "type" : "localization",
102
+ "taskdef" : {"frameIndex" : {{taskID}}, "metadata" : "PYME-CLUSTER://path/to/series/metadata.json"},
103
+ "inputs" : {"frames" : "PYME-CLUSTER://path/to/series.pcs"},
104
+ "outputs" : {"fitResults" : "PYME-CLUSTER://__aggregate_h5r/path/to/analysis.h5r/FitResults",
105
+ "driftResults" : "PYME-CLUSTER://__aggregate_h5r/path/to/analysis.h5r/DriftResults"}
106
+ }
107
+
108
+
109
+ **Recipes**
110
+ The recipe can either be specified inline:
111
+
112
+ .. code-block:: json
113
+
114
+ {
115
+ "id" : "{{ruleID}}~{{taskID}}",
116
+ "type" : "recipe",
117
+ "taskdef" : {"recipe" : "<recipe as a YAML string>"},
118
+ "inputs" : {{taskInputs}},
119
+ "output_dir" : "PYME-CLUSTER://path/to/output/dir",
120
+ }
121
+
122
+
123
+ or using a cluster URI:
124
+
125
+ .. code-block:: json
126
+
127
+ {
128
+ "id" : "{{ruleID}}~{{taskID}}",
129
+ "type" : "recipe",
130
+ "taskdefRef" : "PYME-CLUSTER://path/to/recipe.yaml",
131
+ "inputs" : {{taskInputs}},
132
+ "output_dir" : "PYME-CLUSTER://path/to/output/dir",
133
+ }
134
+
135
+
136
+ The rule will substitute ``{{taskInputs}}`` with a dictionary mapping integer task IDs to recipe input files, e.g.
137
+
138
+ .. code-block:: json
139
+
140
+ {0 : {"recipe_input_0" : "input_0_URI_0","recipe_input_1" : "input_1_URI_0"},
141
+ 1 : {"recipe_input_0" : "input_0_URI_1","recipe_input_1" : "input_1_URI_1"},
142
+ 2 : {"recipe_input_0" : "input_0_URI_2","recipe_input_1" : "input_1_URI_2"},
143
+ }
144
+
145
+
146
+ Alternatively the inputs dictionary can be supplied directly (without relying on the taskInputs substitution).
147
+
148
+ *Rule Chaining*
149
+
150
+ Rules may also define a chained rule, to be run on completion of the original rule. This is accomplished by
151
+ supplying an "on_completion" dictionary. This is a dictionary, ``{'template' : <template>, 'max_tasks' : max_tasks,
152
+ 'rule_timeout' : timeout, 'on_completion' : {...}}``, with the template following the format above and everything
153
+ but the template being optional (max_tasks defaults to 1). Follow on / chained rules are slightly more restricted
154
+ than standard rules in that recipe "inputs" must be hardcoded (no ``{{taskInputs}}`` substitution).
155
+
156
+ Chained rules are created once the original rule is finished (see
157
+ `IntegerIDRule.finished`). All tasks for the chained rule will be released
158
+ immediately.
159
+
160
+ """
161
+ TASK_INFO_DTYPE = np.dtype([('status', 'uint8'), ('nRetries', 'uint8'), ('expiry', 'f4'), ('cost', 'f4')])
162
+
163
+ # task cost threshold below which tasks are deemed 'local' and directly awarded to the first bidder
164
+ # rather than going to "auction" - ie. the "Buy Now" price
165
+ # TODO - Revisit - should this be a settable rule parameter rather than a constant?
166
+ COST_THRESHOLD = 0.2
167
+
168
+
169
+ def __init__(self, ruleID, task_template, inputs_by_task = None,
170
+ max_task_ID=100000, task_timeout=600, rule_timeout=3600,
171
+ on_completion=None):
172
+ self.ruleID = ruleID
173
+
174
+ if not inputs_by_task is None:
175
+ self._inputs_by_task = {int(k):v for k, v in inputs_by_task.items()}
176
+ else:
177
+ self._inputs_by_task = None
178
+
179
+ self._template = task_template
180
+ self._task_info = np.zeros(max_task_ID, self.TASK_INFO_DTYPE)
181
+
182
+ # Number of times to re-queue a task if it times out is set by the 'ruleserver-retries' config option
183
+ # Setting a value of 0 effectively disables re-trying and makes analysis less robust.
184
+ # Note that a timeout is different to a failure - failing tasks will be marked as having failed and will not be re-tried. Timeouts will
185
+ # occur in one of 4 scenarios:
186
+ # - a worker falls over completely or is disconnected from the network
187
+ # - an unhandled exception - e.g. due to an IO error connecting to the ruleserver in `taskWorkerHTTP.taskWorker._return_task_results()`
188
+ # - analysis is getting massively bogged down and nothing is keeping up
189
+ # - the task timeout is unrealistically short for a given processing task
190
+ #
191
+ # In scenarios 1 & 2 it's reasonable to expect that retrying will result in success. In scenarios 3 & 4 it's a bit muddier, but seeing as a) these kind of
192
+ # failures tend to be a bit stochastic and b) the retries get punted to the back of the queue, when the load might have let up a bit, the odds are
193
+ # reasonably good.
194
+ self._n_retries = config.get('ruleserver-retries', 1)
195
+ self._timeout = task_timeout
196
+
197
+ self._rule_timeout = rule_timeout
198
+ self._cached_advert = None
199
+ self._active = True # making this rule inactive will cause it not to generate adverts (this is the closest we get to aborting)
200
+ self._seen_as_finished = False # flag to make sure completion logic only gets triggered once.
201
+
202
+ self.nTotal = 0
203
+ self.nAssigned = 0
204
+ self.nAvailable = 0
205
+ self.nCompleted = 0
206
+ self.nFailed = 0
207
+ self.n_returned_after_timeout = 0
208
+ self.n_repeats = 0
209
+ self.n_timed_out = 0
210
+
211
+ self._n_max = max_task_ID
212
+
213
+ self.on_completion = on_completion
214
+
215
+ self.avCost = 0
216
+
217
+ self.expiry = time.time() + self._rule_timeout
218
+
219
+ # store pending bids
220
+ self._pending_bids = {}
221
+ self._current_bidder_id = 0
222
+
223
+ self._info_lock = threading.Lock()
224
+ self._advert_lock = threading.Lock()
225
+
226
+ def mark_release_complete(self, n_tasks=None):
227
+ """
228
+ Signal that all tasks which are going to be released for this rule have been, and that the rule should evaluate as finished once these tasks have been
229
+ evaluated. Used when the number of tasks is not known in advance. (See also __init__ docs)
230
+
231
+ FIXME - What happens when task release doesn't start at 0?
232
+
233
+ Parameters
234
+ ----------
235
+ n_tasks : int, optional
236
+ mark complete at a given number of tasks. The default is to mark complete at the highest task number which has been released prior to making this call.
237
+ The use case for this optional parameter is to avoid the need for locking when this gets called from another thread than the `make_range_available()`
238
+ and implies a promise by the calling code that it will not release any more tasks above the given number.
239
+
240
+ Raises
241
+ ------
242
+ ValueError
243
+ If `n_tasks` is supplied and is either smaller than the largest task already released or larger than larger than `max_task_ID`
244
+ """
245
+
246
+ with self._info_lock: #TODO - is this lock necessary (I suspect it's not)
247
+ if (n_tasks is not None):
248
+ if self.nTotal > n_tasks:
249
+ raise ValueError('n_tasks cannot be less than nTotal')
250
+
251
+ # extend _task_info array if necessary
252
+ if n_tasks > self._n_max:
253
+ raise ValueError('n_tasks cannot be greater than max_task_ID')
254
+
255
+ self._n_max = n_tasks
256
+ else:
257
+ self._n_max = self.nTotal
258
+
259
+
260
+
261
+
262
+ def _update_nums(self):
263
+ self.nAvailable = int((self._task_info['status'] == STATUS_AVAILABLE).sum())
264
+ self.nAssigned = int((self._task_info['status'] == STATUS_ASSIGNED).sum())
265
+
266
+ def _update_cost(self):
267
+ av_cost = np.mean(self._task_info['cost'][self._task_info['status'] > STATUS_AVAILABLE])
268
+ if np.isnan(av_cost):
269
+ av_cost = 0
270
+ else:
271
+ av_cost = float(av_cost)
272
+
273
+ self.avCost = av_cost
274
+
275
+ def make_range_available(self, start, end):
276
+ """
277
+ Make a range of tasks available (to be called once the underlying data is available)
278
+ [start, end)
279
+
280
+ Parameters
281
+ ----------
282
+ start : int
283
+ first task number to release (inclusive)
284
+ end : int
285
+ last task number to release (exclusive)
286
+
287
+ Raises
288
+ ------
289
+ RuntimeError
290
+ if asked to release a range which is invalid for the max tasks we can create from this rule
291
+ """
292
+
293
+ if start < 0 or start > self._task_info.size or end < 0 or end > self._task_info.size:
294
+ raise RuntimeError('Range (%d, %d) invalid with maxTasks=%d' % (start, end, self._task_info.size))
295
+
296
+ #TODO - check existing status - it probably makes sense to only apply this to tasks which have STATUS_UNAVAILABLE
297
+ with self._info_lock:
298
+ self._task_info['status'][start:end] = STATUS_AVAILABLE
299
+
300
+ self.nTotal = int((self._task_info['status'] >0).sum())
301
+
302
+ self._update_nums()
303
+
304
+ self.expiry = time.time() + self._rule_timeout
305
+
306
+ with self._advert_lock:
307
+ self._cached_advert = None
308
+
309
+ def bid(self, bid):
310
+ """Bid on tasks (and return any that match). Note the current implementation is very naive and doesn't
311
+ check bid cost - i.e. the first bid gets the task. This works if (and only if) the clients are well behaved
312
+ and preferentially bid on tasks which have a lowest cost for them.
313
+
314
+ Parameters
315
+ ----------
316
+
317
+ bid : dict
318
+ A dictionary containing the ruleID, the IDs of the tasks to bid on, and their costs
319
+ ``{"ruleID" : str ,"taskIDs" : [list of int],"taskCosts" : [list of float]}``
320
+
321
+ Returns
322
+ -------
323
+
324
+ successful_bids: dict
325
+ A dictionary containing the ruleID, the IDs of the tasks awarded, and the rule template
326
+ ``{"ruleID" : ruleID, "taskIDs": [list of int], "template" : "<rule template>"}``
327
+
328
+ """
329
+ if not self._active:
330
+ # don't accept any bids
331
+ return {'ruleID': bid['ruleID'], 'taskIDs':[], 'template' : ''}
332
+
333
+ taskIDs = np.array(bid['taskIDs'], 'i')
334
+ costs = np.array(bid['costs'], 'f4')
335
+
336
+ if np.all(costs < self.COST_THRESHOLD):
337
+ # all tasks are below the "Buy Now" threshold, take a shortcut and directly award them to the bidder bypassing
338
+ # the rest of the biddng process. This enables high performance on localisation tasks
339
+ pass
340
+ else:
341
+ # NOTE: this bidding code is not high-performance. This is probably OK as code is bypassed in normal
342
+ # localisation scenario but might need to be revisited as it will be triggered in mixed cases where
343
+ # some bids are local and some are not.
344
+ with self._info_lock:
345
+ # get a unique bidder ID
346
+ self._current_bidder_id += 1
347
+ bidder_id = self._current_bidder_id
348
+
349
+ # record bids
350
+ for taskID, cost in zip(taskIDs, costs):
351
+ # get existing winning bid
352
+ _, winning_cost = self._pending_bids.get(taskID, DEFAULT_BID)
353
+ if cost < winning_cost:
354
+ # if we have a lower cost, over-write the winning bid
355
+ self._pending_bids[taskID] = Bid(bidder_id, cost)
356
+
357
+ #wait for other bids
358
+ time.sleep(0.2) #TODO - make this time configurable??
359
+
360
+ with self._info_lock:
361
+ # filter our tasks to only keep the wining ones
362
+ winners = [self._pending_bids[taskID].bidder_id==bidder_id for taskID in taskIDs]
363
+
364
+ taskIDs = taskIDs[winners]
365
+ costs = costs[winners]
366
+
367
+
368
+ with self._info_lock:
369
+ successful_bid_mask = self._task_info['status'][taskIDs] == STATUS_AVAILABLE
370
+ successful_bid_ids = taskIDs[successful_bid_mask]
371
+ self._task_info['status'][successful_bid_ids] = STATUS_ASSIGNED
372
+ self._task_info['cost'][successful_bid_ids] = costs[successful_bid_mask]
373
+ self._task_info['expiry'][successful_bid_ids] = time.time() + self._timeout
374
+
375
+ nTasks = len(successful_bid_ids)
376
+ self.nAvailable -= nTasks
377
+ self.nAssigned += nTasks
378
+
379
+ self._update_cost()
380
+
381
+ self.expiry = time.time() + self._rule_timeout
382
+
383
+ with self._advert_lock:
384
+ self._cached_advert = None
385
+
386
+ return {'ruleID': bid['ruleID'], 'taskIDs':successful_bid_ids.tolist(), 'template' : self._template}
387
+
388
+ def mark_complete(self, info):
389
+ """
390
+ Mark a set of tasks as completed and/or failed
391
+
392
+ Parameters
393
+ ----------
394
+ info : dict
395
+ A dictionary of the form: ``{"ruleID": str, "taskIDs" : [list of int], "status" : [list of int]}``
396
+
397
+ There should be an entry in status for each entry in taskIDs, the valid values of status being
398
+ ``STATUS_COMPLETE=3`` or ``STATUS_FAILED=4``.
399
+
400
+ Returns
401
+ -------
402
+
403
+ """
404
+ taskIDs = np.array(info['taskIDs'], 'i')
405
+ status = np.array(info['status'], 'uint8')
406
+
407
+ with self._info_lock:
408
+ old_status = np.copy(self._task_info['status'][taskIDs])
409
+ self._task_info['status'][taskIDs] = status
410
+
411
+ # if tasks have timed out (or results have already been recieved), they will register as not assigned
412
+ n_not_assigned = int((old_status != STATUS_ASSIGNED).sum())
413
+
414
+ # if we re-queue tasks after timeout we might receive answers from the re-queued tasks twice
415
+ n_already_complete = int((old_status == STATUS_COMPLETE).sum())
416
+ n_already_failed = int((old_status == STATUS_FAILED).sum())
417
+
418
+
419
+ self.nCompleted += (int((status == STATUS_COMPLETE).sum()) - n_already_complete)
420
+ self.nFailed += (int((status == STATUS_FAILED).sum()) - n_already_failed)
421
+
422
+ self.n_repeats += (n_already_complete + n_already_failed)
423
+ self.n_returned_after_timeout += n_not_assigned
424
+ self.nAvailable -= (n_not_assigned - (n_already_complete + n_already_failed))
425
+
426
+ nTasks = len(taskIDs) - n_not_assigned#(n_already_complete + n_already_failed)
427
+ self.nAssigned -= nTasks
428
+
429
+ self.expiry = time.time() + self._rule_timeout
430
+
431
+ @property
432
+ def advert(self):
433
+ """ The task advertisment.
434
+
435
+ If the rule has tasks available, a dictionary of the form:
436
+ ``{"ruleID" : str, "taskTemplate" : str, "availableTaskIDs" : [list of int], "inputsByTask" : [optional] dict mapping task IDs to inputs}``
437
+
438
+ "inputsByTask" is only provided for some recipe tasks.
439
+ """
440
+ if not self._active:
441
+ return None
442
+
443
+ with self._advert_lock:
444
+ if not self._cached_advert:
445
+ availableTasks = np.where(self._task_info['status'] == STATUS_AVAILABLE)[0].tolist()
446
+
447
+ if len(availableTasks) == 0:
448
+ self._cached_advert = None
449
+ else:
450
+ self._cached_advert = {'ruleID' : self.ruleID,
451
+ 'taskTemplate': self._template,
452
+ 'availableTaskIDs': availableTasks}
453
+
454
+ #print self._inputs_by_task
455
+
456
+ if not self._inputs_by_task is None:
457
+ self._cached_advert['inputsByTask'] = {taskID: self._inputs_by_task[taskID] for taskID in availableTasks}
458
+
459
+ return self._cached_advert
460
+
461
+ # @property
462
+ # def nAvailable(self):
463
+ # return (self._task_info['status'] == STATUS_AVAILABLE).sum()
464
+ #
465
+ # @property
466
+ # def nAssigned(self):
467
+ # return (self._task_info['status'] == STATUS_ASSIGNED).sum()
468
+
469
+ # @property
470
+ # def nCompleted(self):
471
+ # return (self._task_info['status'] == STATUS_COMPLETE).sum()
472
+
473
+ # @property
474
+ # def nFailed(self):
475
+ # return (self._task_info['status'] == STATUS_FAILED).sum()
476
+
477
+
478
+ @property
479
+ def expired(self):
480
+ """ Whether the rule has expired (no available tasks, no tasks assigned, and time > expiry) and can be removed"""
481
+ return (self.nAvailable == 0) and (self.nAssigned == 0) and (time.time() > self.expiry)
482
+
483
+ @property
484
+ def finished(self):
485
+ """
486
+ Whether the rule has finished (the maximum number of tasks which can be created have been completed).
487
+ """
488
+
489
+ # TODO - change this so that we can release starting at task_ID > 0????
490
+ # TODO - make rules finish when some tasks fail.
491
+
492
+ # To fix: Potentially replace with `np.all(self._task_info['status']>=STATUS_COMPLETE)` (although this would need to be cached and refreshed - property access should be cheap).
493
+ # combined with a new enum value STATUS_INVALID==6 - `self.mark_release_complete()` could be re-written as `self._task_info['status'][self._task_info['status'] == 0] = STATUS_INVALID`
494
+
495
+ return (self.nAvailable == 0) and ((self.nCompleted + self.nFailed) >= self._n_max)
496
+
497
+ def inactivate(self):
498
+ """
499
+ Mark rule as inactive (generates no adverts) to facilitate aborting / pausing long-running rules.
500
+ """
501
+ self._active = False
502
+
503
+ def info(self):
504
+ """
505
+ Get information / status about this rule
506
+
507
+ Returns
508
+ -------
509
+
510
+ status : dict
511
+ A status dictionary of the form:
512
+ ``{'tasksPosted': int, 'tasksRunning': int, 'tasksCompleted': int, 'tasksFailed' : int, 'averageExecutionCost' : float}``
513
+
514
+ """
515
+ return {'tasksPosted': self.nTotal,
516
+ 'tasksRunning': self.nAssigned,
517
+ 'tasksCompleted': self.nCompleted,
518
+ 'tasksFailed' : self.nFailed,
519
+ 'averageExecutionCost' : self.avCost,
520
+ 'active' : self._active,
521
+ 'tasksTimedOut' : self.n_timed_out,
522
+ 'tasksCompleteAfterTimeout' : self.n_returned_after_timeout,
523
+ 'finished' : self.finished,
524
+ 'expired' : self.expired,
525
+ }
526
+
527
+ def poll_timeouts(self):
528
+ t = time.time()
529
+
530
+ with self._info_lock:
531
+ timed_out = np.where((self._task_info['status'] == STATUS_ASSIGNED)*(self._task_info['expiry'] < t))[0]
532
+
533
+
534
+ nTimedOut = len(timed_out)
535
+ if nTimedOut > 0:
536
+ self._task_info['status'][timed_out] = STATUS_AVAILABLE
537
+ self._task_info['nRetries'][timed_out] += 1
538
+
539
+ self.nAssigned -= nTimedOut
540
+ self.nAvailable += nTimedOut
541
+
542
+ self.n_timed_out += nTimedOut
543
+
544
+ retry_failed = self._task_info['nRetries'][timed_out] > self._n_retries
545
+ self._task_info['status'][timed_out[retry_failed]] = STATUS_FAILED
546
+ self.nAvailable -= int(retry_failed.sum())
547
+ self.nFailed += int(retry_failed.sum())
548
+
549
+ #self._update_nums()
550
+
551
+ with self._advert_lock:
552
+ self._cached_advert = None
553
+
554
+
555
+
556
+
557
+
558
+
559
+ class RuleServer(object):
560
+ MAX_ADVERTISEMENTS = 5 * 10 * 50 * 12 #only advertise enough for 100 tasks on each core of each cluster node
561
+ def __init__(self):
562
+ self._rules = collections.OrderedDict()
563
+
564
+ #cherrypy.engine.subscribe('stop', self.stop)
565
+
566
+ self._do_poll = True
567
+
568
+ self._queueLock = threading.Lock()
569
+
570
+ self._advert_lock = threading.Lock()
571
+
572
+ #set up threads to poll the distributor and announce ourselves and get and return tasks
573
+ #self.pollThread = threading.Thread(target=self._poll)
574
+ #self.pollThread.start()
575
+
576
+ self._cached_advert = None
577
+ self._cached_advert_expiry = 0
578
+
579
+
580
+ self._info_lock = threading.Lock()
581
+ self._cached_info = None
582
+ self._cached_info_expiry = 0
583
+ self._cached_info_timeout = 5
584
+ self._finished_rule_timeout = 60 # keep finished rules around for a minute (so we can see them in the GUI)
585
+ self._failed_finished_rule_timeout = 5*60 # keep rules with failures around for 5 mins to give us a chance to look at errors
586
+
587
+ self._rule_n = 0
588
+
589
+ self._rule_lock = threading.Lock() # lock for when we modify the dictionary of rules
590
+
591
+ self.rulePollThread = threading.Thread(target=self._poll_rules)
592
+ self.rulePollThread.start()
593
+
594
+ with open(os.path.join(resources.get_web_dir(), 'ruleserver.html'), 'r') as f:
595
+ self._status_page = f.read()
596
+
597
+
598
+ def _poll(self):
599
+ while self._do_poll:
600
+ time.sleep(1)
601
+
602
+ def _poll_rules(self):
603
+ while self._do_poll:
604
+ for qn in list(self._rules.keys()):
605
+ self._rules[qn].poll_timeouts()
606
+
607
+ # look for rules that have processed all tasks
608
+ if self._rules[qn].finished:
609
+ #with self._rule_lock:
610
+ # r = self._rules.pop(qn)
611
+
612
+ r = self._rules[qn]
613
+ if not r._seen_as_finished:
614
+ r._seen_as_finished = True # prevent following logic from executing twice
615
+
616
+ # shorten rule expiry (no need to keep lots of finished rules in memory)
617
+ if r.nFailed > 0:
618
+ # Allow a little more time if we have errors so we can click through to the diagnostics (TODO)
619
+ r.expiry = time.time() + self._failed_finished_rule_timeout
620
+ else:
621
+ # Allow some time so that rules can be seen as complete in the GUI
622
+ r.expiry = time.time() + self._finished_rule_timeout
623
+
624
+ follow_on = r.on_completion
625
+ if follow_on is not None:
626
+ # if a follow on rule is defined, add it
627
+ template = follow_on['template']
628
+ n_tasks = follow_on.get('max_tasks', 1)
629
+ timeout = follow_on.get('rule_timeout', 3600.)
630
+ ruleID = '%06d-%s' % (self._rule_n, uuid.uuid4().hex)
631
+
632
+ rule = IntegerIDRule(ruleID, template, max_task_ID=int(n_tasks),
633
+ rule_timeout=float(timeout), on_completion=follow_on.get('on_completion', None))
634
+
635
+ rule.make_range_available(0, int(n_tasks))
636
+
637
+ with self._rule_lock:
638
+ self._rules[ruleID] = rule
639
+
640
+ self._rule_n += 1
641
+
642
+
643
+ #remore queue if expired (no activity for an hour) to free up memory
644
+ if self._rules[qn].expired:
645
+ logger.debug('removing expired rule: %s' % self._rules[qn].ruleID)
646
+ with self._rule_lock:
647
+ r = self._rules.pop(qn)
648
+
649
+
650
+ time.sleep(5)
651
+
652
+ def stop(self):
653
+ self._do_poll = False
654
+
655
+ #for queue in self._queues.values():
656
+ # queue.stop()
657
+
658
+ @webframework.register_endpoint('/task_advertisements')
659
+ def task_advertisements(self):
660
+ """
661
+ HTTP endpoint (GET) for retrieving task advertisements.
662
+
663
+ Note - by default, a limited number of advertisements are posted at any given time (to limit bandwidth). This
664
+ should be enough to keep all the workers busy, with new adverts being posted once tasks are assigned to workers.
665
+
666
+ Returns
667
+ -------
668
+
669
+ adverts : json str
670
+ List of advertisements. See :attr:`IntegerIDRule.advert`
671
+
672
+ """
673
+ with self._advert_lock:
674
+ t = time.time()
675
+ if (t > self._cached_advert_expiry):
676
+ adverts = []
677
+ nTasks = 0
678
+ ruleN = 0
679
+
680
+ rules = list(self._rules.values())
681
+ while ruleN < len(rules) and nTasks < self.MAX_ADVERTISEMENTS:
682
+ advert = rules[ruleN].advert
683
+
684
+ if not advert is None:
685
+ adverts.append(advert)
686
+ nTasks += len(advert['availableTaskIDs'])
687
+
688
+ ruleN += 1
689
+
690
+ self._cached_advert = json.dumps(adverts)
691
+ self._cached_advert_expiry = time.time() + 1 #regenerate advert once every second
692
+
693
+ return self._cached_advert
694
+
695
+
696
+ @webframework.register_endpoint('/bid_on_tasks')
697
+ def bid_on_tasks(self, body=''):
698
+ """
699
+ HTTP endpoint (POST) for bidding on tasks.
700
+
701
+ Parameters
702
+ ----------
703
+ body : json list of bids
704
+ A list of bids, each of which is a dictionary of the form
705
+ ``{"ruleID" : str ,"taskIDs" : [list of int],"taskCosts" : [list of float]}``
706
+ see :meth:`IntegerIDRule.Bid` for details.
707
+
708
+ Returns
709
+ -------
710
+ assignments: json str
711
+ A json formatted list of task assignments, each of which has the form:
712
+ ``{"ruleID" : ruleID, "taskIDs": [list of int], "template" : "<rule template>"}``
713
+ See :meth:`IntegerIDTask.bid`
714
+
715
+ """
716
+ bids = json.loads(body)
717
+
718
+ succesfull_bids = []
719
+
720
+ for bid in bids:
721
+ rule = self._rules[bid['ruleID']]
722
+
723
+ succesfull_bids.append(rule.bid(bid))
724
+ #task_ids = bid['taskIDs']
725
+ #costs = bid['taskCosts']
726
+
727
+ #print(succesfull_bids)
728
+ return json.dumps(succesfull_bids)
729
+
730
+
731
+
732
+ @webframework.register_endpoint('/add_integer_id_rule')
733
+ def add_integer_id_rule(self, max_tasks= 1e6, release_start=None, release_end = None, ruleID = None, timeout=3600, body=''):
734
+ """
735
+ HTTP endpoint (POST) for adding a new rule.
736
+
737
+ Add a rule that generates tasks based on an integer ID, such as a frame number (localization) or an index into
738
+ a list of inputs (recipes). By default, tasks are not released on creation, but later with
739
+ :func:`release_rule_tasks()`. This allows for the creation of a rule before a series has finished spooling.
740
+
741
+ Parameters
742
+ ----------
743
+ max_tasks : int
744
+ The maximum number of tasks that could match this rule. Generally the number of frames in a localization
745
+ series (if known in advance) or the number of inputs on which to run a recipe. Allows us to pre-allocate a
746
+ task array of the correct size (passing this rather than relying on the default reduces memory usage).
747
+ release_start, release_end : int
748
+ Release a range of tasks for computation after creating the rule (avoids a
749
+ call to `release_rule_tasks()`
750
+ ruleID : str
751
+ A unique identifier for the rule. If not provided, one will be automatically generated
752
+ timeout : int
753
+ How long this rule should live for, in seconds. Defaults to an hour.
754
+ body : str
755
+ A json dictionary ``{'template' : "<rule template>", 'inputsByTask' : [list of URIs]}``. See :class:`IntegerIDRule`
756
+ for the format of the rule template. The ``inputsByTask`` parameter is only used for recipes, and can be omitted
757
+ for localisation analysis, or for recipe tasks using a hard coded ``"inputs"`` dictionary. An optional additional
758
+ parameter, "on_completion" parameter may be given, itself consisting of a new
759
+ ``{'template': <template>, 'on_completion': {...}}`` dictionary.
760
+
761
+ Returns
762
+ -------
763
+
764
+ result : json str
765
+ The result of adding the rule. A dict of the form:
766
+ ``{"ok" : "True", 'ruleID' : str}``
767
+
768
+ """
769
+ with self._rule_lock:
770
+ # lock ~entire call so we don't hit KeyErrors if clients immediately
771
+ # try to abort/mark datasource complete, etc. after posting
772
+ rule_info = json.loads(body)
773
+
774
+ if ruleID is None:
775
+ ruleID = '%06d-%s' % (self._rule_n, uuid.uuid4().hex)
776
+
777
+ rule = IntegerIDRule(ruleID, rule_info['template'], max_task_ID=int(max_tasks), rule_timeout=float(timeout),
778
+ inputs_by_task=rule_info.get('inputsByTask', None), on_completion=rule_info.get('on_completion', None))
779
+
780
+ #print rule._inputs_by_task
781
+ if not release_start is None:
782
+ rule.make_range_available(int(release_start), int(release_end))
783
+
784
+
785
+ self._rules[ruleID] = rule
786
+
787
+ self._rule_n += 1
788
+
789
+ return json.dumps({'ok': 'True', 'ruleID' : ruleID})
790
+
791
+ @webframework.register_endpoint('/release_rule_tasks')
792
+ def release_rule_tasks(self, ruleID, release_start, release_end, body=''):
793
+ """
794
+ HTTP Endpoint (POST or GET ) for releasing tasks associated with a rule.
795
+
796
+ When performing spooling data analysis we typically have one rule per series and one task per frame.
797
+ This method allows for the tasks associated with a particular frame (or range of frames) to be released as they
798
+ become available.
799
+
800
+ Parameters
801
+ ----------
802
+ ruleID : str
803
+ The rule ID
804
+ release_start, release_end: int
805
+ The range of tasks IDs to release
806
+ body : str, empty
807
+ Needed for interface compatibility, ignored
808
+
809
+ Returns
810
+ -------
811
+
812
+ success : json str
813
+ ``{"ok" : "True"}`` if successful.
814
+
815
+ """
816
+ with self._rule_lock:
817
+ # take out the lock in case the rule is still being added in another
818
+ # request and we are already trying to release tasks
819
+ rule = self._rules[ruleID]
820
+
821
+ logger.debug('release_rule_tasks(ruleID = %s, release_start=%d, release_end=%d)' % (ruleID, int(release_start), int(release_end )))
822
+
823
+ rule.make_range_available(int(release_start), int(release_end))
824
+
825
+
826
+ return json.dumps({'ok': 'True'})
827
+
828
+ @webframework.register_endpoint('/inactivate_rule')
829
+ def inactivate_rule(self, ruleID):
830
+ with self._rule_lock:
831
+ # take out the lock in case the rule is still being added in another
832
+ # request and we are already trying to abort
833
+ self._rules[ruleID].inactivate()
834
+
835
+ return json.dumps({'ok': 'True'})
836
+
837
+ @webframework.register_endpoint('/handin')
838
+ def handin(self, body):
839
+ """
840
+ HTTP Endpoint (POST) to mark tasks as having been completed
841
+
842
+ Parameters
843
+ ----------
844
+ body : json list
845
+ A list of entries of the form ``{"ruleID": str, "taskIDs" : [list of int], "status" : [list of int]}``
846
+ where status has the same length as taskIDs with each entry being either ``STATUS_COMPLETE`` or
847
+ ``STATUS_FAILED``. See :meth:`IntegerIDRule.mark_complete`.
848
+
849
+ Returns
850
+ -------
851
+
852
+ success : json str
853
+ ``{"ok" : "True"}`` if successful.
854
+
855
+
856
+ """
857
+
858
+ #logger.debug('Handing in tasks...')
859
+ expired_rules = set()
860
+ for handin in json.loads(body):
861
+ ruleID = handin['ruleID']
862
+ try:
863
+ rule = self._rules[ruleID]
864
+ rule.mark_complete(handin)
865
+ except KeyError: # rule may have expired
866
+ expired_rules.add(ruleID)
867
+
868
+ if len(expired_rules) == 0:
869
+ return json.dumps({'ok': 'True'})
870
+ else:
871
+ # rulenodeserver currently ignores what we say here other than 'ok'
872
+ return json.dumps({'ok': 'False', 'error': str(expired_rules)})
873
+
874
+ @webframework.register_endpoint('/mark_release_complete')
875
+ def mark_release_complete(self, ruleID, n_tasks=None):
876
+ """
877
+
878
+ HTTP Endpoint (POST) to signal that no more tasks will be released for a rule and the rule can be regarded as finished once the previously released
879
+ tasks are complete.
880
+
881
+ Parameters
882
+ ----------
883
+ rule_id : str
884
+ ID of the rule to update
885
+ n_tasks : int, [optional, discouraged]
886
+ a fixed number of tasks to truncate the rule at. Used for avoiding locks/race conditions in a multi-threaded client process. NOTE - this parameter
887
+ may disappear in a future version to enable rules with incomplete ranges to be marked as complete (see comments in `IntegerIDRule.finished`). Locking or
888
+ otherwise structuring the client such that no `release_rule_tasks()` calls can occur after a call to `mark_release_complete()` is therefore preferred.
889
+
890
+ Returns
891
+ -------
892
+ success : str
893
+ ``{"ok" : "True"}`` if successful.
894
+
895
+ Raises
896
+ ------
897
+ ValueError
898
+ If `value` is less than number of tasks already assigned.
899
+
900
+ FIXME - HTTP endpoints should not raise - they should handle the error and return an error response to the client.
901
+ """
902
+ if n_tasks is not None:
903
+ n_tasks = int(n_tasks)
904
+
905
+ # take out the rule lock in case we are still creating the rule and the
906
+ # client POSTs this (e.g. if a series is started/stopped quickly)
907
+ with self._rule_lock:
908
+ self._rules[ruleID].mark_release_complete(n_tasks)
909
+ return json.dumps({'ok': 'True'})
910
+
911
+ @webframework.register_endpoint('/distributor/queues')
912
+ def get_queues(self):
913
+ """
914
+ HTTP Endpoint (GET) - visible at "distributor/queues" - for querying ruleserver status.
915
+
916
+ Returns
917
+ -------
918
+
919
+ status: json str
920
+ A dictionary of the form ``{"ok" : True, "result" : {ruleID0 : rule0.info(), ruleID1 : rule1.info()}}``
921
+ See :meth:`IntegerIDRule.info`.
922
+ """
923
+ with self._info_lock:
924
+ t = time.time()
925
+ if (t > self._cached_info_expiry):
926
+ with self._rule_lock:
927
+ self._cached_info = json.dumps({'ok': True, 'result': {qn: self._rules[qn].info() for qn in self._rules.keys()}})
928
+ self._cached_info_expiry = time.time() + self._cached_info_timeout
929
+
930
+ return self._cached_info
931
+
932
+ @webframework.register_endpoint('/queue_info_longpoll')
933
+ def get_queue_info(self):
934
+ """
935
+ a throttled version of queue info
936
+
937
+ Returns
938
+ -------
939
+
940
+ """
941
+ time.sleep(0.5)
942
+ return self.get_queues()
943
+
944
+ @webframework.register_endpoint('/', mimetype='text/html')
945
+ def status(self):
946
+ return self._status_page
947
+
948
+
949
+ # class CPRuleServer(RuleServer):
950
+ # @cherrypy.expose
951
+ # def add_integer_rule(self, queue=None, nodeID=None, numWant=50, timeout=5):
952
+ # cherrypy.response.headers['Content-Type'] = 'application/json'
953
+ #
954
+ # body = ''
955
+ # #if cherrypy.request.method == 'GET':
956
+ #
957
+ # if cherrypy.request.method == 'POST':
958
+ # body = cherrypy.request.body.read()
959
+ #
960
+ # return self._tasks(queue, nodeID, numWant, timeout, body)
961
+ #
962
+ # @cherrypy.expose
963
+ # def handin(self, nodeID):
964
+ # cherrypy.response.headers['Content-Type'] = 'application/json'
965
+ #
966
+ # body = cherrypy.request.body.read()
967
+ #
968
+ # return self._handin(nodeID, body)
969
+ #
970
+ # @cherrypy.expose
971
+ # def announce(self, nodeID, ip, port):
972
+ # cherrypy.response.headers['Content-Type'] = 'application/json'
973
+ #
974
+ # self._announce(nodeID, ip, port)
975
+ #
976
+ # @cherrypy.expose
977
+ # def queues(self):
978
+ # cherrypy.response.headers['Content-Type'] = 'application/json'
979
+ #
980
+ # return self._get_queues()
981
+
982
+
983
+ class WFRuleServer(webframework.APIHTTPServer, RuleServer):
984
+ """
985
+ Combines the RuleServer with it's web framework.
986
+
987
+ Largely an artifact of initial experiments using cherrypy (allowed quickly switching between cherrypy
988
+ and our internal webframework).
989
+ """
990
+ def __init__(self, port, bind_addr=''):
991
+ RuleServer.__init__(self)
992
+
993
+ server_address = (bind_addr, port)
994
+ webframework.APIHTTPServer.__init__(self, server_address)
995
+ self.daemon_threads = True
996
+
997
+
998
+ # def runCP(port):
999
+ # import socket
1000
+ # cherrypy.config.update({'server.socket_port': port,
1001
+ # 'server.socket_host': '0.0.0.0',
1002
+ # 'log.screen': False,
1003
+ # 'log.access_file': '',
1004
+ # 'log.error_file': '',
1005
+ # 'server.thread_pool': 50,
1006
+ # })
1007
+ #
1008
+ # logging.getLogger('cherrypy.access').setLevel(logging.ERROR)
1009
+ #
1010
+ # #externalAddr = socket.gethostbyname(socket.gethostname())
1011
+ #
1012
+ # distributor = CPRuleServer()
1013
+ #
1014
+ # app = cherrypy.tree.mount(distributor, '/distributor/')
1015
+ # app.log.access_log.setLevel(logging.ERROR)
1016
+ #
1017
+ # try:
1018
+ #
1019
+ # cherrypy.quickstart()
1020
+ # finally:
1021
+ # distributor._do_poll = False
1022
+
1023
+
1024
+ import threading
1025
+
1026
+ class ServerThread(threading.Thread):
1027
+ """"""
1028
+ def __init__(self, port, bind_addr='', profile=False):
1029
+ self.port = int(port)
1030
+ self._profile = profile
1031
+ self.bind_addr = bind_addr
1032
+ threading.Thread.__init__(self)
1033
+
1034
+ def run(self):
1035
+ """"""
1036
+
1037
+ if self._profile:
1038
+ from PYME.util import mProfile
1039
+
1040
+ mProfile.profileOn(['ruleserver.py', ])
1041
+ profileOutDir = config.get('dataserver-root', os.curdir) + '/LOGS/%s/mProf' % computerName.GetComputerName()
1042
+
1043
+ if self.bind_addr == '':
1044
+ import socket
1045
+ self.externalAddr = socket.gethostbyname(socket.gethostname())
1046
+ else:
1047
+ self.externalAddr = self.bind_addr
1048
+
1049
+ self.distributor = WFRuleServer(self.port, bind_addr=self.bind_addr)
1050
+
1051
+ logger.info('Starting ruleserver on %s:%d' % (self.externalAddr, self.port))
1052
+ try:
1053
+ self.distributor.serve_forever()
1054
+ finally:
1055
+ self.distributor._do_poll = False
1056
+ #logger.info('Shutting down ...')
1057
+ #self.distributor.shutdown()
1058
+ logger.info('Closing server ...')
1059
+ self.distributor.server_close()
1060
+
1061
+ if self._profile:
1062
+ mProfile.report(False, profiledir=profileOutDir)
1063
+
1064
+
1065
+ def shutdown(self):
1066
+ self.distributor._do_poll = False
1067
+ logger.info('Shutting down ...')
1068
+ self.distributor.shutdown()
1069
+ logger.info('Closing server ...')
1070
+ self.distributor.server_close()
1071
+
1072
+
1073
+ def on_SIGHUP(signum, frame):
1074
+ """"""
1075
+ from PYME.util import mProfile
1076
+ mProfile.report(False, profiledir=profileOutDir)
1077
+ raise RuntimeError('Recieved SIGHUP')
1078
+
1079
+
1080
+ if __name__ == '__main__':
1081
+ import signal
1082
+
1083
+ port = sys.argv[1]
1084
+
1085
+ if (len(sys.argv) == 3) and (sys.argv[2] == '-k'):
1086
+ profile = True
1087
+ from PYME.util import mProfile
1088
+
1089
+ mProfile.profileOn(['ruleserver.py', ])
1090
+ profileOutDir = config.get('dataserver-root', os.curdir) + '/LOGS/%s/mProf' % computerName.GetComputerName()
1091
+ else:
1092
+ profile = False
1093
+ profileOutDir = None
1094
+
1095
+ if not sys.platform == 'win32':
1096
+ #windows doesn't support handling signals ... don't catch and hope for the best.
1097
+ #Note: This will make it hard to cleanly shutdown the distributor on Windows, but should be OK for testing and
1098
+ #development
1099
+ signal.signal(signal.SIGHUP, on_SIGHUP)
1100
+
1101
+ try:
1102
+ run(int(port))
1103
+ finally:
1104
+ if profile:
1105
+ mProfile.report(False, profiledir=profileOutDir)
1106
+