python-microscopy 25.6.5__cp39-cp39-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.
- PYME/Acquire/ActionManager.py +450 -0
- PYME/Acquire/ExecTools.py +235 -0
- PYME/Acquire/Hardware/AAOptoelectronics/MDS.py +175 -0
- PYME/Acquire/Hardware/AAOptoelectronics/__init__.py +0 -0
- PYME/Acquire/Hardware/ARCoptix/__init__.py +0 -0
- PYME/Acquire/Hardware/ARCoptix/lcdriver.py +149 -0
- PYME/Acquire/Hardware/ARCoptix/lcserver32.py +123 -0
- PYME/Acquire/Hardware/AndorIXon/AndorCam.py +1095 -0
- PYME/Acquire/Hardware/AndorIXon/AndorControlFrame.py +312 -0
- PYME/Acquire/Hardware/AndorIXon/AndorIXon.py +737 -0
- PYME/Acquire/Hardware/AndorIXon/__init__.py +27 -0
- PYME/Acquire/Hardware/AndorNeo/AndorNeo.py +644 -0
- PYME/Acquire/Hardware/AndorNeo/AndorNeoControlFrame.py +161 -0
- PYME/Acquire/Hardware/AndorNeo/AndorZyla.py +761 -0
- PYME/Acquire/Hardware/AndorNeo/SDK3.py +307 -0
- PYME/Acquire/Hardware/AndorNeo/SDK3Cam.py +171 -0
- PYME/Acquire/Hardware/AndorNeo/ZylaControlPanel.py +105 -0
- PYME/Acquire/Hardware/AndorNeo/__init__.py +22 -0
- PYME/Acquire/Hardware/AndorNeo/parseAtdebug.py +46 -0
- PYME/Acquire/Hardware/AndorNeo/plotTimings.py +73 -0
- PYME/Acquire/Hardware/AndorNeo/testNeo.py +62 -0
- PYME/Acquire/Hardware/Camera.py +1199 -0
- PYME/Acquire/Hardware/CameraSkeleton.py +642 -0
- PYME/Acquire/Hardware/Coherent/OBIS.py +147 -0
- PYME/Acquire/Hardware/Coherent/Sapphire.py +162 -0
- PYME/Acquire/Hardware/Coherent/__init__.py +0 -0
- PYME/Acquire/Hardware/DMDGui.py +198 -0
- PYME/Acquire/Hardware/DigiData/DigiData.py +95 -0
- PYME/Acquire/Hardware/DigiData/DigiDataClient.py +30 -0
- PYME/Acquire/Hardware/DigiData/RemoteDigiData.py +51 -0
- PYME/Acquire/Hardware/DigiData/__init__.py +24 -0
- PYME/Acquire/Hardware/DigiData/axDD132x.py +348 -0
- PYME/Acquire/Hardware/EMCCDTheory.py +41 -0
- PYME/Acquire/Hardware/ExciterWheel.py +167 -0
- PYME/Acquire/Hardware/FilterWheel.py +184 -0
- PYME/Acquire/Hardware/FocCorr.py +106 -0
- PYME/Acquire/Hardware/FocCorrR.py +196 -0
- PYME/Acquire/Hardware/FrFilter.py +51 -0
- PYME/Acquire/Hardware/GCS/GCS_DLL.py +370 -0
- PYME/Acquire/Hardware/GCS/__init__.py +0 -0
- PYME/Acquire/Hardware/GCS/gcs.py +210 -0
- PYME/Acquire/Hardware/HamamatsuDCAM/HamamatsuDCAM.py +662 -0
- PYME/Acquire/Hardware/HamamatsuDCAM/HamamatsuORCA.py +602 -0
- PYME/Acquire/Hardware/HamamatsuDCAM/Hamamatsu_control_panel.py +54 -0
- PYME/Acquire/Hardware/HamamatsuDCAM/__init__.py +23 -0
- PYME/Acquire/Hardware/LaserControlFrame.py +160 -0
- PYME/Acquire/Hardware/MPBCommunications/MPBCW.py +132 -0
- PYME/Acquire/Hardware/MPBCommunications/__init__.py +0 -0
- PYME/Acquire/Hardware/Mercury/Mercury.py +269 -0
- PYME/Acquire/Hardware/Mercury/PI_Mercury_GCS_DLL.py +857 -0
- PYME/Acquire/Hardware/Mercury/__init__.py +22 -0
- PYME/Acquire/Hardware/Mercury/mercuryStepper.py +203 -0
- PYME/Acquire/Hardware/Mercury/mercuryStepperGCS.py +281 -0
- PYME/Acquire/Hardware/NikonTE2000.py +68 -0
- PYME/Acquire/Hardware/NikonTi.py +214 -0
- PYME/Acquire/Hardware/NikonTiGUI.py +81 -0
- PYME/Acquire/Hardware/OrielCornerstone.py +125 -0
- PYME/Acquire/Hardware/PM100USB.py +51 -0
- PYME/Acquire/Hardware/Piezos/__init__.py +22 -0
- PYME/Acquire/Hardware/Piezos/base_piezo.py +108 -0
- PYME/Acquire/Hardware/Piezos/offsetPiezo.py +162 -0
- PYME/Acquire/Hardware/Piezos/offsetPiezoREST.py +308 -0
- PYME/Acquire/Hardware/Piezos/piezo_c867.py +486 -0
- PYME/Acquire/Hardware/Piezos/piezo_e255.py +68 -0
- PYME/Acquire/Hardware/Piezos/piezo_e662.py +61 -0
- PYME/Acquire/Hardware/Piezos/piezo_e709.py +434 -0
- PYME/Acquire/Hardware/Piezos/piezo_e816.py +452 -0
- PYME/Acquire/Hardware/Piezos/piezo_e816_corr.py +70 -0
- PYME/Acquire/Hardware/Piezos/piezo_e816_dll.py +518 -0
- PYME/Acquire/Hardware/Piezos/piezo_e816b.py +70 -0
- PYME/Acquire/Hardware/Piezos/piezo_pipython_gcs.py +560 -0
- PYME/Acquire/Hardware/Piezos/piezo_test.py +55 -0
- PYME/Acquire/Hardware/Simulator/EmpiricalHist.py +273 -0
- PYME/Acquire/Hardware/Simulator/__init__.py +22 -0
- PYME/Acquire/Hardware/Simulator/dSimControl.py +961 -0
- PYME/Acquire/Hardware/Simulator/fakeCam.py +651 -0
- PYME/Acquire/Hardware/Simulator/fakePiezo.py +95 -0
- PYME/Acquire/Hardware/Simulator/fluor.py +336 -0
- PYME/Acquire/Hardware/Simulator/illuminate.cp39-win_amd64.dll.a +0 -0
- PYME/Acquire/Hardware/Simulator/illuminate.cp39-win_amd64.pyd +0 -0
- PYME/Acquire/Hardware/Simulator/illuminate.pyx +93 -0
- PYME/Acquire/Hardware/Simulator/lasersliders.py +90 -0
- PYME/Acquire/Hardware/Simulator/rend_im.py +446 -0
- PYME/Acquire/Hardware/Simulator/setup.py +69 -0
- PYME/Acquire/Hardware/Simulator/simcontrol.py +348 -0
- PYME/Acquire/Hardware/Simulator/simui_wx.py +794 -0
- PYME/Acquire/Hardware/Tango/__init__.py +0 -0
- PYME/Acquire/Hardware/Tango/marzhauser_tango.py +583 -0
- PYME/Acquire/Hardware/TiLightCrafter.py +388 -0
- PYME/Acquire/Hardware/__init__.py +22 -0
- PYME/Acquire/Hardware/aotf.py +271 -0
- PYME/Acquire/Hardware/arclampshutterpanel.py +71 -0
- PYME/Acquire/Hardware/cameraSoftwareBuffer.py +215 -0
- PYME/Acquire/Hardware/camera_noise.py +270 -0
- PYME/Acquire/Hardware/ccdAdjPanel.py +188 -0
- PYME/Acquire/Hardware/ccdCalibrator.py +161 -0
- PYME/Acquire/Hardware/cobaltLaser.py +108 -0
- PYME/Acquire/Hardware/cobaltLaser561.py +94 -0
- PYME/Acquire/Hardware/comports.py +26 -0
- PYME/Acquire/Hardware/driftTrackGUI.py +488 -0
- PYME/Acquire/Hardware/driftTracking.py +595 -0
- PYME/Acquire/Hardware/fakeShutters.py +52 -0
- PYME/Acquire/Hardware/focusKeys.py +204 -0
- PYME/Acquire/Hardware/focus_locks/__init__.py +0 -0
- PYME/Acquire/Hardware/focus_locks/reflection_focus_lock.py +684 -0
- PYME/Acquire/Hardware/frZStage.py +117 -0
- PYME/Acquire/Hardware/fw102.py +38 -0
- PYME/Acquire/Hardware/ids_peak_cam.py +561 -0
- PYME/Acquire/Hardware/ioslave.py +305 -0
- PYME/Acquire/Hardware/lasers.py +292 -0
- PYME/Acquire/Hardware/matchboxLaser.py +58 -0
- PYME/Acquire/Hardware/microscope_adapter.py +104 -0
- PYME/Acquire/Hardware/mpd_picosecond_delayer.py +395 -0
- PYME/Acquire/Hardware/multiview.py +287 -0
- PYME/Acquire/Hardware/olympusix81.py +59 -0
- PYME/Acquire/Hardware/pco/__init__.py +0 -0
- PYME/Acquire/Hardware/pco/pco_cam.py +348 -0
- PYME/Acquire/Hardware/pco/pco_edge_42_lt.py +34 -0
- PYME/Acquire/Hardware/pco/pco_sdk.py +1645 -0
- PYME/Acquire/Hardware/pco/pco_sdk_cam.py +518 -0
- PYME/Acquire/Hardware/pco/pco_sdk_cam_control_panel.py +54 -0
- PYME/Acquire/Hardware/phoxxLaser.py +199 -0
- PYME/Acquire/Hardware/phoxxLaserOLD.py +242 -0
- PYME/Acquire/Hardware/priorLumen.py +102 -0
- PYME/Acquire/Hardware/priorarclampshutter.py +52 -0
- PYME/Acquire/Hardware/setup.py +50 -0
- PYME/Acquire/Hardware/spacenav.py +148 -0
- PYME/Acquire/Hardware/splitter.py +394 -0
- PYME/Acquire/Hardware/thorlabsPiezo.py +98 -0
- PYME/Acquire/Hardware/thorlabs_cam.py +136 -0
- PYME/Acquire/Hardware/thorlabs_mff_flipper.py +400 -0
- PYME/Acquire/Hardware/toptica_ibeam.py +51 -0
- PYME/Acquire/Hardware/uc480/AndorControlFrame.py +308 -0
- PYME/Acquire/Hardware/uc480/__init__.py +27 -0
- PYME/Acquire/Hardware/uc480/uCam480.py +695 -0
- PYME/Acquire/Hardware/uc480/uc480.py +189 -0
- PYME/Acquire/Hardware/uc480/uc480Deprecated.py +87 -0
- PYME/Acquire/Hardware/uc480/uc480_h.py +767 -0
- PYME/Acquire/Hardware/uc480/uc480_h_gen.py +62 -0
- PYME/Acquire/Hardware/uc480/ucCamControlFrame.py +83 -0
- PYME/Acquire/Hardware/ueye.py +702 -0
- PYME/Acquire/PYMEAcquire.py +186 -0
- PYME/Acquire/Protocols/DMDMFM.py +74 -0
- PYME/Acquire/Protocols/__init__.py +22 -0
- PYME/Acquire/Protocols/darkCalibrate.py +56 -0
- PYME/Acquire/Protocols/dual671_470.py +45 -0
- PYME/Acquire/Protocols/dual671_488.py +46 -0
- PYME/Acquire/Protocols/gainCal.py +53 -0
- PYME/Acquire/Protocols/htsms-cal-psf.py +32 -0
- PYME/Acquire/Protocols/htsms-cal-registration.py +52 -0
- PYME/Acquire/Protocols/htsms-flow.py +29 -0
- PYME/Acquire/Protocols/htsms-staggered.py +31 -0
- PYME/Acquire/Protocols/htsms-tile.py +68 -0
- PYME/Acquire/Protocols/htsms-two-color.py +29 -0
- PYME/Acquire/Protocols/htsms-widefield.py +32 -0
- PYME/Acquire/Protocols/paint671.py +61 -0
- PYME/Acquire/Protocols/photoconversion.py +52 -0
- PYME/Acquire/Protocols/photoconversion2.py +55 -0
- PYME/Acquire/Protocols/prebleach488.py +70 -0
- PYME/Acquire/Protocols/prebleach490.py +69 -0
- PYME/Acquire/Protocols/prebleach561.py +72 -0
- PYME/Acquire/Protocols/prebleach561NeomEos2.py +70 -0
- PYME/Acquire/Protocols/prebleach561NeomEos2ND1.py +70 -0
- PYME/Acquire/Protocols/prebleach642.py +70 -0
- PYME/Acquire/Protocols/prebleach671.py +69 -0
- PYME/Acquire/Protocols/prebleach671ND1.py +58 -0
- PYME/Acquire/Protocols/prebleach671ND2.py +57 -0
- PYME/Acquire/Protocols/prebleach671Neo.py +69 -0
- PYME/Acquire/Protocols/recover671.py +62 -0
- PYME/Acquire/Protocols/sequence642_488.py +85 -0
- PYME/Acquire/Protocols/sequence642_561.py +87 -0
- PYME/Acquire/Protocols/shiftfield.py +198 -0
- PYME/Acquire/Protocols/simul488.py +59 -0
- PYME/Acquire/Protocols/simul642.py +63 -0
- PYME/Acquire/Protocols/simul642HTSMS.py +63 -0
- PYME/Acquire/Protocols/simulPA.py +37 -0
- PYME/Acquire/Protocols/simulSIM.py +76 -0
- PYME/Acquire/Protocols/simulStep.py +62 -0
- PYME/Acquire/Protocols/spdscan.py +178 -0
- PYME/Acquire/Protocols/standard470.py +45 -0
- PYME/Acquire/Protocols/standard488.py +47 -0
- PYME/Acquire/Protocols/standard671.py +48 -0
- PYME/Acquire/Protocols/standard671_no532.py +47 -0
- PYME/Acquire/Protocols/standardArclamp.py +46 -0
- PYME/Acquire/Protocols/strip_tile.py +204 -0
- PYME/Acquire/Protocols/tile.py +204 -0
- PYME/Acquire/Protocols/tile3D.py +192 -0
- PYME/Acquire/Protocols/tile671.py +190 -0
- PYME/Acquire/Protocols/tile_triggered.py +189 -0
- PYME/Acquire/Scripts/init.py +232 -0
- PYME/Acquire/Scripts/init_N1_Ti_Exeter_ZIx.py +374 -0
- PYME/Acquire/Scripts/init_N2_Ti_Zyla_lasers.py +290 -0
- PYME/Acquire/Scripts/init_Neo.py +266 -0
- PYME/Acquire/Scripts/init_NeoSim.py +159 -0
- PYME/Acquire/Scripts/init_TIRF.py +232 -0
- PYME/Acquire/Scripts/init_TIRF_Neo.py +242 -0
- PYME/Acquire/Scripts/init_TIRF_NeoO.py +241 -0
- PYME/Acquire/Scripts/init_TIRF_onecam.py +233 -0
- PYME/Acquire/Scripts/init_Ti.py +257 -0
- PYME/Acquire/Scripts/init_UOA_n.py +256 -0
- PYME/Acquire/Scripts/init_UOA_n2.py +246 -0
- PYME/Acquire/Scripts/init_Y1.py +249 -0
- PYME/Acquire/Scripts/init_Zyla.py +260 -0
- PYME/Acquire/Scripts/init_drift_tracking.py +80 -0
- PYME/Acquire/Scripts/init_emccd_basic.py +277 -0
- PYME/Acquire/Scripts/init_htsms.py +277 -0
- PYME/Acquire/Scripts/init_htsms_focus_lock.py +132 -0
- PYME/Acquire/Scripts/init_micrpi.py +45 -0
- PYME/Acquire/Scripts/init_orca.py +70 -0
- PYME/Acquire/Scripts/init_pco.py +49 -0
- PYME/Acquire/Scripts/init_rev.py +74 -0
- PYME/Acquire/Scripts/init_sim100.py +169 -0
- PYME/Acquire/Scripts/init_sim103.py +169 -0
- PYME/Acquire/Scripts/init_sim2.py +211 -0
- PYME/Acquire/Scripts/init_sim50.py +169 -0
- PYME/Acquire/Scripts/init_sim75.py +169 -0
- PYME/Acquire/Scripts/init_sim_drift_tracking.py +166 -0
- PYME/Acquire/Scripts/init_sim_htsms.py +224 -0
- PYME/Acquire/Scripts/init_sim_htsms_n.py +233 -0
- PYME/Acquire/Scripts/init_sim_main.py +229 -0
- PYME/Acquire/Scripts/init_sim_min.py +197 -0
- PYME/Acquire/Scripts/init_sim_rem.py +176 -0
- PYME/Acquire/Scripts/init_smi1.py +110 -0
- PYME/Acquire/Scripts/init_spectro.py +78 -0
- PYME/Acquire/Scripts/init_spim.py +116 -0
- PYME/Acquire/Scripts/init_thorcam.py +62 -0
- PYME/Acquire/Scripts/init_twophoton.py +112 -0
- PYME/Acquire/Scripts/init_uc480.py +262 -0
- PYME/Acquire/Scripts/init_ueye.py +261 -0
- PYME/Acquire/SpoolController.py +958 -0
- PYME/Acquire/Utils/MultiPointScanner.py +80 -0
- PYME/Acquire/Utils/__init__.py +13 -0
- PYME/Acquire/Utils/failsafe.py +157 -0
- PYME/Acquire/Utils/fastTiler.py +153 -0
- PYME/Acquire/Utils/pointScanner.py +496 -0
- PYME/Acquire/Utils/sarcSpacing.py +86 -0
- PYME/Acquire/Utils/strip_tiler.py +93 -0
- PYME/Acquire/Utils/tiler.py +464 -0
- PYME/Acquire/Utils/vibrationAnalysis.py +65 -0
- PYME/Acquire/__init__.py +44 -0
- PYME/Acquire/acquire_client.py +90 -0
- PYME/Acquire/acquire_server.py +316 -0
- PYME/Acquire/acquirebase.py +139 -0
- PYME/Acquire/acquiremainframe.py +716 -0
- PYME/Acquire/acquirewx.py +61 -0
- PYME/Acquire/acquisition_base.py +148 -0
- PYME/Acquire/actions.py +209 -0
- PYME/Acquire/autofocus.py +54 -0
- PYME/Acquire/eventLog.py +95 -0
- PYME/Acquire/event_loop.py +119 -0
- PYME/Acquire/frameWrangler.py +530 -0
- PYME/Acquire/htsms/__init__.py +8 -0
- PYME/Acquire/htsms/rule_ui.py +970 -0
- PYME/Acquire/htsms/rule_ui_v2.py +573 -0
- PYME/Acquire/htsms/tweeter.py +222 -0
- PYME/Acquire/microscope.py +1050 -0
- PYME/Acquire/positionTracker.py +181 -0
- PYME/Acquire/protocol.py +299 -0
- PYME/Acquire/protocol_acquisition.py +404 -0
- PYME/Acquire/sampleInformation.py +591 -0
- PYME/Acquire/sampleInformationDjangoDirect.py +446 -0
- PYME/Acquire/setup.py +52 -0
- PYME/Acquire/stackSettings.py +295 -0
- PYME/Acquire/stage_leveling.py +285 -0
- PYME/Acquire/ui/AnalysisSettingsUI.py +184 -0
- PYME/Acquire/ui/HDFSpoolFrame.py +584 -0
- PYME/Acquire/ui/__init__.py +0 -0
- PYME/Acquire/ui/actionUI.py +892 -0
- PYME/Acquire/ui/focus_lock_gui.py +149 -0
- PYME/Acquire/ui/intensity_trace.py +143 -0
- PYME/Acquire/ui/intsliders.py +222 -0
- PYME/Acquire/ui/lasersliders.py +329 -0
- PYME/Acquire/ui/mpd_picosecond_delay_panel.py +69 -0
- PYME/Acquire/ui/multiview_select.py +77 -0
- PYME/Acquire/ui/positionUI.py +519 -0
- PYME/Acquire/ui/preflight.py +58 -0
- PYME/Acquire/ui/scanner_panel.py +41 -0
- PYME/Acquire/ui/selectCameraPanel.py +46 -0
- PYME/Acquire/ui/seqdialog.py +501 -0
- PYME/Acquire/ui/splashScreen.py +175 -0
- PYME/Acquire/ui/spool_panel.py +830 -0
- PYME/Acquire/ui/tile_panel.py +556 -0
- PYME/Acquire/ui/tilesettingsui.py +91 -0
- PYME/Acquire/ui/voxelSizeDialog.py +149 -0
- PYME/Acquire/webui/__init__.py +36 -0
- PYME/Acquire/webui/ipy.py +361 -0
- PYME/Acquire/webui/static/css/pyme-bootstrap.css +9908 -0
- PYME/Acquire/webui/static/css/pymeacquire.css +85 -0
- PYME/Acquire/webui/static/js/pymeacquire.js +375 -0
- PYME/Acquire/webui/static/js/pzf.js +95 -0
- PYME/Acquire/webui/templates/PYMEAcquire.html +232 -0
- PYME/Acquire/webui/templates/login.html +84 -0
- PYME/Acquire/webui/templates/xtermpage.html +106 -0
- PYME/Acquire/xyztc.py +418 -0
- PYME/Acquire/zScanner.py +287 -0
- PYME/Analysis/BleachProfile/__init__.py +26 -0
- PYME/Analysis/BleachProfile/deMod.py +91 -0
- PYME/Analysis/BleachProfile/fitRecover.py +90 -0
- PYME/Analysis/BleachProfile/intensProf.py +519 -0
- PYME/Analysis/BleachProfile/kinModels.py +507 -0
- PYME/Analysis/BleachProfile/rawIntensity.py +227 -0
- PYME/Analysis/BleachProfile/rollins.py +555 -0
- PYME/Analysis/Colocalisation/__init__.py +27 -0
- PYME/Analysis/Colocalisation/colocScaleDep.py +126 -0
- PYME/Analysis/Colocalisation/correlationCoeffs.py +198 -0
- PYME/Analysis/Colocalisation/distColoc.py +110 -0
- PYME/Analysis/Colocalisation/edtColoc.py +191 -0
- PYME/Analysis/MetaData.py +278 -0
- PYME/Analysis/PSFEst/__init__.py +27 -0
- PYME/Analysis/PSFEst/dec.py +283 -0
- PYME/Analysis/PSFEst/extractImages.py +316 -0
- PYME/Analysis/PSFEst/fit_psf_zernikes.py +194 -0
- PYME/Analysis/PSFEst/psfQuality.py +225 -0
- PYME/Analysis/PSFGen/__init__.py +40 -0
- PYME/Analysis/PSFGen/fourier.py +138 -0
- PYME/Analysis/PSFGen/fourierHNA.py +1108 -0
- PYME/Analysis/PSFGen/fourierHNA2.py +979 -0
- PYME/Analysis/PSFGen/genCRBcurves.py +185 -0
- PYME/Analysis/PSFGen/nijboer_zernike.py +79 -0
- PYME/Analysis/PSFGen/ps_app.cp39-win_amd64.dll.a +0 -0
- PYME/Analysis/PSFGen/ps_app.cp39-win_amd64.pyd +0 -0
- PYME/Analysis/PSFGen/test_ps_app.py +24 -0
- PYME/Analysis/Tracking/__init__.py +3 -0
- PYME/Analysis/Tracking/msd.py +57 -0
- PYME/Analysis/Tracking/trackUtils.py +528 -0
- PYME/Analysis/Tracking/tracking.py +152 -0
- PYME/Analysis/__init__.py +30 -0
- PYME/Analysis/_fithelpers.py +161 -0
- PYME/Analysis/angleFilter.py +287 -0
- PYME/Analysis/annealThresh.py +157 -0
- PYME/Analysis/autoencoder_classifier.py +45 -0
- PYME/Analysis/binAvg.py +144 -0
- PYME/Analysis/composite.py +183 -0
- PYME/Analysis/cramerRao.py +259 -0
- PYME/Analysis/deTile.py +441 -0
- PYME/Analysis/density_filter.py +45 -0
- PYME/Analysis/distributed_pyramid.py +426 -0
- PYME/Analysis/fiducial_matching.py +220 -0
- PYME/Analysis/gen_sCMOS_maps.py +355 -0
- PYME/Analysis/graphing_filters.py +311 -0
- PYME/Analysis/implicitFilter.py +359 -0
- PYME/Analysis/keep_pairs.py +69 -0
- PYME/Analysis/optic_flow.py +108 -0
- PYME/Analysis/piecewise.py +36 -0
- PYME/Analysis/piecewiseMapping.py +304 -0
- PYME/Analysis/piezo_movement_correction.py +153 -0
- PYME/Analysis/points/DeClump/__init__.py +78 -0
- PYME/Analysis/points/DeClump/deClump.cp39-win_amd64.dll.a +0 -0
- PYME/Analysis/points/DeClump/deClump.cp39-win_amd64.pyd +0 -0
- PYME/Analysis/points/DeClump/deClumpGUI.py +87 -0
- PYME/Analysis/points/DeClump/pyDeClump.py +284 -0
- PYME/Analysis/points/DeClump/testClump.py +40 -0
- PYME/Analysis/points/DistHist/__init__.py +25 -0
- PYME/Analysis/points/DistHist/distHist.cp39-win_amd64.dll.a +0 -0
- PYME/Analysis/points/DistHist/distHist.cp39-win_amd64.pyd +0 -0
- PYME/Analysis/points/DistHist/distHistThreaded.py +71 -0
- PYME/Analysis/points/DistHist/setup.py +54 -0
- PYME/Analysis/points/EdgeDB/__init__.py +24 -0
- PYME/Analysis/points/EdgeDB/edgeDB.cp39-win_amd64.dll.a +0 -0
- PYME/Analysis/points/EdgeDB/edgeDB.cp39-win_amd64.pyd +0 -0
- PYME/Analysis/points/EdgeDB/edgeTest.py +66 -0
- PYME/Analysis/points/EdgeDB/edges.py +102 -0
- PYME/Analysis/points/EdgeDB/segment.py +75 -0
- PYME/Analysis/points/EdgeDB/setup.py +54 -0
- PYME/Analysis/points/QuadTree/QTrend.py +232 -0
- PYME/Analysis/points/QuadTree/__init__.py +25 -0
- PYME/Analysis/points/QuadTree/pointQT.py +227 -0
- PYME/Analysis/points/QuadTree/pointQTF.py +254 -0
- PYME/Analysis/points/QuadTree/qtUtils.py +36 -0
- PYME/Analysis/points/QuadTree/rendQT.py +118 -0
- PYME/Analysis/points/SoftRend/__init__.py +24 -0
- PYME/Analysis/points/SoftRend/setup.py +61 -0
- PYME/Analysis/points/SoftRend/testTetrahedra.py +41 -0
- PYME/Analysis/points/SoftRend/triRend.cp39-win_amd64.dll.a +0 -0
- PYME/Analysis/points/SoftRend/triRend.cp39-win_amd64.pyd +0 -0
- PYME/Analysis/points/__init__.py +3 -0
- PYME/Analysis/points/arcfit/__init__.py +1 -0
- PYME/Analysis/points/arcfit/arcmf.cp39-win_amd64.dll.a +0 -0
- PYME/Analysis/points/arcfit/arcmf.cp39-win_amd64.pyd +0 -0
- PYME/Analysis/points/arcfit/setup.py +51 -0
- PYME/Analysis/points/astigmatism/__init__.py +0 -0
- PYME/Analysis/points/astigmatism/astigTools.py +338 -0
- PYME/Analysis/points/astigmatism/astiglookup.cp39-win_amd64.dll.a +0 -0
- PYME/Analysis/points/astigmatism/astiglookup.cp39-win_amd64.pyd +0 -0
- PYME/Analysis/points/astigmatism/setup.py +54 -0
- PYME/Analysis/points/cluster_morphology.py +199 -0
- PYME/Analysis/points/coordinate_tools.py +278 -0
- PYME/Analysis/points/features/__init__.py +0 -0
- PYME/Analysis/points/features/metal.py +46 -0
- PYME/Analysis/points/features/shaders/vect_feat_3d.metal +49 -0
- PYME/Analysis/points/fiducials.py +142 -0
- PYME/Analysis/points/gen3DTriangs.py +796 -0
- PYME/Analysis/points/moments.py +143 -0
- PYME/Analysis/points/multiview.py +458 -0
- PYME/Analysis/points/objectMeasure.py +206 -0
- PYME/Analysis/points/qpaint.py +97 -0
- PYME/Analysis/points/rings.py +372 -0
- PYME/Analysis/points/ripleys.py +427 -0
- PYME/Analysis/points/segmentLL.py +134 -0
- PYME/Analysis/points/setup.py +56 -0
- PYME/Analysis/points/spherical_harmonics.py +909 -0
- PYME/Analysis/points/surfit.py +829 -0
- PYME/Analysis/points/tCluster.py +75 -0
- PYME/Analysis/points/traveling_salesperson/__init__.py +0 -0
- PYME/Analysis/points/traveling_salesperson/queue_opt.py +117 -0
- PYME/Analysis/points/traveling_salesperson/sectioned_two_opt.py +327 -0
- PYME/Analysis/points/traveling_salesperson/setup.py +40 -0
- PYME/Analysis/points/traveling_salesperson/sort.py +78 -0
- PYME/Analysis/points/traveling_salesperson/two_opt.py +189 -0
- PYME/Analysis/points/traveling_salesperson/two_opt_utils.cp39-win_amd64.dll.a +0 -0
- PYME/Analysis/points/traveling_salesperson/two_opt_utils.cp39-win_amd64.pyd +0 -0
- PYME/Analysis/points/traveling_salesperson/two_opt_utils.pyx +41 -0
- PYME/Analysis/points/twoColour.py +572 -0
- PYME/Analysis/points/twoColourPlot.py +107 -0
- PYME/Analysis/processLogger.py +129 -0
- PYME/Analysis/profile_extraction.py +72 -0
- PYME/Analysis/setup.py +60 -0
- PYME/Analysis/splitting.py +372 -0
- PYME/Analysis/svmSegment.py +214 -0
- PYME/Analysis/thresholding.py +192 -0
- PYME/Analysis/tile_pyramid.py +938 -0
- PYME/Analysis/widefieldify.py +54 -0
- PYME/DSView/DisplayOptionsPanel.py +503 -0
- PYME/DSView/LUT/__init__.py +33 -0
- PYME/DSView/LUT/lut.cp39-win_amd64.dll.a +0 -0
- PYME/DSView/LUT/lut.cp39-win_amd64.pyd +0 -0
- PYME/DSView/LUT/setup.py +54 -0
- PYME/DSView/OpenSequenceDialog.py +83 -0
- PYME/DSView/OverlaysPanel.py +111 -0
- PYME/DSView/__init__.py +32 -0
- PYME/DSView/arrayViewPanel.py +1035 -0
- PYME/DSView/displayOptions.py +453 -0
- PYME/DSView/displaySettingsPanel.py +271 -0
- PYME/DSView/dsviewer.py +542 -0
- PYME/DSView/eventLogViewer.py +805 -0
- PYME/DSView/fitInfo.py +486 -0
- PYME/DSView/htmlServe.py +72 -0
- PYME/DSView/logparser.py +100 -0
- PYME/DSView/modules/LMAnalysis.py +1053 -0
- PYME/DSView/modules/LMDisplay.py +194 -0
- PYME/DSView/modules/__init__.py +162 -0
- PYME/DSView/modules/_base.py +39 -0
- PYME/DSView/modules/annotation.py +725 -0
- PYME/DSView/modules/arrayView.py +71 -0
- PYME/DSView/modules/blobFinding.py +455 -0
- PYME/DSView/modules/blobMeasure.py +1093 -0
- PYME/DSView/modules/camera_maps.py +38 -0
- PYME/DSView/modules/coloc.py +414 -0
- PYME/DSView/modules/composite.py +715 -0
- PYME/DSView/modules/convnet.py +24 -0
- PYME/DSView/modules/cropping.py +133 -0
- PYME/DSView/modules/dark_and_flatfield.py +31 -0
- PYME/DSView/modules/deconvolution.py +499 -0
- PYME/DSView/modules/eventView.py +80 -0
- PYME/DSView/modules/extractBlobs.py +46 -0
- PYME/DSView/modules/fastGraphPanel.py +85 -0
- PYME/DSView/modules/filtering.py +335 -0
- PYME/DSView/modules/flowView.py +268 -0
- PYME/DSView/modules/fourierRingCorrelation.py +172 -0
- PYME/DSView/modules/gl_image_view.py +12 -0
- PYME/DSView/modules/graphViewPanel.py +272 -0
- PYME/DSView/modules/measure/__init__.py +1 -0
- PYME/DSView/modules/measure/filterPan.py +239 -0
- PYME/DSView/modules/metadataView.py +28 -0
- PYME/DSView/modules/multithreshold.py +98 -0
- PYME/DSView/modules/neuroglancer.py +129 -0
- PYME/DSView/modules/object_tagging.py +157 -0
- PYME/DSView/modules/particleTracking.py +463 -0
- PYME/DSView/modules/playback.py +256 -0
- PYME/DSView/modules/prebleachExtraction.py +75 -0
- PYME/DSView/modules/profileFitting.py +137 -0
- PYME/DSView/modules/profilePlotting.py +408 -0
- PYME/DSView/modules/projections.py +48 -0
- PYME/DSView/modules/psfExtraction.py +570 -0
- PYME/DSView/modules/psfGeneration.py +138 -0
- PYME/DSView/modules/psfTools.py +661 -0
- PYME/DSView/modules/pupilTools.py +204 -0
- PYME/DSView/modules/pupilView.py +139 -0
- PYME/DSView/modules/recipes.py +266 -0
- PYME/DSView/modules/redimension.py +75 -0
- PYME/DSView/modules/segmentation.py +192 -0
- PYME/DSView/modules/sheetView.py +24 -0
- PYME/DSView/modules/shell.py +39 -0
- PYME/DSView/modules/shiftfield_estimation.py +433 -0
- PYME/DSView/modules/sparkprepare.py +94 -0
- PYME/DSView/modules/splitter.py +148 -0
- PYME/DSView/modules/synchronise.py +64 -0
- PYME/DSView/modules/templates/astigCal.html +42 -0
- PYME/DSView/modules/templates/measureView.html +69 -0
- PYME/DSView/modules/templates/measureView2.html +48 -0
- PYME/DSView/modules/templates/measureView3.html +98 -0
- PYME/DSView/modules/templates/trackView.html +139 -0
- PYME/DSView/modules/templates/tracksOverview.html +21 -0
- PYME/DSView/modules/tiling.py +147 -0
- PYME/DSView/modules/unmixing.py +148 -0
- PYME/DSView/modules/vis3D.py +320 -0
- PYME/DSView/modules/visgui.py +163 -0
- PYME/DSView/modules/webview.py +14 -0
- PYME/DSView/overlays.py +295 -0
- PYME/DSView/scrolledImagePanel.py +188 -0
- PYME/DSView/setup.py +53 -0
- PYME/DSView/splashScreen.py +158 -0
- PYME/DSView/voxSizeDialog.py +84 -0
- PYME/Deconv/__init__.py +35 -0
- PYME/Deconv/beadGen.py +55 -0
- PYME/Deconv/dec.py +659 -0
- PYME/Deconv/decTask.py +65 -0
- PYME/Deconv/decThread.py +113 -0
- PYME/Deconv/dec_test.py +47 -0
- PYME/Deconv/deconvDialogs.py +417 -0
- PYME/Deconv/fftwWisdom.py +62 -0
- PYME/Deconv/richardsonLucy.py +141 -0
- PYME/Deconv/richardsonLucyMV.py +151 -0
- PYME/Deconv/richardsonLucyMVM.py +218 -0
- PYME/Deconv/test_block_dec.py +46 -0
- PYME/Deconv/tq_block_dec.py +331 -0
- PYME/Deconv/wiener.py +163 -0
- PYME/IO/DataSources/AlignDataSource.py +91 -0
- PYME/IO/DataSources/ArrayDataSource.py +260 -0
- PYME/IO/DataSources/BGSDataSource.py +353 -0
- PYME/IO/DataSources/BaseDataSource.py +457 -0
- PYME/IO/DataSources/BioformatsDataSource.py +178 -0
- PYME/IO/DataSources/BufferedDataSource.py +99 -0
- PYME/IO/DataSources/ClusterPZFDataSource.py +124 -0
- PYME/IO/DataSources/ConcatenatedDataSource.py +56 -0
- PYME/IO/DataSources/CropDataSource.py +243 -0
- PYME/IO/DataSources/DcimgDataSource.py +54 -0
- PYME/IO/DataSources/ElectronsPerSecondDataSource.py +61 -0
- PYME/IO/DataSources/FlatFieldDataSource.py +77 -0
- PYME/IO/DataSources/HDFDataSource.py +160 -0
- PYME/IO/DataSources/HTTPDataSource.py +80 -0
- PYME/IO/DataSources/ImageSeriesDataSource.py +123 -0
- PYME/IO/DataSources/MultiviewDataSource.py +99 -0
- PYME/IO/DataSources/OBFDataSource.py +67 -0
- PYME/IO/DataSources/RandomDataSource.py +23 -0
- PYME/IO/DataSources/SupertileDatasource.py +148 -0
- PYME/IO/DataSources/TQDataSource.py +41 -0
- PYME/IO/DataSources/TiffDataSource.py +193 -0
- PYME/IO/DataSources/TileDataSource.py +91 -0
- PYME/IO/DataSources/UnsplitDataSource.py +92 -0
- PYME/IO/DataSources/__init__.py +59 -0
- PYME/IO/FileUtils/IJLut.py +43 -0
- PYME/IO/FileUtils/RawToHdf5.py +105 -0
- PYME/IO/FileUtils/SPAD.py +54 -0
- PYME/IO/FileUtils/TiffSeqToHdf5.py +87 -0
- PYME/IO/FileUtils/__init__.py +24 -0
- PYME/IO/FileUtils/compHdf.py +39 -0
- PYME/IO/FileUtils/fileID.py +246 -0
- PYME/IO/FileUtils/fnlGen.py +40 -0
- PYME/IO/FileUtils/freeSpace.py +59 -0
- PYME/IO/FileUtils/h5-thumbnailer.py +85 -0
- PYME/IO/FileUtils/h5ExFrames.py +98 -0
- PYME/IO/FileUtils/h5ToTiffSeries.py +50 -0
- PYME/IO/FileUtils/h5r-thumbnailer.py +118 -0
- PYME/IO/FileUtils/h5rFormatDef.py +99 -0
- PYME/IO/FileUtils/h5rToTxt.py +77 -0
- PYME/IO/FileUtils/nameUtils.py +300 -0
- PYME/IO/FileUtils/obf_support.py +538 -0
- PYME/IO/FileUtils/ply.py +147 -0
- PYME/IO/FileUtils/readSpeckle.py +78 -0
- PYME/IO/FileUtils/readTiff.py +64 -0
- PYME/IO/FileUtils/saveTiffStack.py +137 -0
- PYME/IO/FileUtils/setup.py +36 -0
- PYME/IO/FileUtils/sf-thumbnailer.py +76 -0
- PYME/IO/FileUtils/stl.py +44 -0
- PYME/IO/FileUtils/thumbnailDatabase.py +104 -0
- PYME/IO/HTTPSpooler_v2.py +141 -0
- PYME/IO/MetaDataHandler.py +1072 -0
- PYME/IO/PZFFormat.py +375 -0
- PYME/IO/Spooler.py +279 -0
- PYME/IO/__init__.py +12 -0
- PYME/IO/acquisition_backends.py +353 -0
- PYME/IO/buffer_helpers.cp39-win_amd64.dll.a +0 -0
- PYME/IO/buffer_helpers.cp39-win_amd64.pyd +0 -0
- PYME/IO/buffer_helpers.pyx +190 -0
- PYME/IO/buffers.py +291 -0
- PYME/IO/clusterDuplication.py +204 -0
- PYME/IO/clusterExport.py +152 -0
- PYME/IO/clusterGlob.py +108 -0
- PYME/IO/clusterIO.py +1076 -0
- PYME/IO/clusterListing.py +232 -0
- PYME/IO/clusterResults.py +206 -0
- PYME/IO/clusterUpload.py +49 -0
- PYME/IO/cluster_directory.py +419 -0
- PYME/IO/cluster_streaming.py +216 -0
- PYME/IO/compatibility.py +12 -0
- PYME/IO/countdir/__init__.py +5 -0
- PYME/IO/countdir/setup.py +58 -0
- PYME/IO/csv_flavours.py +251 -0
- PYME/IO/dataExporter.py +470 -0
- PYME/IO/dataWrap.py +108 -0
- PYME/IO/dcimg.py +167 -0
- PYME/IO/events.py +161 -0
- PYME/IO/h5File.py +148 -0
- PYME/IO/h5rFile.py +323 -0
- PYME/IO/image.py +1447 -0
- PYME/IO/load_psf.py +26 -0
- PYME/IO/pyme_h5ls.py +58 -0
- PYME/IO/ragged.py +138 -0
- PYME/IO/rgb_image.py +94 -0
- PYME/IO/tabular.py +1338 -0
- PYME/IO/testClusterSpooling.py +199 -0
- PYME/IO/unifiedIO.py +301 -0
- PYME/LMVis/Extras/QPobjectSegment.py +220 -0
- PYME/LMVis/Extras/__init__.py +55 -0
- PYME/LMVis/Extras/animation.py +359 -0
- PYME/LMVis/Extras/annotation.py +78 -0
- PYME/LMVis/Extras/clusterAnalysis.py +460 -0
- PYME/LMVis/Extras/dockedPanel.py +69 -0
- PYME/LMVis/Extras/extra_layers.py +373 -0
- PYME/LMVis/Extras/fiducial.py +230 -0
- PYME/LMVis/Extras/flagZMotionArtifacts.py +60 -0
- PYME/LMVis/Extras/fusionUtils.py +9 -0
- PYME/LMVis/Extras/multiColourAnalysis.py +103 -0
- PYME/LMVis/Extras/multiviewMapping.py +489 -0
- PYME/LMVis/Extras/objectMeasurements.py +246 -0
- PYME/LMVis/Extras/particleTracking.py +272 -0
- PYME/LMVis/Extras/perFrameVariable.py +77 -0
- PYME/LMVis/Extras/photophysics.py +72 -0
- PYME/LMVis/Extras/pointSetGeneration.py +232 -0
- PYME/LMVis/Extras/pointwiseColoc.py +54 -0
- PYME/LMVis/Extras/saved_views.py +125 -0
- PYME/LMVis/Extras/scaleBox.py +115 -0
- PYME/LMVis/Extras/sequentialSpecies.py +125 -0
- PYME/LMVis/Extras/setBGImage.py +74 -0
- PYME/LMVis/Extras/shiftmapGenerator.py +138 -0
- PYME/LMVis/Extras/showShortcuts.py +69 -0
- PYME/LMVis/Extras/snapshot.py +135 -0
- PYME/LMVis/Extras/spherical_harmonics.py +98 -0
- PYME/LMVis/Extras/subsets.py +15 -0
- PYME/LMVis/Extras/surface_fitting.py +52 -0
- PYME/LMVis/Extras/temperaturePlot.py +53 -0
- PYME/LMVis/Extras/vibration.py +112 -0
- PYME/LMVis/VisGUI.py +506 -0
- PYME/LMVis/__init__.py +39 -0
- PYME/LMVis/colourFilterGUI.py +77 -0
- PYME/LMVis/colourPanel.py +491 -0
- PYME/LMVis/displayPane.py +462 -0
- PYME/LMVis/dyeRatios.py +116 -0
- PYME/LMVis/genImageDialog.py +298 -0
- PYME/LMVis/gl_offScreenHandler.py +134 -0
- PYME/LMVis/gl_render.py +1302 -0
- PYME/LMVis/gl_render3D.py +1453 -0
- PYME/LMVis/gl_render3D_shaders.py +1213 -0
- PYME/LMVis/glcanvas_core.py +1157 -0
- PYME/LMVis/imageView.py +752 -0
- PYME/LMVis/imageView2.py +372 -0
- PYME/LMVis/importTextDialog.py +342 -0
- PYME/LMVis/layer_panel.py +231 -0
- PYME/LMVis/layers/AxesOverlayLayer.py +126 -0
- PYME/LMVis/layers/LUTOverlayLayer.py +346 -0
- PYME/LMVis/layers/OverlayLayer.py +46 -0
- PYME/LMVis/layers/ScaleBarOverlayLayer.py +97 -0
- PYME/LMVis/layers/ScaleBoxOverlayLayer.py +181 -0
- PYME/LMVis/layers/SelectionOverlayLayer.py +124 -0
- PYME/LMVis/layers/__init__.py +53 -0
- PYME/LMVis/layers/base.py +319 -0
- PYME/LMVis/layers/image_layer.py +363 -0
- PYME/LMVis/layers/labels.py +186 -0
- PYME/LMVis/layers/layer_defaults.py +97 -0
- PYME/LMVis/layers/mesh.py +378 -0
- PYME/LMVis/layers/octree.py +194 -0
- PYME/LMVis/layers/pointcloud.py +372 -0
- PYME/LMVis/layers/quiver.py +271 -0
- PYME/LMVis/layers/text.py +250 -0
- PYME/LMVis/layers/tracks.py +309 -0
- PYME/LMVis/mv_math.py +78 -0
- PYME/LMVis/objectDarkMeasure.py +120 -0
- PYME/LMVis/pipeline.py +1227 -0
- PYME/LMVis/pipelineView.py +115 -0
- PYME/LMVis/pointSettingsPanel.py +135 -0
- PYME/LMVis/progGraph.py +59 -0
- PYME/LMVis/quadTreeSettings.py +90 -0
- PYME/LMVis/rendGauss.py +158 -0
- PYME/LMVis/renderers.py +576 -0
- PYME/LMVis/sessionpaths.py +136 -0
- PYME/LMVis/setup.py +39 -0
- PYME/LMVis/setup_exe.py +71 -0
- PYME/LMVis/shader_programs/DefaultShaderProgram.py +149 -0
- PYME/LMVis/shader_programs/GLProgram.py +119 -0
- PYME/LMVis/shader_programs/GouraudShaderProgram.py +157 -0
- PYME/LMVis/shader_programs/PointSpriteShaderProgram.py +163 -0
- PYME/LMVis/shader_programs/ShaderProgramFactory.py +54 -0
- PYME/LMVis/shader_programs/TesselShaderProgram.py +47 -0
- PYME/LMVis/shader_programs/WireFrameShaderProgram.py +50 -0
- PYME/LMVis/shader_programs/__init__.py +20 -0
- PYME/LMVis/shader_programs/oit_compositor.py +23 -0
- PYME/LMVis/shader_programs/shader_loader.py +84 -0
- PYME/LMVis/shader_programs/shader_program.py +168 -0
- PYME/LMVis/shader_programs/shaders/bigflatpoints_fs.glsl +16 -0
- PYME/LMVis/shader_programs/shaders/bigpoints_gs.glsl +40 -0
- PYME/LMVis/shader_programs/shaders/bigpointsprites_fs.glsl +20 -0
- PYME/LMVis/shader_programs/shaders/bigspheres_fs.glsl +53 -0
- PYME/LMVis/shader_programs/shaders/compose_fs.glsl +41 -0
- PYME/LMVis/shader_programs/shaders/compose_vs.glsl +25 -0
- PYME/LMVis/shader_programs/shaders/default_fs.glsl +27 -0
- PYME/LMVis/shader_programs/shaders/default_vs.glsl +88 -0
- PYME/LMVis/shader_programs/shaders/flatpoints_fs.glsl +27 -0
- PYME/LMVis/shader_programs/shaders/gouraud_flatpoints_fs.glsl +30 -0
- PYME/LMVis/shader_programs/shaders/gouraud_fs.glsl +26 -0
- PYME/LMVis/shader_programs/shaders/gouraud_oit_fs.glsl +68 -0
- PYME/LMVis/shader_programs/shaders/gouraud_vs.glsl +135 -0
- PYME/LMVis/shader_programs/shaders/image_fs.glsl +60 -0
- PYME/LMVis/shader_programs/shaders/image_vs.glsl +79 -0
- PYME/LMVis/shader_programs/shaders/phong_fs.glsl +43 -0
- PYME/LMVis/shader_programs/shaders/phong_vs.glsl +45 -0
- PYME/LMVis/shader_programs/shaders/pointsprites_fs.glsl +33 -0
- PYME/LMVis/shader_programs/shaders/pointsprites_vs.glsl +77 -0
- PYME/LMVis/shader_programs/shaders/spheres_fs.glsl +102 -0
- PYME/LMVis/shader_programs/shaders/tessel_fs.glsl +23 -0
- PYME/LMVis/shader_programs/shaders/tessel_vs.glsl +37 -0
- PYME/LMVis/shader_programs/shaders/text_fs.glsl +42 -0
- PYME/LMVis/shader_programs/shaders/text_vs.glsl +84 -0
- PYME/LMVis/shader_programs/shaders/widelines_fs.glsl +19 -0
- PYME/LMVis/shader_programs/shaders/widelines_gs.glsl +56 -0
- PYME/LMVis/shader_programs/shaders/widelines_vs.glsl +51 -0
- PYME/LMVis/statusLog.py +57 -0
- PYME/LMVis/triBlobs.py +142 -0
- PYME/LMVis/view_clipping_pane.py +429 -0
- PYME/LMVis/views.py +275 -0
- PYME/LMVis/visCore.py +1005 -0
- PYME/LMVis/visHelpers.py +880 -0
- PYME/LMVis/visHelpersMin.py +230 -0
- PYME/LMVis/workspaceTree.py +238 -0
- PYME/__init__.py +22 -0
- PYME/cluster/HTTPDataServer.py +1063 -0
- PYME/cluster/HTTPRulePusher.py +382 -0
- PYME/cluster/HTTPTaskPusher.py +377 -0
- PYME/cluster/PYMERuleNodeServer.py +192 -0
- PYME/cluster/PYMERuleServer.py +109 -0
- PYME/cluster/__init__.py +0 -0
- PYME/cluster/clusterUI/accounts/__init__.py +0 -0
- PYME/cluster/clusterUI/accounts/admin.py +85 -0
- PYME/cluster/clusterUI/accounts/forms.py +8 -0
- PYME/cluster/clusterUI/accounts/migrations/0001_initial.py +31 -0
- PYME/cluster/clusterUI/accounts/migrations/__init__.py +0 -0
- PYME/cluster/clusterUI/accounts/models.py +44 -0
- PYME/cluster/clusterUI/accounts/templates/accounts/user_form.html +13 -0
- PYME/cluster/clusterUI/accounts/templates/registration/initial_complete.html +6 -0
- PYME/cluster/clusterUI/accounts/templates/registration/initial_confirm.html +13 -0
- PYME/cluster/clusterUI/accounts/templates/registration/initial_done.html +7 -0
- PYME/cluster/clusterUI/accounts/templates/registration/verification.html +2 -0
- PYME/cluster/clusterUI/accounts/templates/registration/verification_subject.txt +1 -0
- PYME/cluster/clusterUI/accounts/urls.py +19 -0
- PYME/cluster/clusterUI/accounts/views.py +36 -0
- PYME/cluster/clusterUI/clusterUI/__init__.py +0 -0
- PYME/cluster/clusterUI/clusterUI/settings.py +147 -0
- PYME/cluster/clusterUI/clusterUI/urls.py +31 -0
- PYME/cluster/clusterUI/clusterUI/wsgi.py +16 -0
- PYME/cluster/clusterUI/clusterbrowser/__init__.py +0 -0
- PYME/cluster/clusterUI/clusterbrowser/admin.py +3 -0
- PYME/cluster/clusterUI/clusterbrowser/apps.py +7 -0
- PYME/cluster/clusterUI/clusterbrowser/migrations/__init__.py +0 -0
- PYME/cluster/clusterUI/clusterbrowser/models.py +5 -0
- PYME/cluster/clusterUI/clusterbrowser/templates/base.html +129 -0
- PYME/cluster/clusterUI/clusterbrowser/templates/clusterbrowser/dirlisting.html +231 -0
- PYME/cluster/clusterUI/clusterbrowser/templates/clusterbrowser/form_new_folder.html +18 -0
- PYME/cluster/clusterUI/clusterbrowser/templates/clusterbrowser/form_upload_file.html +17 -0
- PYME/cluster/clusterUI/clusterbrowser/templates/clusterbrowser/lightlisting.html +25 -0
- PYME/cluster/clusterUI/clusterbrowser/templates/registration/login.html +38 -0
- PYME/cluster/clusterUI/clusterbrowser/urls.py +10 -0
- PYME/cluster/clusterUI/clusterbrowser/views.py +148 -0
- PYME/cluster/clusterUI/clusterstatus/__init__.py +0 -0
- PYME/cluster/clusterUI/clusterstatus/admin.py +3 -0
- PYME/cluster/clusterUI/clusterstatus/apps.py +7 -0
- PYME/cluster/clusterUI/clusterstatus/migrations/__init__.py +0 -0
- PYME/cluster/clusterUI/clusterstatus/models.py +5 -0
- PYME/cluster/clusterUI/clusterstatus/templates/clusterstatus/load_content.html +29 -0
- PYME/cluster/clusterUI/clusterstatus/templates/clusterstatus/queue_info.html +28 -0
- PYME/cluster/clusterUI/clusterstatus/templates/clusterstatus/queue_info_content.html +50 -0
- PYME/cluster/clusterUI/clusterstatus/templates/clusterstatus/status_dash.html +29 -0
- PYME/cluster/clusterUI/clusterstatus/templates/clusterstatus/status_dash_content.html +90 -0
- PYME/cluster/clusterUI/clusterstatus/urls.py +9 -0
- PYME/cluster/clusterUI/clusterstatus/views.py +69 -0
- PYME/cluster/clusterUI/clusterui_tornado.py +117 -0
- PYME/cluster/clusterUI/deploy.py +62 -0
- PYME/cluster/clusterUI/localization/__init__.py +0 -0
- PYME/cluster/clusterUI/localization/admin.py +3 -0
- PYME/cluster/clusterUI/localization/apps.py +7 -0
- PYME/cluster/clusterUI/localization/migrations/__init__.py +0 -0
- PYME/cluster/clusterUI/localization/models.py +5 -0
- PYME/cluster/clusterUI/localization/templates/localization/settings_form.html +67 -0
- PYME/cluster/clusterUI/localization/urls.py +10 -0
- PYME/cluster/clusterUI/localization/views.py +170 -0
- PYME/cluster/clusterUI/manage.py +17 -0
- PYME/cluster/clusterUI/recipes/__init__.py +0 -0
- PYME/cluster/clusterUI/recipes/admin.py +3 -0
- PYME/cluster/clusterUI/recipes/migrations/__init__.py +0 -0
- PYME/cluster/clusterUI/recipes/models.py +3 -0
- PYME/cluster/clusterUI/recipes/templates/recipes/extra_inputs.html +35 -0
- PYME/cluster/clusterUI/recipes/templates/recipes/form_recipe.html +82 -0
- PYME/cluster/clusterUI/recipes/templates/recipes/input_list.html +7 -0
- PYME/cluster/clusterUI/recipes/templates/recipes/recipe_editor.html +28 -0
- PYME/cluster/clusterUI/recipes/templates/recipes/recipe_editor_common.html +46 -0
- PYME/cluster/clusterUI/recipes/templates/recipes/recipe_editrun.html +93 -0
- PYME/cluster/clusterUI/recipes/templates/recipes/recipe_standalone.html +100 -0
- PYME/cluster/clusterUI/recipes/templates/recipes/recipe_template.html +109 -0
- PYME/cluster/clusterUI/recipes/urls.py +17 -0
- PYME/cluster/clusterUI/recipes/views.py +109 -0
- PYME/cluster/cluster_of_one.py +200 -0
- PYME/cluster/dataserver_wsgi.py +615 -0
- PYME/cluster/distribution.py +71 -0
- PYME/cluster/rulenodeserver.py +487 -0
- PYME/cluster/rules.py +979 -0
- PYME/cluster/ruleserver.py +1106 -0
- PYME/cluster/status.py +101 -0
- PYME/cluster/taskWorkerHTTP.py +522 -0
- PYME/cluster/webdav.py +1102 -0
- PYME/config.py +659 -0
- PYME/contrib/TextCtrlAutoComplete.py +582 -0
- PYME/contrib/__init__.py +7 -0
- PYME/contrib/aniso/__init__.py +2 -0
- PYME/contrib/aniso/aniso.py +268 -0
- PYME/contrib/auiFloatBook.py +94 -0
- PYME/contrib/congrid.py +127 -0
- PYME/contrib/dispatch/__init__.py +19 -0
- PYME/contrib/dispatch/dispatcher.py +289 -0
- PYME/contrib/gohlke/__init__.py +1 -0
- PYME/contrib/gohlke/_tifffile.cp39-win_amd64.dll.a +0 -0
- PYME/contrib/gohlke/_tifffile.cp39-win_amd64.pyd +0 -0
- PYME/contrib/gohlke/czifile.py +1289 -0
- PYME/contrib/gohlke/fcsfiles.py +514 -0
- PYME/contrib/gohlke/setup.py +54 -0
- PYME/contrib/gohlke/tifffile.py +3095 -0
- PYME/contrib/listctrlMixins.py +896 -0
- PYME/contrib/lzw.py +838 -0
- PYME/contrib/pad/__init__.py +13 -0
- PYME/contrib/pad/info_pad.py +18 -0
- PYME/contrib/pad/pad.py +670 -0
- PYME/contrib/setup.py +38 -0
- PYME/contrib/wxPlotPanel.py +137 -0
- PYME/experimental/SimReconstruction.py +49 -0
- PYME/experimental/__init__.pxd +0 -0
- PYME/experimental/__init__.py +4 -0
- PYME/experimental/_octree.cp39-win_amd64.dll.a +0 -0
- PYME/experimental/_octree.cp39-win_amd64.pyd +0 -0
- PYME/experimental/_octree.pyx +477 -0
- PYME/experimental/_treap.cp39-win_amd64.dll.a +0 -0
- PYME/experimental/_treap.cp39-win_amd64.pyd +0 -0
- PYME/experimental/_treap.pyx +267 -0
- PYME/experimental/_triangle_mesh.cp39-win_amd64.dll.a +0 -0
- PYME/experimental/_triangle_mesh.cp39-win_amd64.pyd +0 -0
- PYME/experimental/_triangle_mesh.pxd +149 -0
- PYME/experimental/_triangle_mesh.pyx +2787 -0
- PYME/experimental/aqavg.py +40 -0
- PYME/experimental/dcimgFileChucker.py +375 -0
- PYME/experimental/dcimgSpoolShim.py +174 -0
- PYME/experimental/dcimg_chuck_test.py +78 -0
- PYME/experimental/dual_marching_cubes.py +801 -0
- PYME/experimental/dual_marching_cubes_v2.py +645 -0
- PYME/experimental/expectationMaximisation.py +298 -0
- PYME/experimental/func_octree.cp39-win_amd64.dll.a +0 -0
- PYME/experimental/func_octree.cp39-win_amd64.pyd +0 -0
- PYME/experimental/func_octree.pyx +381 -0
- PYME/experimental/fusionRadial.py +520 -0
- PYME/experimental/fusionUtils.py +522 -0
- PYME/experimental/isosurface.py +147 -0
- PYME/experimental/labview_spooling_hacks.py +48 -0
- PYME/experimental/marching_cubes.py +811 -0
- PYME/experimental/marching_tetrahedra.py +343 -0
- PYME/experimental/modified_marching_cubes.py +1245 -0
- PYME/experimental/music.py +25 -0
- PYME/experimental/octree.py +188 -0
- PYME/experimental/pSpaceMap.py +34 -0
- PYME/experimental/pointFitConfoc.py +112 -0
- PYME/experimental/scanner_control.py +107 -0
- PYME/experimental/setup.py +109 -0
- PYME/experimental/spark.py +31 -0
- PYME/experimental/tcHist.py +71 -0
- PYME/experimental/treap.py +262 -0
- PYME/experimental/triangle_mesh.py +2287 -0
- PYME/experimental/triangle_mesh_utils.cp39-win_amd64.dll.a +0 -0
- PYME/experimental/triangle_mesh_utils.cp39-win_amd64.pyd +0 -0
- PYME/experimental/triangle_utils.py +87 -0
- PYME/experimental/triangular_mesh.py +2255 -0
- PYME/experimental/zMotionArtifactUtils.py +55 -0
- PYME/localization/FitFactories/AstigGaussFitFR.py +175 -0
- PYME/localization/FitFactories/AstigGaussGPUFitFR.py +326 -0
- PYME/localization/FitFactories/BeadConvolvedAstigGaussFit.py +206 -0
- PYME/localization/FitFactories/ChecksumFR.py +82 -0
- PYME/localization/FitFactories/ChecksumGPUFR.py +213 -0
- PYME/localization/FitFactories/ChecksumMultifitSR.py +86 -0
- PYME/localization/FitFactories/ConfocCOIR.py +93 -0
- PYME/localization/FitFactories/Dumbell3DFitR.py +193 -0
- PYME/localization/FitFactories/DumbellFitR.py +163 -0
- PYME/localization/FitFactories/FFBase.py +403 -0
- PYME/localization/FitFactories/Gauss3DFitR.py +213 -0
- PYME/localization/FitFactories/GaussFitConstrR.py +177 -0
- PYME/localization/FitFactories/GaussMultifitLinesR.py +351 -0
- PYME/localization/FitFactories/GaussMultifitR.py +326 -0
- PYME/localization/FitFactories/GaussMultifitSR.py +373 -0
- PYME/localization/FitFactories/InterpFitR.py +236 -0
- PYME/localization/FitFactories/InterpFitWFR.py +111 -0
- PYME/localization/FitFactories/Interpolators/CSInterpolator.py +148 -0
- PYME/localization/FitFactories/Interpolators/CubeSInterpolatorP.py +121 -0
- PYME/localization/FitFactories/Interpolators/CubicSplineInterpolator.py +69 -0
- PYME/localization/FitFactories/Interpolators/LinearInterpolator.py +135 -0
- PYME/localization/FitFactories/Interpolators/LinearPInterpolatorP.py +95 -0
- PYME/localization/FitFactories/Interpolators/__init__.py +33 -0
- PYME/localization/FitFactories/Interpolators/baseInterpolator.py +202 -0
- PYME/localization/FitFactories/LatFitCOIR.py +82 -0
- PYME/localization/FitFactories/LatGaussFitFR.py +220 -0
- PYME/localization/FitFactories/LatObjFindFR.py +85 -0
- PYME/localization/FitFactories/LatPSFFitR.py +142 -0
- PYME/localization/FitFactories/MultiviewFitInterpNR.py +400 -0
- PYME/localization/FitFactories/PRInterpFitQR.py +192 -0
- PYME/localization/FitFactories/PRInterpFitR.py +223 -0
- PYME/localization/FitFactories/ROIExtractNR.py +93 -0
- PYME/localization/FitFactories/SpecGaussFitFR.py +174 -0
- PYME/localization/FitFactories/SplitterFitCOIR.py +142 -0
- PYME/localization/FitFactories/SplitterFitFNR.py +312 -0
- PYME/localization/FitFactories/SplitterFitFusionR.py +318 -0
- PYME/localization/FitFactories/SplitterFitInterpBNR.py +357 -0
- PYME/localization/FitFactories/SplitterFitInterpNR.py +343 -0
- PYME/localization/FitFactories/SplitterFitScavNR.py +352 -0
- PYME/localization/FitFactories/SplitterMultifitSR.py +410 -0
- PYME/localization/FitFactories/SplitterObjFindR.py +194 -0
- PYME/localization/FitFactories/SplitterROIExtractNR.py +91 -0
- PYME/localization/FitFactories/SplitterShiftEstFR.py +230 -0
- PYME/localization/FitFactories/__init__.py +103 -0
- PYME/localization/FitFactories/fitCommon.py +195 -0
- PYME/localization/FitFactories/zEstimators/__init__.py +29 -0
- PYME/localization/FitFactories/zEstimators/astigEstimator.py +173 -0
- PYME/localization/FitFactories/zEstimators/biplaneEstimator.py +209 -0
- PYME/localization/FitFactories/zEstimators/genericDualEstimator.py +232 -0
- PYME/localization/FitFactories/zEstimators/genericEstimator.py +224 -0
- PYME/localization/FitFactories/zEstimators/priEstimator.py +255 -0
- PYME/localization/MetaDataEdit.py +543 -0
- PYME/localization/Test/30_9_series_A_1.sf +0 -0
- PYME/localization/Test/PRI.md +45 -0
- PYME/localization/Test/PRI_qr.md +52 -0
- PYME/localization/Test/PRI_r.md +52 -0
- PYME/localization/Test/__init__.py +22 -0
- PYME/localization/Test/astig.md +50 -0
- PYME/localization/Test/astigCOI.md +50 -0
- PYME/localization/Test/astig_gauss.md +52 -0
- PYME/localization/Test/astig_pe.md +50 -0
- PYME/localization/Test/astig_splitter.md +66 -0
- PYME/localization/Test/astig_splitterCOI.md +67 -0
- PYME/localization/Test/astig_splitterQ.md +66 -0
- PYME/localization/Test/astig_theory.md +50 -0
- PYME/localization/Test/astig_theory.psf +0 -0
- PYME/localization/Test/astig_theory.tif +0 -0
- PYME/localization/Test/beads1.psf +0 -0
- PYME/localization/Test/beads1.tif +0 -0
- PYME/localization/Test/biplane_splitter.md +75 -0
- PYME/localization/Test/biplane_splitter2.md +103 -0
- PYME/localization/Test/biplane_splitter3.md +115 -0
- PYME/localization/Test/defoc.md +48 -0
- PYME/localization/Test/dumbell_3d.md +52 -0
- PYME/localization/Test/fitTestJig.py +172 -0
- PYME/localization/Test/fitTestJigSCMOS.py +487 -0
- PYME/localization/Test/fitTestJigWC.py +225 -0
- PYME/localization/Test/gauss.md +50 -0
- PYME/localization/Test/gaussCOI.md +50 -0
- PYME/localization/Test/pri_pe.md +50 -0
- PYME/localization/Test/pri_theory.md +51 -0
- PYME/localization/Test/pri_theory.psf +0 -0
- PYME/localization/Test/pri_theory.tif +0 -0
- PYME/localization/Test/psf_astig.psf +0 -0
- PYME/localization/Test/psf_astig.tif +0 -0
- PYME/localization/Test/psf_astig_bg_d.psf +0 -0
- PYME/localization/Test/psf_astig_bg_d.tif +0 -0
- PYME/localization/Test/psf_astig_pe.psf +0 -0
- PYME/localization/Test/psf_astig_pe.tif +0 -0
- PYME/localization/Test/psf_decon.psf +0 -0
- PYME/localization/Test/psf_decon.tif +0 -0
- PYME/localization/Test/psf_decon_pe.psf +0 -0
- PYME/localization/Test/psf_decon_pe.tif +0 -0
- PYME/localization/Test/psf_guess.psf +0 -0
- PYME/localization/Test/splitter.md +63 -0
- PYME/localization/Test/splitter_scav.md +63 -0
- PYME/localization/Test/test.psf +0 -0
- PYME/localization/Test/test.tif +0 -0
- PYME/localization/Test/test_decon.psf +0 -0
- PYME/localization/Test/test_decon.tif +0 -0
- PYME/localization/Test/test_pe.psf +0 -0
- PYME/localization/Test/test_pe.tif +0 -0
- PYME/localization/Test/wf_theory.psf +0 -0
- PYME/localization/Test/wf_theory2.psf +0 -0
- PYME/localization/__init__.py +17 -0
- PYME/localization/autopsf/__init__.py +1 -0
- PYME/localization/autopsf/autopsf.py +486 -0
- PYME/localization/autopsf/roifit.py +310 -0
- PYME/localization/cInterp/__init__.py +24 -0
- PYME/localization/cInterp/cInterp.cp39-win_amd64.dll.a +0 -0
- PYME/localization/cInterp/cInterp.cp39-win_amd64.pyd +0 -0
- PYME/localization/cInterp/setup.py +54 -0
- PYME/localization/cModels/__init__.py +24 -0
- PYME/localization/cModels/gauss_app.cp39-win_amd64.dll.a +0 -0
- PYME/localization/cModels/gauss_app.cp39-win_amd64.pyd +0 -0
- PYME/localization/ofind.py +444 -0
- PYME/localization/ofind3d.py +306 -0
- PYME/localization/ofind_nofilt.py +128 -0
- PYME/localization/ofind_pri.py +478 -0
- PYME/localization/ofind_split.py +399 -0
- PYME/localization/ofind_xcorr.py +351 -0
- PYME/localization/ofind_xcorr_fw.py +441 -0
- PYME/localization/remFitBuf.py +657 -0
- PYME/localization/setup.py +56 -0
- PYME/localization/splitting.py +240 -0
- PYME/localization/twist.py +60 -0
- PYME/misc/TiSettings.py +36 -0
- PYME/misc/TiffImagePlugin.py +838 -0
- PYME/misc/VolProj.py +144 -0
- PYME/misc/__init__.py +25 -0
- PYME/misc/aligned_array.py +10 -0
- PYME/misc/aniso.py +29 -0
- PYME/misc/big_sur_fix.py +20 -0
- PYME/misc/check_for_updates.py +139 -0
- PYME/misc/colormaps.py +199 -0
- PYME/misc/colorsys.py +201 -0
- PYME/misc/computerName.py +33 -0
- PYME/misc/coverslipGeometries.py +60 -0
- PYME/misc/cython_numpy_monkey.py +40 -0
- PYME/misc/depGraph.py +406 -0
- PYME/misc/dirSize.py +31 -0
- PYME/misc/diskCleanup.py +64 -0
- PYME/misc/djangoRecarray.py +57 -0
- PYME/misc/django_widgets.py +27 -0
- PYME/misc/editgrid.py +101 -0
- PYME/misc/eventSpy.py +122 -0
- PYME/misc/exceptions.py +30 -0
- PYME/misc/facsPlot.py +89 -0
- PYME/misc/fbpIcons.py +90 -0
- PYME/misc/fftw_compat.py +28 -0
- PYME/misc/findCycles.py +91 -0
- PYME/misc/fortran_interrupt_defeat.py +43 -0
- PYME/misc/glassModel.py +64 -0
- PYME/misc/hash32.py +41 -0
- PYME/misc/hillcurve.py +88 -0
- PYME/misc/hybrid_ns.py +84 -0
- PYME/misc/kdFit.py +72 -0
- PYME/misc/locate.py +10 -0
- PYME/misc/memUsage.py +65 -0
- PYME/misc/memmap.py +52 -0
- PYME/misc/mock_ctypes.py +28 -0
- PYME/misc/mock_traits.py +59 -0
- PYME/misc/mock_traitsui.py +29 -0
- PYME/misc/pyme_zeroconf.py +287 -0
- PYME/misc/pyro_tracebacks.py +32 -0
- PYME/misc/read_agf.py +605 -0
- PYME/misc/sffake.py +16 -0
- PYME/misc/snells.py +71 -0
- PYME/misc/sqlite_ns.py +132 -0
- PYME/misc/sqlitendarray.py +56 -0
- PYME/misc/taskDef.py +44 -0
- PYME/misc/tempDB.py +56 -0
- PYME/misc/wxThread.py +33 -0
- PYME/misc/zemax.py +259 -0
- PYME/misc/zernike.py +151 -0
- PYME/pyme_warnings.py +70 -0
- PYME/recipes/Recipes/STEDDeconvolution.yaml +14 -0
- PYME/recipes/Recipes/STEDMinistacks.yaml +15 -0
- PYME/recipes/Recipes/STED_COP3.yaml +25 -0
- PYME/recipes/Recipes/blobMeas.yaml +19 -0
- PYME/recipes/Recipes/blobMeas2.yaml +37 -0
- PYME/recipes/Recipes/blobMeasSR.yaml +66 -0
- PYME/recipes/Recipes/coloc.yaml +43 -0
- PYME/recipes/Recipes/coloc_roi_masked.yaml +46 -0
- PYME/recipes/Recipes/multiblob.yaml +38 -0
- PYME/recipes/Recipes/pre_particleTracking.yaml +30 -0
- PYME/recipes/Recipes/segmentAndMeasureLoci.yaml +41 -0
- PYME/recipes/__init__.py +6 -0
- PYME/recipes/acquisition.py +158 -0
- PYME/recipes/bakeshop.py +32 -0
- PYME/recipes/base.py +1393 -0
- PYME/recipes/batchProcess.py +147 -0
- PYME/recipes/filters.py +394 -0
- PYME/recipes/fudges.py +41 -0
- PYME/recipes/graphing.py +108 -0
- PYME/recipes/html_recipe_editor.py +90 -0
- PYME/recipes/localisations.py +1386 -0
- PYME/recipes/machine_learning.py +286 -0
- PYME/recipes/measurement.py +1062 -0
- PYME/recipes/modules.py +50 -0
- PYME/recipes/multiview.py +435 -0
- PYME/recipes/output.py +667 -0
- PYME/recipes/pointcloud.py +510 -0
- PYME/recipes/processing.py +2954 -0
- PYME/recipes/pyramid.py +206 -0
- PYME/recipes/recipe.py +965 -0
- PYME/recipes/recipeGui.py +1029 -0
- PYME/recipes/recipeLayout.py +499 -0
- PYME/recipes/runRecipe.py +140 -0
- PYME/recipes/setup.py +37 -0
- PYME/recipes/simulation.py +91 -0
- PYME/recipes/skfilters.py +143 -0
- PYME/recipes/surface_fitting.py +776 -0
- PYME/recipes/tablefilters.py +275 -0
- PYME/recipes/tracking.py +343 -0
- PYME/recipes/traits.py +157 -0
- PYME/recipes/vertical_recipe_display.py +373 -0
- PYME/resources/__init__.py +23 -0
- PYME/resources/config_template/distributor.yaml +14 -0
- PYME/resources/config_template/nodeserver.yaml +15 -0
- PYME/resources/icons/LUT.png +0 -0
- PYME/resources/icons/YSM_Shield.png +0 -0
- PYME/resources/icons/YSM_logo.png +0 -0
- PYME/resources/icons/arrow.png +0 -0
- PYME/resources/icons/crosshairs.png +0 -0
- PYME/resources/icons/line_select.png +0 -0
- PYME/resources/icons/logo_fmhs.png +0 -0
- PYME/resources/icons/media-playback-pause.png +0 -0
- PYME/resources/icons/media-playback-start.png +0 -0
- PYME/resources/icons/media-skip-backward.png +0 -0
- PYME/resources/icons/media-skip-forward.png +0 -0
- PYME/resources/icons/mesh.png +0 -0
- PYME/resources/icons/mesh.svg +28 -0
- PYME/resources/icons/pmacquire.icns +0 -0
- PYME/resources/icons/pmacquire.ico +0 -0
- PYME/resources/icons/pmanal.icns +0 -0
- PYME/resources/icons/pmanal.ico +0 -0
- PYME/resources/icons/pmvis.icns +0 -0
- PYME/resources/icons/pmvis.ico +0 -0
- PYME/resources/icons/points.png +0 -0
- PYME/resources/icons/points.svg +16 -0
- PYME/resources/icons/pymeLogo.png +0 -0
- PYME/resources/icons/rect_select.png +0 -0
- PYME/resources/icons/squiggle_select.png +0 -0
- PYME/resources/icons/text3800.icns +0 -0
- PYME/resources/icons/text3800.ico +0 -0
- PYME/resources/icons/text3800.png +0 -0
- PYME/resources/icons/text3800.tif +0 -0
- PYME/resources/icons/text5377.icns +0 -0
- PYME/resources/icons/text5377.ico +0 -0
- PYME/resources/icons/text5377.png +0 -0
- PYME/resources/icons/tracks.png +0 -0
- PYME/resources/icons/tracks.svg +19 -0
- PYME/resources/icons/view-front.png +0 -0
- PYME/resources/icons/view-home.png +0 -0
- PYME/resources/icons/view-right.png +0 -0
- PYME/resources/icons/view-top.png +0 -0
- PYME/resources/test_datasets/README.md +8 -0
- PYME/resources/test_datasets/t_im.tif +0 -0
- PYME/resources/test_datasets/test_csv.csv +4282 -0
- PYME/resources/test_datasets/test_hdf.hdf +0 -0
- PYME/resources/web/rule_inline.html +21 -0
- PYME/resources/web/ruleserver.html +75 -0
- PYME/resources/web/static/bootstrap.min.js +7 -0
- PYME/resources/web/static/cluster.css +137 -0
- PYME/resources/web/static/css/bootstrap-theme.css +587 -0
- PYME/resources/web/static/css/bootstrap-theme.min.css +6 -0
- PYME/resources/web/static/css/bootstrap.css +6757 -0
- PYME/resources/web/static/css/bootstrap.min.css +6 -0
- PYME/resources/web/static/css/flat_design_colors_full.css +306 -0
- PYME/resources/web/static/css/recipe_editor.css +106 -0
- PYME/resources/web/static/dashboard.css +106 -0
- PYME/resources/web/static/fileselector.js +77 -0
- PYME/resources/web/static/fonts/glyphicons-halflings-regular.eot +0 -0
- PYME/resources/web/static/fonts/glyphicons-halflings-regular.svg +288 -0
- PYME/resources/web/static/fonts/glyphicons-halflings-regular.ttf +0 -0
- PYME/resources/web/static/fonts/glyphicons-halflings-regular.woff +0 -0
- PYME/resources/web/static/fonts/glyphicons-halflings-regular.woff2 +0 -0
- PYME/resources/web/static/images/osd_flat/LICENSE.txt +116 -0
- PYME/resources/web/static/images/osd_flat/README.md +9 -0
- PYME/resources/web/static/images/osd_flat/fullpage_grouphover.png +0 -0
- PYME/resources/web/static/images/osd_flat/fullpage_hover.png +0 -0
- PYME/resources/web/static/images/osd_flat/fullpage_pressed.png +0 -0
- PYME/resources/web/static/images/osd_flat/fullpage_rest.png +0 -0
- PYME/resources/web/static/images/osd_flat/home_grouphover.png +0 -0
- PYME/resources/web/static/images/osd_flat/home_hover.png +0 -0
- PYME/resources/web/static/images/osd_flat/home_pressed.png +0 -0
- PYME/resources/web/static/images/osd_flat/home_rest.png +0 -0
- PYME/resources/web/static/images/osd_flat/next_grouphover.png +0 -0
- PYME/resources/web/static/images/osd_flat/next_hover.png +0 -0
- PYME/resources/web/static/images/osd_flat/next_pressed.png +0 -0
- PYME/resources/web/static/images/osd_flat/next_rest.png +0 -0
- PYME/resources/web/static/images/osd_flat/previous_grouphover.png +0 -0
- PYME/resources/web/static/images/osd_flat/previous_hover.png +0 -0
- PYME/resources/web/static/images/osd_flat/previous_pressed.png +0 -0
- PYME/resources/web/static/images/osd_flat/previous_rest.png +0 -0
- PYME/resources/web/static/images/osd_flat/rotateleft_grouphover.png +0 -0
- PYME/resources/web/static/images/osd_flat/rotateleft_hover.png +0 -0
- PYME/resources/web/static/images/osd_flat/rotateleft_pressed.png +0 -0
- PYME/resources/web/static/images/osd_flat/rotateleft_rest.png +0 -0
- PYME/resources/web/static/images/osd_flat/rotateright_grouphover.png +0 -0
- PYME/resources/web/static/images/osd_flat/rotateright_hover.png +0 -0
- PYME/resources/web/static/images/osd_flat/rotateright_pressed.png +0 -0
- PYME/resources/web/static/images/osd_flat/rotateright_rest.png +0 -0
- PYME/resources/web/static/images/osd_flat/zoomin_grouphover.png +0 -0
- PYME/resources/web/static/images/osd_flat/zoomin_hover.png +0 -0
- PYME/resources/web/static/images/osd_flat/zoomin_pressed.png +0 -0
- PYME/resources/web/static/images/osd_flat/zoomin_rest.png +0 -0
- PYME/resources/web/static/images/osd_flat/zoomout_grouphover.png +0 -0
- PYME/resources/web/static/images/osd_flat/zoomout_hover.png +0 -0
- PYME/resources/web/static/images/osd_flat/zoomout_pressed.png +0 -0
- PYME/resources/web/static/images/osd_flat/zoomout_rest.png +0 -0
- PYME/resources/web/static/jigna-vue-bare.js +1395 -0
- PYME/resources/web/static/jquery.min.js +2 -0
- PYME/resources/web/static/jstree.min.js +6 -0
- PYME/resources/web/static/openSeadragonGL.js +102 -0
- PYME/resources/web/static/openseadragon-svg-overlay.js +103 -0
- PYME/resources/web/static/openseadragon-viewerinputhook.min.js +6 -0
- PYME/resources/web/static/openseadragon.min.js +9 -0
- PYME/resources/web/static/recipe_editor.js +119 -0
- PYME/resources/web/static/shaders/fragment/lut.glsl +20 -0
- PYME/resources/web/static/shaders/fragment/none.glsl +17 -0
- PYME/resources/web/static/shaders/fragment/outline.glsl +43 -0
- PYME/resources/web/static/shaders/fragment/rect.glsl +7 -0
- PYME/resources/web/static/shaders/fragment/sobel3.glsl +71 -0
- PYME/resources/web/static/shaders/fragment/white.glsl +4 -0
- PYME/resources/web/static/shaders/vertex/rect.glsl +22 -0
- PYME/resources/web/static/shaders/vertex/square.glsl +9 -0
- PYME/resources/web/static/utils.js +3 -0
- PYME/resources/web/static/viaWebGL.js +217 -0
- PYME/setup.py +109 -0
- PYME/setup_exe.py +57 -0
- PYME/simulation/__init__.py +0 -0
- PYME/simulation/locify.py +319 -0
- PYME/simulation/pointsets.py +279 -0
- PYME/simulation/wormlike.py +99 -0
- PYME/simulation/wormlike2.py +198 -0
- PYME/simulation/wormlike3.py +197 -0
- PYME/simulation/wormlike_curled.py +104 -0
- PYME/tileviewer/__init__.py +0 -0
- PYME/tileviewer/templates/roi_list.html +12 -0
- PYME/tileviewer/templates/tileviewer.html +247 -0
- PYME/tileviewer/tileviewer.py +207 -0
- PYME/ui/AUIFrame.py +279 -0
- PYME/ui/MetadataTree.py +469 -0
- PYME/ui/__init__.py +4 -0
- PYME/ui/about_dlg.py +29 -0
- PYME/ui/autoFoldPanel.py +643 -0
- PYME/ui/cascading_layout.py +45 -0
- PYME/ui/crop_dialog.py +145 -0
- PYME/ui/custom_traits_editors.py +508 -0
- PYME/ui/editFilterDialog.py +80 -0
- PYME/ui/editList.py +40 -0
- PYME/ui/fastGraph.py +240 -0
- PYME/ui/filterPane.py +348 -0
- PYME/ui/histLimits.py +543 -0
- PYME/ui/layerFoldPanel.py +232 -0
- PYME/ui/manualFoldPanel.py +870 -0
- PYME/ui/mytimer.py +116 -0
- PYME/ui/patch_traitsui.py +151 -0
- PYME/ui/progress.py +160 -0
- PYME/ui/recArrayView.py +145 -0
- PYME/ui/selection.py +71 -0
- PYME/ui/shell.py +37 -0
- PYME/ui/traitsui_constants.py +91 -0
- PYME/ui/wx_compat.py +43 -0
- PYME/update_version.py +159 -0
- PYME/util/__init__.py +3 -0
- PYME/util/authenticate.py +164 -0
- PYME/util/execfile.py +21 -0
- PYME/util/fProfile/__init__.py +1 -0
- PYME/util/fProfile/convertProfile.py +117 -0
- PYME/util/fProfile/fProfile.py +162 -0
- PYME/util/fProfile/html/404.html +60 -0
- PYME/util/fProfile/html/css/main.css +258 -0
- PYME/util/fProfile/html/css/normalize.css +427 -0
- PYME/util/fProfile/html/css/normalize.min.css +1 -0
- PYME/util/fProfile/html/index.html +64 -0
- PYME/util/fProfile/html/js/main.js +492 -0
- PYME/util/fProfile/html/js/plugins.js +24 -0
- PYME/util/fProfile/html/js/vendor/crossfilter.min.js +1 -0
- PYME/util/fProfile/html/js/vendor/jquery-1.11.2.min.js +4 -0
- PYME/util/fProfile/html/js/vendor/modernizr-2.8.3.min.js +4 -0
- PYME/util/fProfile/html/js/vendor/tinycolor-min.js +4 -0
- PYME/util/fProfile/viewProfile.py +30 -0
- PYME/util/install_dependencies.py +95 -0
- PYME/util/log_verbosity.py +11 -0
- PYME/util/mProfile/__init__.py +1 -0
- PYME/util/mProfile/colorize_db_t.py +297 -0
- PYME/util/mProfile/mProfile.py +164 -0
- PYME/util/mProfile/p.py +101 -0
- PYME/util/mProfile/tProfile.py +165 -0
- PYME/util/pymelauncher.py +47 -0
- PYME/util/shmarray/__init__.py +0 -0
- PYME/util/shmarray/shmTest.py +74 -0
- PYME/util/shmarray/shmarray.py +165 -0
- PYME/util/webframework.py +365 -0
- PYME/version.py +65 -0
- python_microscopy-25.6.5.dist-info/METADATA +68 -0
- python_microscopy-25.6.5.dist-info/RECORD +1277 -0
- python_microscopy-25.6.5.dist-info/WHEEL +4 -0
PYME/cluster/rules.py
ADDED
|
@@ -0,0 +1,979 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Refactored rule pushing. Introduces rule classes which act as a python proxy for the JSON rule objects, and rule
|
|
3
|
+
factories for use when constructing equivalent rules (or chains of rules) for multiple series.
|
|
4
|
+
|
|
5
|
+
Design principles as follows:
|
|
6
|
+
|
|
7
|
+
- a `Rule` object is a 1:1 mapping with rules on the ruleserver
|
|
8
|
+
- you create a new `Rule` object for each rule you push to the server
|
|
9
|
+
- a pattern for rule creation is expressed using a `RuleFactory`
|
|
10
|
+
- calling `.get_rule() on the first step returns you a fully linked rule suitable for submitting
|
|
11
|
+
- very limited inference of inputs etc ... between steps - rely on specifying inputs and outputs using patterns instead
|
|
12
|
+
|
|
13
|
+
Examples
|
|
14
|
+
--------
|
|
15
|
+
|
|
16
|
+
>>> step1 = LocalisationRuleFactory(analysisMetadata=mdh)
|
|
17
|
+
>>> step2 = RecipeRuleFactory(recipeURI='PYME-CLUSTER///RECIPES/render_image.yaml', input_patterns={'input':'{{spool_dir}}/analysis/{{series_stub}}.h5r'})
|
|
18
|
+
>>> step1.chain(step2)
|
|
19
|
+
>>> step3 = RecipeRuleFactory(recipeURI='PYME-CLUSTER///RECIPES/measure_blobs.yaml', input_patterns={'input':'{{spool_dir}}/analysis/{{series_stub}}.tif'})
|
|
20
|
+
>>> step2.chain(step3)
|
|
21
|
+
|
|
22
|
+
or
|
|
23
|
+
|
|
24
|
+
>>> step1 = LocalisationRuleFactory(analysisMetadata=mdh,
|
|
25
|
+
>>> on_completion=RecipeRuleFactory(recipeURI='PYME-CLUSTER///RECIPES/render_image.yaml',
|
|
26
|
+
>>> input_patterns={'input':'{{spool_dir}}/analysis/{{series_stub}}.h5r'},
|
|
27
|
+
>>> on_completion=RecipeRuleFactory(recipeURI='PYME-CLUSTER///RECIPES/measure_blobs.yaml',
|
|
28
|
+
>>> input_patterns={'input':'{{spool_dir}}/analysis/{{series_stub}}.tif'})))
|
|
29
|
+
|
|
30
|
+
then:
|
|
31
|
+
|
|
32
|
+
>>> def on_launch_analysis(context={'spool_dir': ..., 'series_stub': ...}):
|
|
33
|
+
>>> step1.get_rule(context=context).push()
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
import six
|
|
38
|
+
import json
|
|
39
|
+
import threading
|
|
40
|
+
import time
|
|
41
|
+
import logging
|
|
42
|
+
logger = logging.getLogger(__name__)
|
|
43
|
+
|
|
44
|
+
from PYME.IO import DataSources, clusterIO, clusterResults, unifiedIO
|
|
45
|
+
|
|
46
|
+
class NoNewTasks(Exception):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def verify_cluster_results_filename(resultsFilename):
|
|
51
|
+
"""
|
|
52
|
+
Checks whether a results file already exists on the cluster, and returns an available version of the results
|
|
53
|
+
filename. Should be called before writing a new results file.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
resultsFilename : str
|
|
58
|
+
cluster path, e.g. pyme-cluster:///example_folder/name.h5r
|
|
59
|
+
Returns
|
|
60
|
+
-------
|
|
61
|
+
resultsFilename : str
|
|
62
|
+
cluster path which may have _# appended to it if the input resultsFileName is already in use, e.g.
|
|
63
|
+
pyme-cluster:///example_folder/name_1.h5r
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
from PYME.IO import clusterIO
|
|
67
|
+
import os
|
|
68
|
+
if clusterIO.exists(resultsFilename):
|
|
69
|
+
di, fn = os.path.split(resultsFilename)
|
|
70
|
+
i = 1
|
|
71
|
+
stub = os.path.splitext(fn)[0]
|
|
72
|
+
while clusterIO.exists(os.path.join(di, stub + '_%d.h5r' % i)):
|
|
73
|
+
i += 1
|
|
74
|
+
|
|
75
|
+
resultsFilename = os.path.join(di, stub + '_%d.h5r' % i)
|
|
76
|
+
|
|
77
|
+
return resultsFilename
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class RuleWatcher(object):
|
|
81
|
+
""" Single object / thread to watch multiple rules"""
|
|
82
|
+
def __init__(self):
|
|
83
|
+
self.active = True
|
|
84
|
+
self._rules_to_watch = []
|
|
85
|
+
self._cached_status = {}
|
|
86
|
+
|
|
87
|
+
self._t_watch = None
|
|
88
|
+
|
|
89
|
+
def _ipy_status_update(self):
|
|
90
|
+
from IPython.display import update_display
|
|
91
|
+
while self.active:
|
|
92
|
+
for r, disp_id in self._rules_to_watch:
|
|
93
|
+
try:
|
|
94
|
+
s = r.status()
|
|
95
|
+
if not (self._cached_status.get(disp_id, {}) == s):
|
|
96
|
+
update_display(r, display_id=disp_id)
|
|
97
|
+
self._cached_status[disp_id] = s
|
|
98
|
+
except:
|
|
99
|
+
logger.exception('Error updating rule %s' % r)
|
|
100
|
+
|
|
101
|
+
time.sleep(1)
|
|
102
|
+
|
|
103
|
+
def watch(self, rule):
|
|
104
|
+
import uuid
|
|
105
|
+
from IPython.display import display
|
|
106
|
+
|
|
107
|
+
disp_id = str(uuid.uuid4())
|
|
108
|
+
display(rule, display_id=disp_id)
|
|
109
|
+
|
|
110
|
+
self._rules_to_watch.append((rule, disp_id))
|
|
111
|
+
|
|
112
|
+
if (self._t_watch is None) or not (self._t_watch.is_alive()):
|
|
113
|
+
self._t_watch = threading.Thread(target=self._ipy_status_update)
|
|
114
|
+
self._t_watch.daemon=False
|
|
115
|
+
self._t_watch.start()
|
|
116
|
+
|
|
117
|
+
import jinja2
|
|
118
|
+
jenv = jinja2.Environment(loader=jinja2.PackageLoader('PYME.resources', 'web'))
|
|
119
|
+
rg_template = jenv.get_template('rule_inline.html')
|
|
120
|
+
class RuleGroupWatcher(object):
|
|
121
|
+
""" Single object / thread to watch multiple rules
|
|
122
|
+
|
|
123
|
+
Used when launching rules from jupyter notebooks, this will show an
|
|
124
|
+
updating display of rule progress
|
|
125
|
+
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
def __init__(self):
|
|
129
|
+
self.active = True
|
|
130
|
+
#self._rules_to_watch = {}
|
|
131
|
+
self._rule_groups = {}
|
|
132
|
+
self._cached_status = {}
|
|
133
|
+
|
|
134
|
+
self._t_watch = None
|
|
135
|
+
self._curr_cell = None
|
|
136
|
+
self._ip = None
|
|
137
|
+
|
|
138
|
+
def _pre_run_cell(self, info):
|
|
139
|
+
#print(info)
|
|
140
|
+
import uuid
|
|
141
|
+
self._info = info
|
|
142
|
+
self._curr_cell = str(uuid.uuid4())#info.cell_id
|
|
143
|
+
# try:
|
|
144
|
+
# self._rule_groups.pop(_curr_cell)
|
|
145
|
+
# except KeyError:
|
|
146
|
+
# pass
|
|
147
|
+
|
|
148
|
+
def _update(self):
|
|
149
|
+
from IPython.display import update_display
|
|
150
|
+
from PYME.cluster.distribution import get_cached_queue_info
|
|
151
|
+
|
|
152
|
+
while self.active:
|
|
153
|
+
for k, v in list(self._rule_groups.items()):
|
|
154
|
+
rules, disp_id = v
|
|
155
|
+
try:
|
|
156
|
+
status = get_cached_queue_info(rules[0].taskQueueURI)
|
|
157
|
+
if status != self._cached_status.get(disp_id, None):
|
|
158
|
+
self._cached_status[disp_id] = status
|
|
159
|
+
|
|
160
|
+
ri = [rule._get_info(status) for rule in rules]
|
|
161
|
+
html = rg_template.render(info=ri)
|
|
162
|
+
update_display({'text/html': html}, raw=True, display_id=disp_id)
|
|
163
|
+
except:
|
|
164
|
+
logger.exception('Error polling rules %s' % rules)
|
|
165
|
+
self._rule_groups.pop(k)
|
|
166
|
+
|
|
167
|
+
time.sleep(1)
|
|
168
|
+
|
|
169
|
+
def register(self):
|
|
170
|
+
import IPython
|
|
171
|
+
self._ip = IPython.get_ipython()
|
|
172
|
+
|
|
173
|
+
if not self._ip is None:
|
|
174
|
+
self._ip.events.register('pre_run_cell', self._pre_run_cell)
|
|
175
|
+
|
|
176
|
+
def watch(self, rule):
|
|
177
|
+
import uuid
|
|
178
|
+
from IPython.display import display
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
rules, disp_id = self._rule_groups[self._curr_cell]
|
|
182
|
+
|
|
183
|
+
rules.append(rule)
|
|
184
|
+
except KeyError:
|
|
185
|
+
disp_id = str(uuid.uuid4())
|
|
186
|
+
display('', display_id=disp_id)
|
|
187
|
+
|
|
188
|
+
self._rule_groups[self._curr_cell] = ([rule, ], disp_id)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
if (self._t_watch is None) or not (self._t_watch.is_alive()):
|
|
192
|
+
self._t_watch = threading.Thread(target=self._update)
|
|
193
|
+
self._t_watch.daemon=False
|
|
194
|
+
self._t_watch.start()
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
rule_watcher = RuleGroupWatcher()
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class Rule(object):
|
|
202
|
+
def __init__(self, on_completion=None, **kwargs):
|
|
203
|
+
"""
|
|
204
|
+
Create a new rule. Sub-classed for specific rule types
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
Parameters
|
|
208
|
+
----------
|
|
209
|
+
on_completion : RuleFactory instance
|
|
210
|
+
A rule to run after this one has completed (also setable using the `.chain()` method)
|
|
211
|
+
|
|
212
|
+
kwargs : any additional arguments, available in the context used when creating the rule template
|
|
213
|
+
|
|
214
|
+
"""
|
|
215
|
+
|
|
216
|
+
self.rule = self._populate_rule(context=kwargs, on_completion=on_completion)
|
|
217
|
+
|
|
218
|
+
def _populate_rule(self, context, on_completion=None):
|
|
219
|
+
"""
|
|
220
|
+
Populate a rule using series specific info from context
|
|
221
|
+
|
|
222
|
+
Parameters
|
|
223
|
+
----------
|
|
224
|
+
context : dict
|
|
225
|
+
a dictionary containing series specific info to populate into the task template
|
|
226
|
+
|
|
227
|
+
Returns
|
|
228
|
+
-------
|
|
229
|
+
|
|
230
|
+
a rule suitable for submitting to the ruleserver `/add_integer_id_rule` endpoint
|
|
231
|
+
|
|
232
|
+
"""
|
|
233
|
+
rule = {'template': self._task_template(context)}
|
|
234
|
+
|
|
235
|
+
if on_completion:
|
|
236
|
+
chained_context = dict(**context)
|
|
237
|
+
# standard recipe single-input key is 'input'. Set up 'results'
|
|
238
|
+
# as alt key so we can use the same recipe in clusterUI views
|
|
239
|
+
out_files = self.output_files
|
|
240
|
+
if 'results' in out_files.keys() and 'input' not in out_files.keys():
|
|
241
|
+
out_files = out_files.copy()
|
|
242
|
+
out_files['input'] = out_files.pop('results')
|
|
243
|
+
chained_context['rule_outputs'] = out_files
|
|
244
|
+
rule['on_completion'] = on_completion.get_rule(chained_context).rule
|
|
245
|
+
|
|
246
|
+
return rule
|
|
247
|
+
|
|
248
|
+
def _task_template(self, context):
|
|
249
|
+
"""
|
|
250
|
+
Populate the task template for a given rule type. Should be implemented in derived classes.
|
|
251
|
+
|
|
252
|
+
Parameters
|
|
253
|
+
----------
|
|
254
|
+
context : dict
|
|
255
|
+
Series specific context information to use in the template
|
|
256
|
+
|
|
257
|
+
Returns
|
|
258
|
+
-------
|
|
259
|
+
|
|
260
|
+
The task template as a string.
|
|
261
|
+
|
|
262
|
+
"""
|
|
263
|
+
raise NotImplementedError('This method should be over-ridden in a derived class')
|
|
264
|
+
|
|
265
|
+
def prepare(self):
|
|
266
|
+
"""
|
|
267
|
+
Do any setup work - e.g. uploading metadata required before the rule is triggered
|
|
268
|
+
|
|
269
|
+
Returns
|
|
270
|
+
-------
|
|
271
|
+
|
|
272
|
+
post_args : dict
|
|
273
|
+
a dictionary with arguments to pass to RulePusher._post_rule() - specifically timeout, max_tasks, release_start, release_end
|
|
274
|
+
|
|
275
|
+
"""
|
|
276
|
+
|
|
277
|
+
return {}
|
|
278
|
+
|
|
279
|
+
def _output_files(self):
|
|
280
|
+
""" Return a dictionary of output cluster URIs.
|
|
281
|
+
The principle output (if it makes sense to define one) should be under the 'results' key. Each entry should be a
|
|
282
|
+
single output as this gets substituted into the recipe before submission (not in the ruleserver):
|
|
283
|
+
|
|
284
|
+
For a single output, the dictionary should look like: {'results' : results_URI}
|
|
285
|
+
|
|
286
|
+
Over-ride in derived rule classes
|
|
287
|
+
"""
|
|
288
|
+
return {}
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def output_files(self):
|
|
292
|
+
return self._output_files()
|
|
293
|
+
|
|
294
|
+
@property
|
|
295
|
+
def complete(self):
|
|
296
|
+
"""
|
|
297
|
+
Is this rule complete, or do we need to poll for more input?
|
|
298
|
+
|
|
299
|
+
Over-ridden in localisation rule
|
|
300
|
+
Returns
|
|
301
|
+
-------
|
|
302
|
+
|
|
303
|
+
"""
|
|
304
|
+
return True
|
|
305
|
+
|
|
306
|
+
@property
|
|
307
|
+
def data_complete(self):
|
|
308
|
+
""" Is the underlying data complete?"""
|
|
309
|
+
return True
|
|
310
|
+
|
|
311
|
+
def on_data_complete(self):
|
|
312
|
+
'''Over-ride in derived rules so that, e.g. events can be written at the end of a real-time acquisition '''
|
|
313
|
+
pass
|
|
314
|
+
|
|
315
|
+
def get_new_tasks(self):
|
|
316
|
+
"""
|
|
317
|
+
Over-ridden in rules where all the data is not guaranteed to be present when the rule is created
|
|
318
|
+
|
|
319
|
+
Returns
|
|
320
|
+
-------
|
|
321
|
+
|
|
322
|
+
release_start, release_end : the indices of starting and ending tasks to release
|
|
323
|
+
|
|
324
|
+
"""
|
|
325
|
+
raise NoNewTasks('get_new_tasks() called in base class which assumes all tasks are released on rule creation')
|
|
326
|
+
|
|
327
|
+
@classmethod
|
|
328
|
+
def _getTaskQueueURI(cls, n_retries=2):
|
|
329
|
+
"""Discover the distributors using zeroconf and choose one"""
|
|
330
|
+
from PYME.misc import hybrid_ns
|
|
331
|
+
import socket
|
|
332
|
+
import random
|
|
333
|
+
import time
|
|
334
|
+
from PYME.misc.computerName import GetComputerName
|
|
335
|
+
compName = GetComputerName()
|
|
336
|
+
|
|
337
|
+
ns = hybrid_ns.getNS('_pyme-taskdist')
|
|
338
|
+
|
|
339
|
+
queueURLs = {}
|
|
340
|
+
|
|
341
|
+
def _search():
|
|
342
|
+
for name, info in ns.get_advertised_services():
|
|
343
|
+
if name.startswith('PYMERuleServer'):
|
|
344
|
+
#print(info, info.address)
|
|
345
|
+
queueURLs[name] = 'http://%s:%d' % (socket.inet_ntoa(info.address), info.port)
|
|
346
|
+
|
|
347
|
+
_search()
|
|
348
|
+
while not queueURLs and (n_retries > 0):
|
|
349
|
+
logging.info('could not find a rule server, waiting 5s and trying again')
|
|
350
|
+
time.sleep(5)
|
|
351
|
+
n_retries -= 1
|
|
352
|
+
_search()
|
|
353
|
+
|
|
354
|
+
try:
|
|
355
|
+
#try to grab the distributor on the local computer
|
|
356
|
+
local_queues = [q for q in queueURLs if compName in q]
|
|
357
|
+
logger.debug('local_queues: %s' % local_queues)
|
|
358
|
+
return queueURLs[local_queues[0]]
|
|
359
|
+
except (KeyError, IndexError):
|
|
360
|
+
#if there is no local distributor, choose one at random
|
|
361
|
+
logger.info('no local rule server, choosing one at random')
|
|
362
|
+
return random.choice(list(queueURLs.values()))
|
|
363
|
+
|
|
364
|
+
def push(self):
|
|
365
|
+
self._ruleID = None
|
|
366
|
+
self.taskQueueURI = self._getTaskQueueURI()
|
|
367
|
+
self._current_task_num = 0
|
|
368
|
+
|
|
369
|
+
#create any needed files - e.g. metadata
|
|
370
|
+
post_args = self.prepare()
|
|
371
|
+
|
|
372
|
+
#post our rule
|
|
373
|
+
self._post_rule(**post_args)
|
|
374
|
+
|
|
375
|
+
if not self.complete:
|
|
376
|
+
#we haven't released all the frames yet, start a loop to poll and release frames as they become available.
|
|
377
|
+
self.doPoll = True
|
|
378
|
+
self.pollT = threading.Thread(target=self._poll_loop)
|
|
379
|
+
self.pollT.start()
|
|
380
|
+
else:
|
|
381
|
+
self.on_data_complete()
|
|
382
|
+
|
|
383
|
+
return self #return a reference so we can chain methods - e.g. Rule.post().watch().join()
|
|
384
|
+
|
|
385
|
+
def _post_rule(self, timeout=3600, max_tasks=1e6, release_start=None, release_end=None):
|
|
386
|
+
""" wrapper around add_integer_rule api endpoint"""
|
|
387
|
+
from PYME.IO import clusterIO
|
|
388
|
+
|
|
389
|
+
s = clusterIO._getSession(self.taskQueueURI)
|
|
390
|
+
if release_start is None:
|
|
391
|
+
cmd = '%s/add_integer_id_rule?timeout=%d&max_tasks=%d' % (self.taskQueueURI, timeout, max_tasks)
|
|
392
|
+
else:
|
|
393
|
+
# TODO - can we get rid of this special casing?
|
|
394
|
+
cmd = '%s/add_integer_id_rule?timeout=%d&max_tasks=%d&release_start=%d&release_end=%d' % (
|
|
395
|
+
self.taskQueueURI, timeout, max_tasks, release_start, release_end)
|
|
396
|
+
|
|
397
|
+
r = s.post(cmd,
|
|
398
|
+
data=json.dumps(self.rule),
|
|
399
|
+
headers={'Content-Type': 'application/json'})
|
|
400
|
+
|
|
401
|
+
if r.status_code == 200:
|
|
402
|
+
resp = r.json()
|
|
403
|
+
self._ruleID = resp['ruleID']
|
|
404
|
+
logger.debug('Successfully created rule')
|
|
405
|
+
else:
|
|
406
|
+
logger.error('Failed creating rule with status code: %d' % r.status_code)
|
|
407
|
+
|
|
408
|
+
def _release_tasks(self, release_start, release_end):
|
|
409
|
+
""" Thin wrapper around release_rule_tasks api endpoint"""
|
|
410
|
+
from PYME.IO import clusterIO
|
|
411
|
+
s = clusterIO._getSession(self.taskQueueURI)
|
|
412
|
+
r = s.get('%s/release_rule_tasks?ruleID=%s&release_start=%d&release_end=%d' % (
|
|
413
|
+
self.taskQueueURI, self._ruleID, release_start, release_end),
|
|
414
|
+
data='',
|
|
415
|
+
headers={'Content-Type': 'application/json'})
|
|
416
|
+
|
|
417
|
+
if r.status_code == 200 and r.json()['ok']:
|
|
418
|
+
logging.debug('Successfully released tasks (%d:%d)' % (release_start, release_end))
|
|
419
|
+
else:
|
|
420
|
+
logging.error('Failed on releasing tasks with status code: %d' % r.status_code)
|
|
421
|
+
|
|
422
|
+
def _mark_complete(self):
|
|
423
|
+
""" Thin wrapper around release_rule_tasks api endpoint"""
|
|
424
|
+
from PYME.IO import clusterIO
|
|
425
|
+
s = clusterIO._getSession(self.taskQueueURI)
|
|
426
|
+
r = s.get('%s/mark_release_complete?ruleID=%s' % (
|
|
427
|
+
self.taskQueueURI, self._ruleID),
|
|
428
|
+
data='',
|
|
429
|
+
headers={'Content-Type': 'application/json'})
|
|
430
|
+
|
|
431
|
+
if r.status_code == 200 and r.json()['ok']:
|
|
432
|
+
logging.debug('Successfully marked rule as complete')
|
|
433
|
+
else:
|
|
434
|
+
logging.error('Failed to mark rule complete with status code: %d' % r.status_code)
|
|
435
|
+
|
|
436
|
+
def _poll_loop(self):
|
|
437
|
+
logging.debug('task pusher poll loop started')
|
|
438
|
+
|
|
439
|
+
while (self.doPoll == True):
|
|
440
|
+
try:
|
|
441
|
+
rel_start, rel_end = self.get_new_tasks()
|
|
442
|
+
self._release_tasks(rel_start, rel_end)
|
|
443
|
+
except NoNewTasks:
|
|
444
|
+
pass
|
|
445
|
+
|
|
446
|
+
if self.data_complete and not hasattr(self, '_data_comp_callback_res'):
|
|
447
|
+
logger.debug('input data complete, calling on_data_complete')
|
|
448
|
+
self._data_comp_callback_res=self.on_data_complete()
|
|
449
|
+
|
|
450
|
+
if self.complete:
|
|
451
|
+
logger.debug('input data complete')
|
|
452
|
+
try: # check/relase one more time to avoid race condition
|
|
453
|
+
rel_start, rel_end = self.get_new_tasks()
|
|
454
|
+
self._release_tasks(rel_start, rel_end)
|
|
455
|
+
except NoNewTasks:
|
|
456
|
+
pass
|
|
457
|
+
logger.debug('all tasks pushed, marking rule as complete')
|
|
458
|
+
self._mark_complete()
|
|
459
|
+
logging.debug('ending polling loop.')
|
|
460
|
+
self.doPoll = False
|
|
461
|
+
else:
|
|
462
|
+
time.sleep(1)
|
|
463
|
+
|
|
464
|
+
def cleanup(self):
|
|
465
|
+
self.doPoll = False
|
|
466
|
+
|
|
467
|
+
def status(self):
|
|
468
|
+
from PYME.cluster.distribution import get_cached_queue_info
|
|
469
|
+
return self._get_info(get_cached_queue_info(self.taskQueueURI), errors=False)
|
|
470
|
+
|
|
471
|
+
def join(self):
|
|
472
|
+
while not self.status()['finished']:
|
|
473
|
+
time.sleep(1)
|
|
474
|
+
#raise NotImplementedError('Join is not implemented yet')
|
|
475
|
+
|
|
476
|
+
#def __repr__(self) -> str:
|
|
477
|
+
|
|
478
|
+
def _ipy_status_update(self):
|
|
479
|
+
from IPython.display import update_display
|
|
480
|
+
while not self.status()['finished']:
|
|
481
|
+
time.sleep(1)
|
|
482
|
+
update_display(self, display_id=self._disp_id)
|
|
483
|
+
|
|
484
|
+
def _watch(self):
|
|
485
|
+
import uuid
|
|
486
|
+
from IPython.display import display
|
|
487
|
+
self._disp_id = str(uuid.uuid4())
|
|
488
|
+
display(self, display_id=self._disp_id)
|
|
489
|
+
threading.Thread(target=self._ipy_status_update).start()
|
|
490
|
+
return self
|
|
491
|
+
|
|
492
|
+
def watch(self):
|
|
493
|
+
rule_watcher.watch(self)
|
|
494
|
+
return self
|
|
495
|
+
|
|
496
|
+
def _get_info(self, queue_info, errors=True):
|
|
497
|
+
"""
|
|
498
|
+
Extract the bit of info which is relevant to this rule
|
|
499
|
+
from the complete queue info dictionary
|
|
500
|
+
"""
|
|
501
|
+
info = {'finished': False}
|
|
502
|
+
info.update(queue_info.get(self._ruleID, {}))
|
|
503
|
+
|
|
504
|
+
if errors:
|
|
505
|
+
if (info.get('tasksFailed', 0) > 0):
|
|
506
|
+
dm = clusterIO.get_dir_manager()
|
|
507
|
+
try:
|
|
508
|
+
info['errors'] = dm.locate_file(f'LOGS/rules/{self._ruleID}.html', True)[0][0]
|
|
509
|
+
except IndexError:
|
|
510
|
+
info['errors'] = None
|
|
511
|
+
else:
|
|
512
|
+
info['errors'] = None
|
|
513
|
+
|
|
514
|
+
info['ID'] = self._ruleID
|
|
515
|
+
|
|
516
|
+
return info
|
|
517
|
+
|
|
518
|
+
def _repr_html_(self):
|
|
519
|
+
info = self.status()
|
|
520
|
+
if not 'tasksPosted' in info:
|
|
521
|
+
return f'<h5>{self.__class__.__name__} ID: {self._ruleID}</h5>'
|
|
522
|
+
else:
|
|
523
|
+
error_info =''
|
|
524
|
+
tr_class = ''
|
|
525
|
+
if info['finished']:
|
|
526
|
+
if info['tasksFailed'] > 0:
|
|
527
|
+
tr_class = ' style="background-color:indianred;" '
|
|
528
|
+
error_info = clusterIO.get_file(f'LOGS/rules/{self._ruleID}.html').decode()
|
|
529
|
+
else:
|
|
530
|
+
tr_class = ' style="background-color:lightgreen;" '
|
|
531
|
+
|
|
532
|
+
rep=f'''
|
|
533
|
+
<h5>{self.__class__.__name__} ID: {self._ruleID}</h5>
|
|
534
|
+
<table class="table table-striped">
|
|
535
|
+
<tr><th>Posted</th><th>Assigned</th><th>Completed</th><th>Failed</th><th>Timed out</th><th>Returned after timeout</th><th>Avg Cost</th><th></th></tr>
|
|
536
|
+
|
|
537
|
+
<tr {tr_class}>
|
|
538
|
+
<td>{ info['tasksPosted'] }</td>
|
|
539
|
+
<td>{ info['tasksRunning'] }</td>
|
|
540
|
+
<td>{ info['tasksCompleted'] }</td>
|
|
541
|
+
<td>{ info['tasksFailed'] }</td>
|
|
542
|
+
<td>{ info['tasksTimedOut'] }</td>
|
|
543
|
+
<td>{ info['tasksCompleteAfterTimeout'] }</td>
|
|
544
|
+
<td>{ info['averageExecutionCost'] }</td>
|
|
545
|
+
<!--<td><button>Abort</button></td>-->
|
|
546
|
+
</tr>
|
|
547
|
+
|
|
548
|
+
</table>
|
|
549
|
+
{error_info}
|
|
550
|
+
'''
|
|
551
|
+
|
|
552
|
+
return rep
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
class RecipeRule(Rule):
|
|
557
|
+
def __init__(self, recipe=None, recipeURI=None, output_dir=None, **kwargs):
|
|
558
|
+
"""
|
|
559
|
+
Create a recipe rule
|
|
560
|
+
|
|
561
|
+
Parameters
|
|
562
|
+
----------
|
|
563
|
+
recipe : str or recipes.modules.ModuleCollection
|
|
564
|
+
The recipe as YAML text or as a recipe instance (alternatively provide recipeURL)
|
|
565
|
+
recipeURI : str
|
|
566
|
+
A cluster URI for the recipe text (if `recipe` not provided directly)
|
|
567
|
+
output_dir : str
|
|
568
|
+
The directory to put the recipe output TODO: should this be templated based on context?
|
|
569
|
+
kwargs : dict
|
|
570
|
+
Parameters for the base `Rule` class (notably `on_completion`, which, if provided, should be a RuleFactory instance).
|
|
571
|
+
Additional parameters, not consumed by `Rule` are accessible in the context used for creating rule templates.
|
|
572
|
+
|
|
573
|
+
One (and only one) of the following keyword parameters should be provided to specify the recipe inputs:
|
|
574
|
+
inputs : dict
|
|
575
|
+
keys are recipe namespace keys, values are either lists of file URIs, or globs which will be expanded
|
|
576
|
+
to a list of URIs. Corresponds to the `inputsByTask` property in the recipe description (see `ruleserver` docs).
|
|
577
|
+
`inputsByTask` will be used by the server to populate the inputs for individual tasks
|
|
578
|
+
input_templates : dict
|
|
579
|
+
simplar to inputs, except that dictionary substitution with the rule context is perfromed on the values before
|
|
580
|
+
they are written to `inputsByTasks`
|
|
581
|
+
rule_outputs : dict
|
|
582
|
+
used with chained recipes, this is the outputs of the previous recipe step. Unlike `inputs` and `input_templates`
|
|
583
|
+
this is a dict of str, rather than of list (or glob-implied list) and is written directly to the `"inputs"` section
|
|
584
|
+
of the template, rather than to the `inputsByTask` property of the rule, short-circuiting server side input filling.
|
|
585
|
+
|
|
586
|
+
TODO - support for templated recipes? Subclass?
|
|
587
|
+
"""
|
|
588
|
+
|
|
589
|
+
if recipe:
|
|
590
|
+
if isinstance(recipe, six.string_types):
|
|
591
|
+
self.recipe_text = recipe
|
|
592
|
+
else:
|
|
593
|
+
self.recipe_text = recipe.toYAML()
|
|
594
|
+
|
|
595
|
+
self.recipeURI = None
|
|
596
|
+
else:
|
|
597
|
+
if recipeURI is None:
|
|
598
|
+
raise ValueError('recipeURI must be defined if no recipe given')
|
|
599
|
+
else:
|
|
600
|
+
self.recipeURI = recipeURI
|
|
601
|
+
|
|
602
|
+
self.output_dir = output_dir
|
|
603
|
+
|
|
604
|
+
Rule.__init__(self, **kwargs)
|
|
605
|
+
|
|
606
|
+
def _populate_rule(self, context, on_completion=None):
|
|
607
|
+
# over-ride here because we need to add input info
|
|
608
|
+
|
|
609
|
+
# try (in order of increasing precedence):
|
|
610
|
+
#
|
|
611
|
+
# - an `input_templates` variable in the context
|
|
612
|
+
# - hard coded `inputs` in the context
|
|
613
|
+
inputs = {} # = context.get('rule_outputs', {})
|
|
614
|
+
input_templates = context.get('input_templates', None)
|
|
615
|
+
if input_templates is not None:
|
|
616
|
+
inputs.update({k: v.format(context) for k, v in input_templates.items()})
|
|
617
|
+
|
|
618
|
+
inputs.update(context.get('inputs', {}))
|
|
619
|
+
|
|
620
|
+
if not inputs:
|
|
621
|
+
if not context.get('rule_outputs', False):
|
|
622
|
+
# NOTE - rule_outputs is handled in _task_template.
|
|
623
|
+
raise RuntimeError('No inputs found, one of "inputs", "input_templates", or "rule_outputs" must be present in context')
|
|
624
|
+
inputs_by_task = None
|
|
625
|
+
else:
|
|
626
|
+
input_names = inputs.keys()
|
|
627
|
+
|
|
628
|
+
def _to_input_list(v):
|
|
629
|
+
# TODO - move this fcn definition??
|
|
630
|
+
if isinstance(v, list):
|
|
631
|
+
return v
|
|
632
|
+
else:
|
|
633
|
+
# value is a string glob
|
|
634
|
+
name, serverfilter = unifiedIO.split_cluster_url(v)
|
|
635
|
+
return clusterIO.cglob(name, serverfilter)
|
|
636
|
+
|
|
637
|
+
inputs = {k: _to_input_list(inputs[k]) for k in input_names}
|
|
638
|
+
|
|
639
|
+
self._num_recipe_tasks = len(list(inputs.values())[0])
|
|
640
|
+
|
|
641
|
+
logger.debug('numTotalFrames = %d' % self._num_recipe_tasks)
|
|
642
|
+
logger.debug('inputs = %s' % inputs)
|
|
643
|
+
|
|
644
|
+
inputs_by_task = {frameNum: {k: inputs[k][frameNum] for k in inputs.keys()} for frameNum in
|
|
645
|
+
range(self._num_recipe_tasks)}
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
rule = Rule._populate_rule(self, context, on_completion=on_completion)
|
|
649
|
+
|
|
650
|
+
if inputs_by_task:
|
|
651
|
+
rule['inputsByTask'] = inputs_by_task
|
|
652
|
+
|
|
653
|
+
return rule
|
|
654
|
+
|
|
655
|
+
def prepare(self):
|
|
656
|
+
return dict(max_tasks=self._num_recipe_tasks, release_start=0, release_end=self._num_recipe_tasks)
|
|
657
|
+
|
|
658
|
+
def _task_template(self, context):
|
|
659
|
+
task = '''{"id": "{{ruleID}}~{{taskID}}",
|
|
660
|
+
"type": "recipe",
|
|
661
|
+
"optimal-chunk-size" : 1,
|
|
662
|
+
"inputs" : {{taskInputs}},
|
|
663
|
+
%s
|
|
664
|
+
}'''
|
|
665
|
+
|
|
666
|
+
if self.output_dir is None:
|
|
667
|
+
output_dir_n = ''
|
|
668
|
+
else:
|
|
669
|
+
output_dir_n = '"output_dir": "%s",\n ' % self.output_dir
|
|
670
|
+
|
|
671
|
+
if self.recipeURI:
|
|
672
|
+
task = task % (output_dir_n + '"taskdefRef" : "%s"' % self.recipeURI)
|
|
673
|
+
else:
|
|
674
|
+
task = task % (output_dir_n + '"taskdef" : {"recipe": "%s"}' % self.recipe_text)
|
|
675
|
+
|
|
676
|
+
#if we are a chained rule, hard-code inputs
|
|
677
|
+
rule_outputs = context.get('rule_outputs', None)
|
|
678
|
+
if rule_outputs is not None:
|
|
679
|
+
#logger.debug(rule_outputs)
|
|
680
|
+
task = task.replace('{{taskInputs}}', json.dumps(rule_outputs))
|
|
681
|
+
logger.debug(task)
|
|
682
|
+
|
|
683
|
+
return task
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
class LocalisationRule(Rule):
|
|
688
|
+
def __init__(self, seriesName, analysisMetadata, resultsFilename=None, startAt=0, dataSourceModule=None, serverfilter=clusterIO.local_serverfilter, **kwargs):
|
|
689
|
+
from PYME.IO import MetaDataHandler
|
|
690
|
+
from PYME.Analysis import MetaData
|
|
691
|
+
from PYME.IO.FileUtils.nameUtils import genClusterResultFileName
|
|
692
|
+
from PYME.IO import unifiedIO
|
|
693
|
+
|
|
694
|
+
unifiedIO.assert_uri_path_ok(seriesName)
|
|
695
|
+
|
|
696
|
+
if resultsFilename is None:
|
|
697
|
+
resultsFilename = genClusterResultFileName(seriesName)
|
|
698
|
+
|
|
699
|
+
resultsFilename = verify_cluster_results_filename(resultsFilename)
|
|
700
|
+
logger.info('Results file: ' + resultsFilename)
|
|
701
|
+
|
|
702
|
+
resultsMdh = MetaDataHandler.NestedClassMDHandler()
|
|
703
|
+
# NB - anything passed in analysis MDH will wipe out corresponding entries in the series metadata
|
|
704
|
+
try:
|
|
705
|
+
resultsMdh.update(json.loads(unifiedIO.read(seriesName + '/metadata.json')))
|
|
706
|
+
except IOError:
|
|
707
|
+
logger.exception('Raw file metadata (%s) not found, continuing with analysis metadata alone. Can probably be ignored for .tiff analysis' % (seriesName + '/metadata.json') )
|
|
708
|
+
resultsMdh.update(analysisMetadata)
|
|
709
|
+
|
|
710
|
+
resultsMdh['EstimatedLaserOnFrameNo'] = resultsMdh.getOrDefault('EstimatedLaserOnFrameNo',
|
|
711
|
+
resultsMdh.getOrDefault('Analysis.StartAt', 0))
|
|
712
|
+
MetaData.fixEMGain(resultsMdh)
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
self._setup(seriesName, resultsMdh, resultsFilename, startAt, serverfilter)
|
|
716
|
+
|
|
717
|
+
#load data source
|
|
718
|
+
if dataSourceModule is None:
|
|
719
|
+
DataSource = DataSources.getDataSourceForFilename(seriesName)
|
|
720
|
+
else:
|
|
721
|
+
DataSource = __import__('PYME.IO.DataSources.' + dataSourceModule,
|
|
722
|
+
fromlist=['PYME', 'io', 'DataSources']).DataSource #import our data source
|
|
723
|
+
|
|
724
|
+
self.ds = DataSource(seriesName)
|
|
725
|
+
|
|
726
|
+
logger.debug('DataSource.__class__: %s' % self.ds.__class__)
|
|
727
|
+
|
|
728
|
+
Rule.__init__(self, **kwargs)
|
|
729
|
+
|
|
730
|
+
def _output_files(self):
|
|
731
|
+
return {'results' : self.resultsURI}
|
|
732
|
+
|
|
733
|
+
def _setup(self, dataSourceID, metadata, resultsFilename, startAt=0, dataSourceModule=None, serverfilter=clusterIO.local_serverfilter):
|
|
734
|
+
self.dataSourceID = dataSourceID
|
|
735
|
+
if '~' in self.dataSourceID or '~' in resultsFilename:
|
|
736
|
+
raise RuntimeError('File, queue or results name must NOT contain ~')
|
|
737
|
+
|
|
738
|
+
#where the results are when we want to read them
|
|
739
|
+
self.resultsURI = 'PYME-CLUSTER://%s/%s' % (serverfilter, resultsFilename)
|
|
740
|
+
|
|
741
|
+
# it's faster (and safer for race condition avoidance) to pick a server in advance and give workers the direct
|
|
742
|
+
# HTTP endpoint to write to. This should also be an aggregate endpoint, as multiple writes are needed.
|
|
743
|
+
self.worker_resultsURI = clusterResults.pickResultsServer('__aggregate_h5r/%s' % resultsFilename, serverfilter)
|
|
744
|
+
|
|
745
|
+
self.resultsMDFilename = resultsFilename + '.json'
|
|
746
|
+
self.results_md_uri = 'PYME-CLUSTER://%s/%s' % (serverfilter, self.resultsMDFilename)
|
|
747
|
+
|
|
748
|
+
self.mdh = metadata
|
|
749
|
+
self.start_at = startAt
|
|
750
|
+
self.serverfilter = serverfilter
|
|
751
|
+
|
|
752
|
+
def _task_template(self, context):
|
|
753
|
+
tt = {'id': '{{ruleID}}~{{taskID}}',
|
|
754
|
+
'type': 'localization',
|
|
755
|
+
'taskdef': {'frameIndex': '{{taskID}}', 'metadata': self.results_md_uri},
|
|
756
|
+
'inputs': {'frames': self.dataSourceID},
|
|
757
|
+
'outputs': {'fitResults': self.worker_resultsURI + '/FitResults',
|
|
758
|
+
'driftResults': self.worker_resultsURI + '/DriftResults'}
|
|
759
|
+
}
|
|
760
|
+
return json.dumps(tt)
|
|
761
|
+
|
|
762
|
+
def prepare(self):
|
|
763
|
+
"""
|
|
764
|
+
Do any setup work - e.g. uploading metadata required before the rule is triggered
|
|
765
|
+
|
|
766
|
+
Returns
|
|
767
|
+
-------
|
|
768
|
+
|
|
769
|
+
post_args : dict
|
|
770
|
+
a dictionary with arguments to pass to RulePusher._post_rule() - specifically timeout, max_tasks, release_start, release_end
|
|
771
|
+
|
|
772
|
+
"""
|
|
773
|
+
#set up results file:
|
|
774
|
+
logging.debug('resultsURI: ' + self.worker_resultsURI)
|
|
775
|
+
clusterResults.fileResults(self.worker_resultsURI + '/MetaData', self.mdh)
|
|
776
|
+
|
|
777
|
+
# defer copying events to after series completion
|
|
778
|
+
#clusterResults.fileResults(self.worker_resultsURI + '/Events', self.ds.getEvents())
|
|
779
|
+
|
|
780
|
+
# set up metadata file which is used for deciding how to launch the analysis
|
|
781
|
+
clusterIO.put_file(self.resultsMDFilename, self.mdh.to_JSON().encode(), serverfilter=self.serverfilter)
|
|
782
|
+
|
|
783
|
+
#wait until clusterIO caches clear to avoid replicating the results file.
|
|
784
|
+
#time.sleep(1.5) #moved inside polling thread so launches will run quicker
|
|
785
|
+
|
|
786
|
+
self._next_release_start = self.start_at
|
|
787
|
+
self.frames_outstanding=self.total_frames - self._next_release_start
|
|
788
|
+
if self.data_complete:
|
|
789
|
+
return dict(max_tasks=self.total_frames)
|
|
790
|
+
return {}
|
|
791
|
+
|
|
792
|
+
@property
|
|
793
|
+
def total_frames(self):
|
|
794
|
+
return self.ds.getNumSlices()
|
|
795
|
+
|
|
796
|
+
@property
|
|
797
|
+
def data_complete(self):
|
|
798
|
+
return self.ds.is_complete
|
|
799
|
+
|
|
800
|
+
@property
|
|
801
|
+
def complete(self):
|
|
802
|
+
"""
|
|
803
|
+
Is this rule complete, or do we need to poll for more input?
|
|
804
|
+
|
|
805
|
+
Over-ridden in localisation rule
|
|
806
|
+
Returns
|
|
807
|
+
-------
|
|
808
|
+
|
|
809
|
+
"""
|
|
810
|
+
return self.data_complete and self.total_frames == self._next_release_start
|
|
811
|
+
|
|
812
|
+
def on_data_complete(self):
|
|
813
|
+
logger.debug('Data complete, copying events to output file')
|
|
814
|
+
clusterResults.fileResults(self.worker_resultsURI + '/Events', self.ds.getEvents())
|
|
815
|
+
|
|
816
|
+
def get_new_tasks(self):
|
|
817
|
+
"""
|
|
818
|
+
Over-ridden in rules where all the data is not gauranteed to be present when the rule is created
|
|
819
|
+
|
|
820
|
+
Returns
|
|
821
|
+
-------
|
|
822
|
+
|
|
823
|
+
release_start, release_end : the indices of starting and ending tasks to release
|
|
824
|
+
|
|
825
|
+
"""
|
|
826
|
+
numTotalFrames = self.total_frames
|
|
827
|
+
logging.debug('numTotalFrames: %s, _next_release_start: %d' % (numTotalFrames, self._next_release_start))
|
|
828
|
+
|
|
829
|
+
if numTotalFrames <= self._next_release_start:
|
|
830
|
+
raise NoNewTasks('not new localisation tasks available at this time')
|
|
831
|
+
else:
|
|
832
|
+
logging.debug('we have unpublished frames - push them')
|
|
833
|
+
release_end = min(self._next_release_start + 100000, numTotalFrames)
|
|
834
|
+
release_start = self._next_release_start
|
|
835
|
+
self._next_release_start = release_end #note - we use standard slice indexing where release_end = last_frame_idx +1 = the start idx of the next release
|
|
836
|
+
self.frames_outstanding = numTotalFrames - self._next_release_start
|
|
837
|
+
|
|
838
|
+
return release_start, release_end
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
class SpoolLocalLocalizationRule(LocalisationRule):
|
|
842
|
+
def __init__(self, spooler, seriesName, analysisMetadata, resultsFilename=None, startAt=0, serverfilter=clusterIO.local_serverfilter, **kwargs):
|
|
843
|
+
# TODO - reduce duplication of `LocalisationRule.__init__()` and `LocalisationRule._setup()`
|
|
844
|
+
from PYME.IO import MetaDataHandler
|
|
845
|
+
from PYME.Analysis import MetaData
|
|
846
|
+
from PYME.IO.FileUtils.nameUtils import genClusterResultFileName
|
|
847
|
+
from PYME.IO import unifiedIO
|
|
848
|
+
|
|
849
|
+
self.spooler = spooler
|
|
850
|
+
|
|
851
|
+
if resultsFilename is None:
|
|
852
|
+
resultsFilename = genClusterResultFileName(seriesName)
|
|
853
|
+
|
|
854
|
+
resultsFilename = verify_cluster_results_filename(resultsFilename)
|
|
855
|
+
logger.info('Results file: ' + resultsFilename)
|
|
856
|
+
|
|
857
|
+
resultsMdh = MetaDataHandler.DictMDHandler()
|
|
858
|
+
# NB - anything passed in analysis MDH will wipe out corresponding entries in the series metadata
|
|
859
|
+
resultsMdh.update(self.spooler.md)
|
|
860
|
+
resultsMdh.update(analysisMetadata)
|
|
861
|
+
resultsMdh['EstimatedLaserOnFrameNo'] = resultsMdh.getOrDefault('EstimatedLaserOnFrameNo',
|
|
862
|
+
resultsMdh.getOrDefault('Analysis.StartAt', 0))
|
|
863
|
+
MetaData.fixEMGain(resultsMdh)
|
|
864
|
+
|
|
865
|
+
self._setup(seriesName, resultsMdh, resultsFilename, startAt, serverfilter)
|
|
866
|
+
|
|
867
|
+
Rule.__init__(self, **kwargs)
|
|
868
|
+
|
|
869
|
+
@property
|
|
870
|
+
def total_frames(self):
|
|
871
|
+
return self.spooler.get_n_frames()
|
|
872
|
+
|
|
873
|
+
@property
|
|
874
|
+
def data_complete(self):
|
|
875
|
+
try:
|
|
876
|
+
return self.spooler.finished()
|
|
877
|
+
except RuntimeError as e:
|
|
878
|
+
logger.error(str(e))
|
|
879
|
+
logger.info('marking data as complete')
|
|
880
|
+
return True
|
|
881
|
+
|
|
882
|
+
def on_data_complete(self):
|
|
883
|
+
events = self.spooler.evtLogger.to_recarray()
|
|
884
|
+
clusterResults.fileResults(self.worker_resultsURI + '/Events', events)
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
class RuleFactory(object):
|
|
888
|
+
_type = ''
|
|
889
|
+
def __init__(self, on_completion=None, rule_class = Rule, **kwargs):
|
|
890
|
+
"""
|
|
891
|
+
Create a new rule factory. Sub-classed for specific rule types
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
Parameters
|
|
895
|
+
----------
|
|
896
|
+
on_completion : RuleFactory instance
|
|
897
|
+
A rule to run after this one has completed (also setable using the `.chain()` method)
|
|
898
|
+
|
|
899
|
+
kwargs : any additional arguments (ignored in base class)
|
|
900
|
+
|
|
901
|
+
"""
|
|
902
|
+
self._on_completion = on_completion
|
|
903
|
+
self._rule_class = rule_class
|
|
904
|
+
self._rule_kwargs = kwargs
|
|
905
|
+
|
|
906
|
+
def get_rule(self, context):
|
|
907
|
+
"""
|
|
908
|
+
Populate a rule using series specific info from context. Note that
|
|
909
|
+
the the rule class initialization arguments should be passed in the
|
|
910
|
+
RuleFactory initialization as kwargs, but can also be passed here in
|
|
911
|
+
context if, e.g. the series name is not known when creating the
|
|
912
|
+
|
|
913
|
+
Parameters
|
|
914
|
+
----------
|
|
915
|
+
context : dict
|
|
916
|
+
a dictionary containing series specific info to populate into the task template
|
|
917
|
+
|
|
918
|
+
Returns
|
|
919
|
+
-------
|
|
920
|
+
Rule
|
|
921
|
+
a rule suitable for submitting to the ruleserver `/add_integer_id_rule`
|
|
922
|
+
endpoint
|
|
923
|
+
|
|
924
|
+
"""
|
|
925
|
+
|
|
926
|
+
d = dict(self._rule_kwargs)
|
|
927
|
+
d.update(context)
|
|
928
|
+
|
|
929
|
+
return self._rule_class(on_completion=self._on_completion, **d)
|
|
930
|
+
|
|
931
|
+
def chain(self, on_completion):
|
|
932
|
+
"""
|
|
933
|
+
Chain a rule (as an alternative to passing on_completion to the rule constructor, allows us to create rule chains
|
|
934
|
+
from front to back rather than back to front
|
|
935
|
+
|
|
936
|
+
Parameters
|
|
937
|
+
----------
|
|
938
|
+
|
|
939
|
+
on_completion : RuleFactory instance
|
|
940
|
+
The rule to run after this one has completed
|
|
941
|
+
"""
|
|
942
|
+
assert(isinstance(on_completion, RuleFactory))
|
|
943
|
+
self._on_completion = on_completion
|
|
944
|
+
|
|
945
|
+
@property
|
|
946
|
+
def rule_type(self):
|
|
947
|
+
# TODO - rename to something like `display_name` of `display_type` to indicate that this is a UI helper function.
|
|
948
|
+
# TODO - do we need a function for this, or can we just have a property?
|
|
949
|
+
return self._type
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
class RecipeRuleFactory(RuleFactory):
|
|
953
|
+
_type = 'recipe'
|
|
954
|
+
def __init__(self, **kwargs):
|
|
955
|
+
RuleFactory.__init__(self, rule_class=RecipeRule, **kwargs)
|
|
956
|
+
|
|
957
|
+
class LocalisationRuleFactory(RuleFactory):
|
|
958
|
+
_type = 'localization'
|
|
959
|
+
def __init__(self, **kwargs):
|
|
960
|
+
"""
|
|
961
|
+
See `LocalisationRule` for full initialization arguments. Required
|
|
962
|
+
kwargs are:
|
|
963
|
+
|
|
964
|
+
:seriesName : str
|
|
965
|
+
:analysisMetadata : PYME.IO.MetaDataHandler.MDHandlerBase
|
|
966
|
+
"""
|
|
967
|
+
RuleFactory.__init__(self, rule_class=LocalisationRule, **kwargs)
|
|
968
|
+
|
|
969
|
+
class SpoolLocalLocalizationRuleFactory(RuleFactory):
|
|
970
|
+
_type = 'localization'
|
|
971
|
+
def __init__(self, **kwargs):
|
|
972
|
+
"""
|
|
973
|
+
See `SpoolLocalLocalizationRule` for full initialization arguments.
|
|
974
|
+
Required kwargs are:
|
|
975
|
+
|
|
976
|
+
:seriesName : str
|
|
977
|
+
:analysisMetadata : PYME.IO.MetaDataHandler.MDHandlerBase
|
|
978
|
+
"""
|
|
979
|
+
RuleFactory.__init__(self, rule_class=SpoolLocalLocalizationRule, **kwargs)
|