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/recipes/base.py
ADDED
|
@@ -0,0 +1,1393 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from __future__ import print_function
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Created on Mon May 25 17:02:04 2015
|
|
6
|
+
|
|
7
|
+
@author: david
|
|
8
|
+
"""
|
|
9
|
+
#import wx
|
|
10
|
+
import six
|
|
11
|
+
|
|
12
|
+
from PYME.recipes.traits import HasTraits, HasStrictTraits, Float, List, Bool, Int, CStr, Enum, File, on_trait_change, Input, Output, Instance, WeakRef
|
|
13
|
+
|
|
14
|
+
#for some reason traitsui raises SystemExit when called from sphinx on OSX
|
|
15
|
+
#This is due to the framework build problem of anaconda on OSX, and also
|
|
16
|
+
#creates a problem whenever there is no GUI available.
|
|
17
|
+
#as we want to be able to use recipes without a GUI (presumably the reason for this problem)
|
|
18
|
+
#it's prudent to catch this and spoof the View and Item functions which are not going to be used anyway
|
|
19
|
+
#try:
|
|
20
|
+
#from traitsui.api import View, Item, Group# EnumEditor, InstanceEditor, Group
|
|
21
|
+
#except SystemExit:
|
|
22
|
+
# print('Got stupid OSX SystemExit exception - using dummy traitsui')
|
|
23
|
+
# from PYME.misc.mock_traitsui import *
|
|
24
|
+
|
|
25
|
+
from PYME.IO.image import ImageStack
|
|
26
|
+
import numpy as np
|
|
27
|
+
from PYME import config
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
import dask.array as da
|
|
31
|
+
except ImportError:
|
|
32
|
+
da = None
|
|
33
|
+
|
|
34
|
+
import logging
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
import yaml
|
|
38
|
+
class MyDumper(yaml.SafeDumper):
|
|
39
|
+
def represent_mapping(self, tag, value, flow_style=None):
|
|
40
|
+
return super(MyDumper, self).represent_mapping(tag, value, False)
|
|
41
|
+
|
|
42
|
+
# make sure we can dump metadata to yaml
|
|
43
|
+
from PYME.IO import MetaDataHandler
|
|
44
|
+
MyDumper.add_multi_representer(MetaDataHandler.MDHandlerBase, yaml.representer.SafeRepresenter.represent_dict)
|
|
45
|
+
|
|
46
|
+
# TODO - move to recipe.py?
|
|
47
|
+
all_modules = {}
|
|
48
|
+
_legacy_modules = {}
|
|
49
|
+
module_names = {}
|
|
50
|
+
|
|
51
|
+
def get_parsable_module_info():
|
|
52
|
+
"""
|
|
53
|
+
Returns a dictionary of all modules, suitable for parsing by an LLM or similar.
|
|
54
|
+
|
|
55
|
+
The dictionary contains the module name, its docstring, and a list of inputs, outputs, and parameters.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
dict
|
|
60
|
+
A dictionary with module names as keys and their schema as values.
|
|
61
|
+
"""
|
|
62
|
+
return {k: v.module_schema() for k, v in all_modules.items()}
|
|
63
|
+
|
|
64
|
+
def register_module(moduleName, prefix=None):
|
|
65
|
+
"""
|
|
66
|
+
Register a module so that it is discoverable by the recipe architecture
|
|
67
|
+
|
|
68
|
+
Recipe module prefixes are treated slightly differently depending on whether it is a PYME internal
|
|
69
|
+
recipe, or comes from an external module. For PYME-internal recipe modules, their prefix is the name
|
|
70
|
+
of the (python) module in which the recipe is defined. For external (plugin) recipe modules, it is
|
|
71
|
+
the name of the python **package** which contains the recipe module - a plugin may define multiple
|
|
72
|
+
recipes in different files, but they will all be accessible using the package prefix. This is a change
|
|
73
|
+
from previous behaviour where the most proximal module name was used in plugin derived modules (similar
|
|
74
|
+
to internal recipe modules). This change was made to a) decrease the chance of collisions, where plugin
|
|
75
|
+
modules shadowed exisiting internal recipe modules and b) make module provenance (is this an internal
|
|
76
|
+
or plugin-derived module) clear to assist debugging.
|
|
77
|
+
|
|
78
|
+
If the plugin package name is not sufficiently distinctive, or happens to shadow any of the internal
|
|
79
|
+
PYME recipe module names, plugin authors have the opportuntiy to specify their own prefix as a second
|
|
80
|
+
argument to register_module. If taking this route, the prefix should be an identifier of the
|
|
81
|
+
group/individual maintaining the plugin - e.g. baddeleylab.
|
|
82
|
+
"""
|
|
83
|
+
def c_decorate(cls):
|
|
84
|
+
if not prefix:
|
|
85
|
+
top_level_mod = cls.__module__.split('.')[0]
|
|
86
|
+
py_module = cls.__module__.split('.')[-1]
|
|
87
|
+
|
|
88
|
+
if top_level_mod == 'PYME':
|
|
89
|
+
prefix_ = py_module
|
|
90
|
+
else:
|
|
91
|
+
prefix_ = top_level_mod
|
|
92
|
+
else:
|
|
93
|
+
prefix_ = prefix
|
|
94
|
+
|
|
95
|
+
full_module_name = '.'.join([prefix_, moduleName])
|
|
96
|
+
|
|
97
|
+
all_modules[full_module_name] = cls
|
|
98
|
+
_legacy_modules[moduleName] = cls #allow acces by non-hierarchical names for backwards compatibility
|
|
99
|
+
|
|
100
|
+
module_names[cls] = full_module_name
|
|
101
|
+
cls._module_name = full_module_name
|
|
102
|
+
cls._short_name = moduleName # for use in metadata generation
|
|
103
|
+
return cls
|
|
104
|
+
|
|
105
|
+
return c_decorate
|
|
106
|
+
|
|
107
|
+
def register_legacy_module(moduleName, py_module=None):
|
|
108
|
+
"""Permits a module to be accessed by an old name"""
|
|
109
|
+
|
|
110
|
+
def c_decorate(cls):
|
|
111
|
+
if py_module is None:
|
|
112
|
+
py_module_ = cls.__module__.split('.')[-1]
|
|
113
|
+
else:
|
|
114
|
+
py_module_ = py_module
|
|
115
|
+
|
|
116
|
+
full_module_name = '.'.join([py_module_, moduleName])
|
|
117
|
+
|
|
118
|
+
_legacy_modules[full_module_name] = cls
|
|
119
|
+
_legacy_modules[moduleName] = cls #allow access by non-hierarchical names for backwards compatibility
|
|
120
|
+
|
|
121
|
+
cls._module_name = full_module_name
|
|
122
|
+
|
|
123
|
+
#module_names[cls] = full_module_name
|
|
124
|
+
return cls
|
|
125
|
+
|
|
126
|
+
return c_decorate
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class MissingInputError(Exception):
|
|
130
|
+
pass
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class ModuleBase(HasStrictTraits):
|
|
134
|
+
"""
|
|
135
|
+
Recipe modules represent a "functional" processing block, the effects of which depend solely on its
|
|
136
|
+
inputs and parameters. They read a number of named inputs from the recipe namespace and write the
|
|
137
|
+
results of their computation back to one or more named output variables in the recipe namespace.
|
|
138
|
+
|
|
139
|
+
They must not modify anything other than their named output variables, and should not maintain state
|
|
140
|
+
between executions (no side effects). This is critical in ensuring that repeat executions of the same
|
|
141
|
+
recipe are reproducible and in allowing the incremental update (without re-running every module) when
|
|
142
|
+
the parameters of one module change.
|
|
143
|
+
|
|
144
|
+
If you want side effects - e.g. saving something to disk, look at the OutputModule class.
|
|
145
|
+
"""
|
|
146
|
+
_invalidate_parent = Bool(True)
|
|
147
|
+
_parent=WeakRef(object, allow_none=True)
|
|
148
|
+
|
|
149
|
+
_initial_set = Bool(False)
|
|
150
|
+
_success = Bool(False)
|
|
151
|
+
_last_error = Instance(object)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def __init__(self, parent=None, invalidate_parent = True, **kwargs):
|
|
155
|
+
self._parent = parent
|
|
156
|
+
self._invalidate_parent = invalidate_parent
|
|
157
|
+
|
|
158
|
+
HasTraits.__init__(self)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
if (parent is not None):
|
|
162
|
+
# make sure that the default output name does not collide with any outputs
|
|
163
|
+
# already in the recipe
|
|
164
|
+
for k, v in self._output_traits.items():
|
|
165
|
+
if v in parent.module_outputs:
|
|
166
|
+
duplicate_num = 0
|
|
167
|
+
val = v
|
|
168
|
+
|
|
169
|
+
while (val in parent.module_outputs):
|
|
170
|
+
# we already have an output of that name in the recipe
|
|
171
|
+
# increase the subscript until we get a unique value
|
|
172
|
+
duplicate_num += 1
|
|
173
|
+
val = v + '_%d' % duplicate_num
|
|
174
|
+
|
|
175
|
+
self.trait_set(**{k:val})
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# if an input matches the default value for an output, our circular reference check will fail, even if we are
|
|
179
|
+
# setting both values to good values in the kwargs (see issue #695). To mitigate, we first set without validation
|
|
180
|
+
# to overwrite any default values which may be modified, and then re-set with validation turned on to catch any
|
|
181
|
+
# circular references in the final values.
|
|
182
|
+
self._initial_set = False
|
|
183
|
+
self.trait_set(trait_change_notify=False, **kwargs) #don't notify here - next set will do notification.
|
|
184
|
+
self._initial_set = True
|
|
185
|
+
|
|
186
|
+
# validate input and outputs now that output names have been set.
|
|
187
|
+
# for now, just set all the values again to re-trigger validation
|
|
188
|
+
self.trait_set(**kwargs)
|
|
189
|
+
|
|
190
|
+
self._check_outputs()
|
|
191
|
+
|
|
192
|
+
@on_trait_change('anytrait')
|
|
193
|
+
def invalidate_parent(self, name='', new=None):
|
|
194
|
+
#print('invalidate_parent', name, new)
|
|
195
|
+
if (name == 'trait_added') or name.startswith('_'):
|
|
196
|
+
# don't trigger on private variables
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
if self._invalidate_parent and not self._parent is None:
|
|
200
|
+
#print('invalidating')
|
|
201
|
+
self._parent.prune_dependencies_from_namespace(self.outputs)
|
|
202
|
+
|
|
203
|
+
self._parent.invalidate_data()
|
|
204
|
+
|
|
205
|
+
def _check_outputs(self):
|
|
206
|
+
"""
|
|
207
|
+
This function exists to help with debugging when writing a new recipe module. It generates an
|
|
208
|
+
exception if no outputs have been defined (a module with no outputs will never execute).
|
|
209
|
+
|
|
210
|
+
Over-ridden in the special case IO modules derived from OutputModule as these are permitted to
|
|
211
|
+
have side-effects, but not permitted to have classical outputs to the namespace and will execute
|
|
212
|
+
(when appropriate) regardless.
|
|
213
|
+
"""
|
|
214
|
+
if len(self.outputs) == 0:
|
|
215
|
+
raise RuntimeError('Module should define at least one output.')
|
|
216
|
+
|
|
217
|
+
def cleaned_dict_repr(self):
|
|
218
|
+
ct = self.class_traits()
|
|
219
|
+
|
|
220
|
+
mod_traits_cleaned = {}
|
|
221
|
+
params = self.trait_get().items()
|
|
222
|
+
for k, v in params:
|
|
223
|
+
if not k.startswith('_'): #don't save private data - this is usually used for caching etc ..,
|
|
224
|
+
try:
|
|
225
|
+
if (not (v == ct[k].default)) or (k.startswith('input')) or (k.startswith('output')) or isinstance(ct[k], (Input, Output)):
|
|
226
|
+
#don't save defaults
|
|
227
|
+
if isinstance(v, dict) and not type(v) == dict:
|
|
228
|
+
v = dict(v)
|
|
229
|
+
elif isinstance(v, list) and not type(v) == list:
|
|
230
|
+
v = list(v)
|
|
231
|
+
elif isinstance(v, set) and not type(v) == set:
|
|
232
|
+
v = set(v)
|
|
233
|
+
|
|
234
|
+
mod_traits_cleaned[k] = v
|
|
235
|
+
except KeyError:
|
|
236
|
+
# for some reason we have a trait that shouldn't be here
|
|
237
|
+
pass
|
|
238
|
+
return {module_names[self.__class__]: mod_traits_cleaned}
|
|
239
|
+
|
|
240
|
+
def toYAML(self):
|
|
241
|
+
return yaml.dump(self.cleaned_dict_repr(), Dumper=MyDumper)
|
|
242
|
+
|
|
243
|
+
@classmethod
|
|
244
|
+
def file_or_uri_traits(cls):
|
|
245
|
+
from PYME.recipes import traits
|
|
246
|
+
"""Return a list of FileOrURI traits, as these can require special handling (potentially warn if this list is not empty)"""
|
|
247
|
+
return [k for k, v in cls.class_traits().items() if isinstance(v.trait_type, traits.FileOrURI)]
|
|
248
|
+
|
|
249
|
+
@classmethod
|
|
250
|
+
def module_schema(cls):
|
|
251
|
+
"""Return a dictionary, suitable for feeding to an LLM or similar which describes the module, its inputs, outputs, and parameters."""
|
|
252
|
+
|
|
253
|
+
from PYME.recipes import traits
|
|
254
|
+
|
|
255
|
+
ct = cls.class_traits()
|
|
256
|
+
|
|
257
|
+
schema = {
|
|
258
|
+
'name': module_names[cls],
|
|
259
|
+
'docstring': cls.__doc__,
|
|
260
|
+
'baseclass': cls.__bases__[0].__name__, # Useful to know if it derives from Filter, OutputModule etc ...
|
|
261
|
+
'inputs': [],
|
|
262
|
+
'outputs': [],
|
|
263
|
+
'parameters': [],
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
for k in cls.class_editable_traits():
|
|
267
|
+
if not k.startswith('_'):
|
|
268
|
+
v = ct[k]
|
|
269
|
+
if isinstance(v.trait_type, traits.Input):
|
|
270
|
+
schema['inputs'].append({
|
|
271
|
+
'name': k,
|
|
272
|
+
#'type': v.trait_type.type,
|
|
273
|
+
'description': v.desc,
|
|
274
|
+
})
|
|
275
|
+
elif isinstance(v.trait_type, traits.Output):
|
|
276
|
+
schema['outputs'].append({
|
|
277
|
+
'name': k,
|
|
278
|
+
#'type': v.trait_type.type,
|
|
279
|
+
'description': v.desc,
|
|
280
|
+
})
|
|
281
|
+
else:
|
|
282
|
+
default = v.trait_type.default_value if hasattr(v.trait_type, 'default_value') else None
|
|
283
|
+
if isinstance(default, range):
|
|
284
|
+
default = str(default) # handle unserialisable range objects
|
|
285
|
+
|
|
286
|
+
pd = {
|
|
287
|
+
'name': k,
|
|
288
|
+
'type': str(v.trait_type.__class__.__name__),
|
|
289
|
+
'default': default,
|
|
290
|
+
'description': v.desc,
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
if hasattr(v.trait_type, 'values') and (v.trait_type.values is not None):
|
|
295
|
+
# if the trait has a set of possible values (e.g. Enum), add to the schema
|
|
296
|
+
pd['accepted_values'] = list(v.trait_type.values)
|
|
297
|
+
|
|
298
|
+
schema['parameters'].append(pd)
|
|
299
|
+
|
|
300
|
+
return schema
|
|
301
|
+
|
|
302
|
+
def check_inputs(self, namespace):
|
|
303
|
+
"""
|
|
304
|
+
Checks that module inputs are present in namespace, raising an exception if they are missing. Existing to simplify
|
|
305
|
+
debugging, this function is called in ModuleCollection.execute prior to executing the module so that an
|
|
306
|
+
informative error message is generated if the inputs are missing (rather than the somewhat cryptic KeyError
|
|
307
|
+
you would get when a module tries to access a missing input.
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
Parameters
|
|
311
|
+
----------
|
|
312
|
+
namespace
|
|
313
|
+
|
|
314
|
+
"""
|
|
315
|
+
keys = list(namespace.keys())
|
|
316
|
+
|
|
317
|
+
for input in self.inputs:
|
|
318
|
+
if not input in keys:
|
|
319
|
+
raise MissingInputError('Input "%s" is missing from namespace; keys: %s' % (input, keys))
|
|
320
|
+
|
|
321
|
+
def outputs_in_namespace(self, namespace):
|
|
322
|
+
keys = namespace.keys()
|
|
323
|
+
return np.all([op in keys for op in self.outputs])
|
|
324
|
+
|
|
325
|
+
def execute(self, namespace):
|
|
326
|
+
"""
|
|
327
|
+
takes a namespace (a dictionary like object) from which it reads its inputs and
|
|
328
|
+
into which it writes outputs
|
|
329
|
+
|
|
330
|
+
NOTE: This was previously the function to define / override to make a module work. To support automatic metadata propagation
|
|
331
|
+
and reduce the ammount of boiler plate, new modules should override the `run()` method instead.
|
|
332
|
+
"""
|
|
333
|
+
from PYME.IO import MetaDataHandler
|
|
334
|
+
inputs = {k: namespace[v] for k, v in self._input_traits.items()}
|
|
335
|
+
|
|
336
|
+
ret = self.run(**inputs)
|
|
337
|
+
|
|
338
|
+
# convert output to a dictionary if needed
|
|
339
|
+
if isinstance(ret, dict):
|
|
340
|
+
out = {k : ret[v] for v, k in self._output_traits.items()}
|
|
341
|
+
elif isinstance(ret, List):
|
|
342
|
+
out = {k : v for k, v in zip(self.outputs, ret)} #TODO - is this safe (is ordering consistent)
|
|
343
|
+
else:
|
|
344
|
+
# single output
|
|
345
|
+
if len(self.outputs) > 1:
|
|
346
|
+
raise RuntimeError('Module has multiple outputs, but .run() returns a single value')
|
|
347
|
+
|
|
348
|
+
out = {list(self.outputs)[0] : ret}
|
|
349
|
+
|
|
350
|
+
# complete metadata (injecting as appropriate)
|
|
351
|
+
mdhin = MetaDataHandler.DictMDHandler(getattr(list(inputs.values())[0], 'mdh', None))
|
|
352
|
+
|
|
353
|
+
mdh = MetaDataHandler.DictMDHandler()
|
|
354
|
+
self._params_to_metadata(mdh)
|
|
355
|
+
|
|
356
|
+
for v in out.values():
|
|
357
|
+
if getattr(v, 'mdh', None) is None:
|
|
358
|
+
v.mdh = MetaDataHandler.DictMDHandler()
|
|
359
|
+
|
|
360
|
+
v.mdh.mergeEntriesFrom(mdhin) #merge, to allow e.g. voxel size overrides due to downsampling
|
|
361
|
+
#print(v.mdh, mdh)
|
|
362
|
+
v.mdh.copyEntriesFrom(mdh) # copy / overwrite with module processing parameters
|
|
363
|
+
|
|
364
|
+
namespace.update(out)
|
|
365
|
+
|
|
366
|
+
def run(self, **kwargs):
|
|
367
|
+
"""
|
|
368
|
+
OVERRIDE THIS in derived classes to implement module functionality. Parameters are passed in by keyword, and keyword names must
|
|
369
|
+
be a 1:1 match to the module input traits.
|
|
370
|
+
|
|
371
|
+
The function should return either a dict (multiple outputs, keyed with output trait keys), or
|
|
372
|
+
"""
|
|
373
|
+
raise NotImplementedError
|
|
374
|
+
|
|
375
|
+
def apply(self, *args, **kwargs):
|
|
376
|
+
"""
|
|
377
|
+
Execute this module on the given input without the need for creating a recipe. Creates a namespace, populates it,
|
|
378
|
+
runs the module, and returns a dictionary of outputs.
|
|
379
|
+
|
|
380
|
+
If a module has a single input, you can provide the input directly as the first and only argument. If the module
|
|
381
|
+
supports multiple inputs, they must be specified using keyword arguments.
|
|
382
|
+
|
|
383
|
+
NOTE: Use the trait names as keys.
|
|
384
|
+
|
|
385
|
+
If the module has only one output, using apply_simple() will automatically pull it out of the namespace and return it.
|
|
386
|
+
|
|
387
|
+
Parameters
|
|
388
|
+
----------
|
|
389
|
+
args
|
|
390
|
+
kwargs
|
|
391
|
+
|
|
392
|
+
Returns
|
|
393
|
+
-------
|
|
394
|
+
|
|
395
|
+
"""
|
|
396
|
+
namespace = dict()
|
|
397
|
+
|
|
398
|
+
ips = list(self.inputs)
|
|
399
|
+
|
|
400
|
+
if (len(ips) == 1) and (len(args) == 1):
|
|
401
|
+
namespace[ips[0]] = args[0]
|
|
402
|
+
elif (len(args) > 0):
|
|
403
|
+
raise RuntimeError('This module has multiple inputs, please use keyword arguments')
|
|
404
|
+
else:
|
|
405
|
+
for k, v in kwargs.items():
|
|
406
|
+
namespace[getattr(self, k)] = v
|
|
407
|
+
|
|
408
|
+
self.execute(namespace)
|
|
409
|
+
|
|
410
|
+
return {k : namespace[k] for k in self.outputs}
|
|
411
|
+
|
|
412
|
+
def apply_simple(self, *args, **kwargs):
|
|
413
|
+
"""
|
|
414
|
+
See documentaion for `self.apply` above - this allows single output modules to be used as though they were functions.
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
Parameters
|
|
418
|
+
----------
|
|
419
|
+
args
|
|
420
|
+
kwargs
|
|
421
|
+
|
|
422
|
+
Returns
|
|
423
|
+
-------
|
|
424
|
+
|
|
425
|
+
"""
|
|
426
|
+
if (len(self.outputs) > 1):
|
|
427
|
+
raise RuntimeError('Module has multiple outputs - use apply instead')
|
|
428
|
+
|
|
429
|
+
return self.apply(*args, **kwargs)[next(iter(self.outputs))]
|
|
430
|
+
|
|
431
|
+
@property
|
|
432
|
+
def inputs(self):
|
|
433
|
+
"""
|
|
434
|
+
Get module inputs
|
|
435
|
+
|
|
436
|
+
Returns
|
|
437
|
+
-------
|
|
438
|
+
set of input names
|
|
439
|
+
"""
|
|
440
|
+
#return {v for k, v in self.trait_get().items() if (k.startswith('input') or isinstance(k, Input)) and not v == ''}
|
|
441
|
+
return set(self._input_traits.values())
|
|
442
|
+
|
|
443
|
+
@property
|
|
444
|
+
def _input_traits(self):
|
|
445
|
+
return {k:getattr(self,k) for k, v in self.traits().items() if (k.startswith('input') or isinstance(v.trait_type, Input)) and not getattr(self, k) == ''}
|
|
446
|
+
|
|
447
|
+
@property
|
|
448
|
+
def _output_traits(self):
|
|
449
|
+
#return {k:v for k, v in self.trait_get().items() if (k.startswith('output') or isinstance(k, Output)) and not v ==''}
|
|
450
|
+
return {k:getattr(self,k) for k, v in self.traits().items() if (isinstance(v.trait_type, Output)) and not getattr(self, k) == ''}
|
|
451
|
+
|
|
452
|
+
@property
|
|
453
|
+
def outputs(self):
|
|
454
|
+
"""
|
|
455
|
+
Get module outputs
|
|
456
|
+
|
|
457
|
+
Returns
|
|
458
|
+
-------
|
|
459
|
+
set of output names
|
|
460
|
+
"""
|
|
461
|
+
return set(self._output_traits.values())
|
|
462
|
+
|
|
463
|
+
@property
|
|
464
|
+
def file_inputs(self):
|
|
465
|
+
"""
|
|
466
|
+
Allows templated file names which will be substituted when a user runs the recipe
|
|
467
|
+
|
|
468
|
+
Any key of the form {USERFILEXXXXXX} where XXXXXX is a unique name for this input will then give rise to a
|
|
469
|
+
file input box and will be replaced by the file path / URI in the recipe.
|
|
470
|
+
|
|
471
|
+
Returns
|
|
472
|
+
-------
|
|
473
|
+
inputs: list
|
|
474
|
+
keys for any inputs which should be substituted
|
|
475
|
+
|
|
476
|
+
"""
|
|
477
|
+
return [v.lstrip('{').rstrip('}') for k, v in self.trait_get().items() if isinstance(v, six.string_types) and v.startswith('{USERFILE')]
|
|
478
|
+
|
|
479
|
+
def get_name(self):
|
|
480
|
+
"""
|
|
481
|
+
|
|
482
|
+
Returns
|
|
483
|
+
-------
|
|
484
|
+
registered_name : str
|
|
485
|
+
returns the name of this recipe module as it is registered and will be displayed in e.g. 'Add Module' menus.
|
|
486
|
+
"""
|
|
487
|
+
return module_names[self.__class__]
|
|
488
|
+
|
|
489
|
+
def trait_view(self, name=None, view_element=None):
|
|
490
|
+
import traitsui.api as tui
|
|
491
|
+
from six import string_types
|
|
492
|
+
|
|
493
|
+
if view_element is None and isinstance(name, string_types):
|
|
494
|
+
try:
|
|
495
|
+
tc = getattr(self, name)
|
|
496
|
+
|
|
497
|
+
if isinstance(tc, tui.View):
|
|
498
|
+
return tc
|
|
499
|
+
except AttributeError:
|
|
500
|
+
pass
|
|
501
|
+
|
|
502
|
+
return HasTraits.trait_view(self, name, view_element)
|
|
503
|
+
|
|
504
|
+
def edit_no_invalidate(self, *args, **kwargs):
|
|
505
|
+
inv_mode = self._invalidate_parent
|
|
506
|
+
|
|
507
|
+
try:
|
|
508
|
+
old_traits = self.trait_get()
|
|
509
|
+
#print('turning off invalidation')
|
|
510
|
+
self._invalidate_parent = False
|
|
511
|
+
#print('edit_traits')
|
|
512
|
+
self.edit_traits(*args, kind='modal', **kwargs)
|
|
513
|
+
self._invalidate_parent = inv_mode
|
|
514
|
+
if not self.trait_get() == old_traits:
|
|
515
|
+
#print(self.trait_get(), old_traits)
|
|
516
|
+
#print('invalidating ...')
|
|
517
|
+
self.invalidate_parent()
|
|
518
|
+
finally:
|
|
519
|
+
self._invalidate_parent = inv_mode
|
|
520
|
+
|
|
521
|
+
@property
|
|
522
|
+
def hide_in_overview(self):
|
|
523
|
+
return []
|
|
524
|
+
|
|
525
|
+
def get_params(self):
|
|
526
|
+
t = self.traits()
|
|
527
|
+
editable = self.class_editable_traits()
|
|
528
|
+
inputs = [tn for tn in editable if (tn.startswith('input') or isinstance(t[tn].trait_type, Input))]
|
|
529
|
+
outputs = [tn for tn in editable if (tn.startswith('output') or isinstance(t[tn].trait_type, Output))]
|
|
530
|
+
params = [tn for tn in editable if not (tn in inputs or tn in outputs or tn.startswith('_'))]
|
|
531
|
+
|
|
532
|
+
return inputs, outputs, params
|
|
533
|
+
|
|
534
|
+
def _params_to_metadata(self, mdh):
|
|
535
|
+
"""
|
|
536
|
+
Automatically populate metadata with module parameters
|
|
537
|
+
|
|
538
|
+
This currently gets called manually in a few modules ...
|
|
539
|
+
|
|
540
|
+
TODO - make this automatic.
|
|
541
|
+
TODO? - resolve ambiguities when the same module appears twice in a recipe (the metadata
|
|
542
|
+
will currently reflect the settings of the last module to operate on the data). In practice,
|
|
543
|
+
probably best addressed by simply saving the whole recipe into the metadata in the output module
|
|
544
|
+
and then not worrying about the metadata entries saved by individual modules.
|
|
545
|
+
"""
|
|
546
|
+
_, _, params = self.get_params()
|
|
547
|
+
|
|
548
|
+
for p in params:
|
|
549
|
+
p_name = ''.join([s.capitalize() for s in p.split('_')]) #convert to camel case to follow metadata conventions
|
|
550
|
+
mdh[f'Processing.{self._short_name}.{p_name}'] = getattr(self, p)
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def _pipeline_view(self, show_label=True):
|
|
554
|
+
import wx
|
|
555
|
+
if wx.GetApp() is None:
|
|
556
|
+
return None
|
|
557
|
+
|
|
558
|
+
import traitsui.api as tui
|
|
559
|
+
modname = ','.join(self.inputs) + ' -> ' + self.__class__.__name__ + ' -> ' + ','.join(self.outputs)
|
|
560
|
+
|
|
561
|
+
if show_label:
|
|
562
|
+
return tui.View(tui.Group(self._view_items(),label=modname))
|
|
563
|
+
else:
|
|
564
|
+
return tui.View(self._view_items())
|
|
565
|
+
|
|
566
|
+
def _view_items(self, params=None):
|
|
567
|
+
"""
|
|
568
|
+
Used to customize module views, bye.g. specifying custom editors for a particular parameter, by grouping
|
|
569
|
+
parameters in a more functionally meaningful manner, or even by hiding certain parameters based on e.g. method
|
|
570
|
+
selection.
|
|
571
|
+
|
|
572
|
+
See `https://docs.enthought.com/traitsui/traitsui_user_manual/view.html`_ and the following 2 topics for details
|
|
573
|
+
on defining a view. Critically, this function should not return an entire view, but rather a list of items
|
|
574
|
+
(which could potentially be Groups). default_view, pipeline_view, and pipeline_view_min will then augment this
|
|
575
|
+
list as appropriate. The list should include items for all parameters of the module, but not for the input and
|
|
576
|
+
outputs as these will be added separately by default_view (and don't appear in the pipeline views).
|
|
577
|
+
|
|
578
|
+
Returns
|
|
579
|
+
-------
|
|
580
|
+
view_list: list
|
|
581
|
+
a list of traitsui.View Items
|
|
582
|
+
|
|
583
|
+
See Also
|
|
584
|
+
--------
|
|
585
|
+
|
|
586
|
+
default_view
|
|
587
|
+
pipeline_view
|
|
588
|
+
pipeline_view_min
|
|
589
|
+
|
|
590
|
+
"""
|
|
591
|
+
import traitsui.api as tui
|
|
592
|
+
if not params:
|
|
593
|
+
inputs, outputs, params = self.get_params()
|
|
594
|
+
|
|
595
|
+
return [tui.Item(tn) for tn in params]
|
|
596
|
+
|
|
597
|
+
@property
|
|
598
|
+
def pipeline_view(self):
|
|
599
|
+
"""
|
|
600
|
+
A condensed view of the module suitable for display in the 'pipeline' section of VisGUI (or anywhere where you
|
|
601
|
+
might want to edit all of the parameters of a recipe at once). It differs from the default_view in that it doesn't
|
|
602
|
+
display input and output variables - i.e. it lets you edit the recipe parameters but not connectivity.
|
|
603
|
+
|
|
604
|
+
The difference between pipeline_view and pipeline_view_min is that pipeline_view puts all the parameters in a
|
|
605
|
+
named group which encodes the module name and its connectivity, whereas pipeline_view_min omits this header.
|
|
606
|
+
|
|
607
|
+
To customise the view, you should over-ride `_view_items` instead of this function as this will customise both
|
|
608
|
+
pipeline views and the default view in one hit, reducing duplicate code.
|
|
609
|
+
|
|
610
|
+
Returns
|
|
611
|
+
-------
|
|
612
|
+
|
|
613
|
+
A traitsui `View` object - see `https://docs.enthought.com/traitsui/traitsui_user_manual/view.html`_
|
|
614
|
+
|
|
615
|
+
See Also
|
|
616
|
+
--------
|
|
617
|
+
|
|
618
|
+
_view_items
|
|
619
|
+
pipeline_view_min
|
|
620
|
+
default_view
|
|
621
|
+
|
|
622
|
+
"""
|
|
623
|
+
return self._pipeline_view()
|
|
624
|
+
|
|
625
|
+
@property
|
|
626
|
+
def pipeline_view_min(self):
|
|
627
|
+
""" See docs for pipeline_view - this is the same, but lacks the module header"""
|
|
628
|
+
return self._pipeline_view(False)
|
|
629
|
+
|
|
630
|
+
@property
|
|
631
|
+
def _namespace_keys(self):
|
|
632
|
+
try:
|
|
633
|
+
namespace_keys = {'input', } | set(self._parent.namespace.keys())
|
|
634
|
+
namespace_keys.update(self._parent.module_outputs)
|
|
635
|
+
return list(namespace_keys)
|
|
636
|
+
except:
|
|
637
|
+
return []
|
|
638
|
+
|
|
639
|
+
@property
|
|
640
|
+
def default_view(self):
|
|
641
|
+
""" The default traits view - displayed when clicking on a recipe module in the full recipe view to edit it
|
|
642
|
+
|
|
643
|
+
This can be over-ridden in a derived class to customise how the recipe module is edited and, e.g. specify custom
|
|
644
|
+
traits editors. NOTE: Editing this property will NOT change how the module is displayed in the compact recipe
|
|
645
|
+
overview displayed in VisGUI. **In most cases, it is preferable to over-ride the `_view_items()` method** which
|
|
646
|
+
just constructs the part of the view associated with the module parameters, leaving the base module to
|
|
647
|
+
auto-generate the input and output sections.
|
|
648
|
+
|
|
649
|
+
In general a view should have the inputs, a separator, the module parameters, another separator, and finally an OK button.
|
|
650
|
+
|
|
651
|
+
Returns
|
|
652
|
+
-------
|
|
653
|
+
view : traitsui.View
|
|
654
|
+
A traitsui `View` object, see `https://docs.enthought.com/traitsui/traitsui_user_manual/view.html`_
|
|
655
|
+
|
|
656
|
+
See Also
|
|
657
|
+
--------
|
|
658
|
+
|
|
659
|
+
pipeline_view
|
|
660
|
+
_view_items
|
|
661
|
+
|
|
662
|
+
"""
|
|
663
|
+
import wx
|
|
664
|
+
if wx.GetApp() is None:
|
|
665
|
+
return None
|
|
666
|
+
|
|
667
|
+
from traitsui.api import View, Item, Group
|
|
668
|
+
from PYME.ui.custom_traits_editors import CBEditor
|
|
669
|
+
|
|
670
|
+
inputs, outputs, params = self.get_params()
|
|
671
|
+
|
|
672
|
+
return View([Item(tn, editor=CBEditor(choices=self._namespace_keys)) for tn in inputs] +
|
|
673
|
+
[Item('_'),] +
|
|
674
|
+
self._view_items(params) +
|
|
675
|
+
[Item('_'),] +
|
|
676
|
+
[Item(tn) for tn in outputs], buttons=['OK']) #TODO - should we have cancel? Traits update whilst being edited and cancel doesn't roll back
|
|
677
|
+
|
|
678
|
+
def default_traits_view( self ):
|
|
679
|
+
""" This is the traits stock method to specify the default view"""
|
|
680
|
+
return self.default_view
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
class OutputModule(ModuleBase):
|
|
684
|
+
"""
|
|
685
|
+
Output modules are the one exception to the recipe-module functional (no side effects) programming
|
|
686
|
+
paradigm and are used to perform IO and save or display designated outputs/endpoints from the recipe.
|
|
687
|
+
|
|
688
|
+
As such, they should act solely as a sink, and should not do any processing or write anything back
|
|
689
|
+
to the namespace.
|
|
690
|
+
"""
|
|
691
|
+
filePattern = CStr('{output_dir}/{file_stub}.csv')
|
|
692
|
+
scheme = Enum('File', 'pyme-cluster://', 'pyme-cluster:// - aggregate')
|
|
693
|
+
|
|
694
|
+
def _schemafy_filename(self, out_filename):
|
|
695
|
+
if self.scheme == 'File':
|
|
696
|
+
return out_filename
|
|
697
|
+
elif self.scheme == 'pyme-cluster://':
|
|
698
|
+
from PYME.IO import clusterIO
|
|
699
|
+
import os
|
|
700
|
+
return os.path.join(clusterIO.local_dataroot, out_filename.lstrip('/'))
|
|
701
|
+
elif self.scheme == 'pyme-cluster:// - aggregate':
|
|
702
|
+
raise RuntimeError('Aggregation not suported')
|
|
703
|
+
|
|
704
|
+
def _check_outputs(self):
|
|
705
|
+
"""
|
|
706
|
+
This function exists to help with debugging when writing a new recipe module.
|
|
707
|
+
|
|
708
|
+
Over-ridden here for the special case IO modules derived from OutputModule as these are permitted to
|
|
709
|
+
have side-effects, but not permitted to have classical outputs to the namespace and will execute
|
|
710
|
+
(when appropriate) regardless.
|
|
711
|
+
"""
|
|
712
|
+
if len(self.outputs) != 0:
|
|
713
|
+
raise RuntimeError('Output modules should not write anything to the namespace')
|
|
714
|
+
|
|
715
|
+
def generate(self, namespace, recipe_context={}):
|
|
716
|
+
"""
|
|
717
|
+
Function to be called from within dh5view (rather than batch processing). Some outputs are ignored, in which
|
|
718
|
+
case this function returns None.
|
|
719
|
+
|
|
720
|
+
Parameters
|
|
721
|
+
----------
|
|
722
|
+
namespace : dict
|
|
723
|
+
The recipe namespace
|
|
724
|
+
recipe_context : dict
|
|
725
|
+
Information about the source file(s) to allow pattern substitution and generate the output name.
|
|
726
|
+
At least 'basedir' (which is the fully resolved directory name in which the input file resides)
|
|
727
|
+
and 'filestub' (which is the filename without any extension) should be resolved.
|
|
728
|
+
|
|
729
|
+
Returns
|
|
730
|
+
-------
|
|
731
|
+
|
|
732
|
+
"""
|
|
733
|
+
return None
|
|
734
|
+
|
|
735
|
+
def execute(self, namespace):
|
|
736
|
+
"""
|
|
737
|
+
Output modules by definition do nothing when executed - they act as a sink and implement a save method instead.
|
|
738
|
+
|
|
739
|
+
Parameters
|
|
740
|
+
----------
|
|
741
|
+
namespace : dict
|
|
742
|
+
The recipe namespace
|
|
743
|
+
|
|
744
|
+
Returns
|
|
745
|
+
-------
|
|
746
|
+
None
|
|
747
|
+
|
|
748
|
+
"""
|
|
749
|
+
pass
|
|
750
|
+
|
|
751
|
+
def save(self, namespace, context={}):
|
|
752
|
+
"""
|
|
753
|
+
|
|
754
|
+
Parameters
|
|
755
|
+
----------
|
|
756
|
+
namespace : dict
|
|
757
|
+
The recipe namespace
|
|
758
|
+
context : dict
|
|
759
|
+
Information about the source file to allow pattern substitution to
|
|
760
|
+
generate the output name. At least 'basedir' (which is the fully-
|
|
761
|
+
resolved directory name in which the input file resides) and
|
|
762
|
+
'file_stub' (which is the filename without any extension) should be
|
|
763
|
+
resolved.
|
|
764
|
+
|
|
765
|
+
Returns
|
|
766
|
+
-------
|
|
767
|
+
|
|
768
|
+
"""
|
|
769
|
+
raise NotImplementedError
|
|
770
|
+
|
|
771
|
+
def ModuleCollection(*args, **kwargs):
|
|
772
|
+
""" Backwards compatible factory stub for Recipe class"""
|
|
773
|
+
from .recipe import Recipe
|
|
774
|
+
import warnings
|
|
775
|
+
|
|
776
|
+
warnings.warn(DeprecationWarning('recipes.base.ModuleCollection is deprecated, use recipes.recipe.Recipe instead'))
|
|
777
|
+
return Recipe(*args, **kwargs)
|
|
778
|
+
|
|
779
|
+
class ImageModuleBase(ModuleBase):
|
|
780
|
+
# NOTE - if a derived class only supports, e.g. XY analysis, it should redefine this trait ro only include the dimensions
|
|
781
|
+
# it supports
|
|
782
|
+
dimensionality = Enum('XY', 'XYZ', 'XYZT', desc='Which image dimensions should the filter be applied to?')
|
|
783
|
+
|
|
784
|
+
#processFramesIndividually = Bool(True)
|
|
785
|
+
|
|
786
|
+
@property
|
|
787
|
+
def processFramesIndividually(self):
|
|
788
|
+
import warnings
|
|
789
|
+
warnings.warn(
|
|
790
|
+
'Use dimensionality =="XY" instead to check which dimensions a filter should be applied to, chunking '
|
|
791
|
+
'hints for computational optimisation', DeprecationWarning, stacklevel=2)
|
|
792
|
+
|
|
793
|
+
logger.warning(
|
|
794
|
+
'Use dimensionality =="XY" instead to check which dimensions a filter should be applied to, chunking '
|
|
795
|
+
'hints for computational optimisation')
|
|
796
|
+
return self.dimensionality == 'XY'
|
|
797
|
+
|
|
798
|
+
@processFramesIndividually.setter
|
|
799
|
+
def processFramesIndividually(self, value):
|
|
800
|
+
import warnings
|
|
801
|
+
warnings.warn(
|
|
802
|
+
'Use dimensionality ="XY" instead to check which dimensions a filter should be applied to, chunking '
|
|
803
|
+
'hints for computational optimisation', DeprecationWarning, stacklevel=2)
|
|
804
|
+
|
|
805
|
+
logger.warning(
|
|
806
|
+
'Use dimensionality ="XY" instead to check which dimensions a filter should be applied to, chunking '
|
|
807
|
+
'hints for computational optimisation')
|
|
808
|
+
|
|
809
|
+
if value:
|
|
810
|
+
self.dimensionality = 'XY'
|
|
811
|
+
else:
|
|
812
|
+
self.dimensionality = 'XYZ'
|
|
813
|
+
|
|
814
|
+
class Filter(ImageModuleBase):
|
|
815
|
+
"""Module with one image input and one image output"""
|
|
816
|
+
inputName = Input('input')
|
|
817
|
+
outputName = Output('filtered_image')
|
|
818
|
+
|
|
819
|
+
# flag which can be set to false in derived classes (e.g. Projection, Zoom)
|
|
820
|
+
# which (in their current forms) will behave badly if run blocked
|
|
821
|
+
_block_safe = True
|
|
822
|
+
|
|
823
|
+
def _block_overlap(self):
|
|
824
|
+
# override in derrived classes to specify desired overlap between blocks
|
|
825
|
+
# this should generally be a few times the kernel width for filtering ops.
|
|
826
|
+
return None
|
|
827
|
+
|
|
828
|
+
def output_shapes(self, input_shapes):
|
|
829
|
+
"""What shape is the output (without running any computation)
|
|
830
|
+
|
|
831
|
+
Filters which modify image size (e.g. zoom) should over-write this. Will be used in the future for smart chunking.
|
|
832
|
+
"""
|
|
833
|
+
return {self.outputName : input_shapes[self.inputName]}
|
|
834
|
+
|
|
835
|
+
def filter(self, image):
|
|
836
|
+
from PYME.IO.dataWrap import ListWrapper
|
|
837
|
+
out = []
|
|
838
|
+
for c in range(image.data_xyztc.shape[4]):
|
|
839
|
+
if self.dimensionality == 'XYZT':
|
|
840
|
+
data = image.data_xyztc[:, :, :, :,c].squeeze().astype('f')
|
|
841
|
+
xyzt = np.atleast_3d(self._apply_filter(data, image, c=c))
|
|
842
|
+
else: # XYZ or XY
|
|
843
|
+
xyzt = []
|
|
844
|
+
for t in range(image.data_xyztc.shape[3]):
|
|
845
|
+
if self.dimensionality == 'XYZ':
|
|
846
|
+
data = image.data_xyztc[:, :, :, t, c].squeeze().astype('f')
|
|
847
|
+
xyz = np.atleast_3d(self._apply_filter(data, image, c=c, t=t))
|
|
848
|
+
else: #XY
|
|
849
|
+
xyz = []
|
|
850
|
+
for z in range(image.data_xyztc.shape[2]):
|
|
851
|
+
data = image.data_xyztc[:, :, z, t, c].squeeze().astype('f')
|
|
852
|
+
|
|
853
|
+
xyz.append(np.atleast_2d(self._apply_filter(data, image, c=c, t=t, z=z).squeeze()))
|
|
854
|
+
|
|
855
|
+
xyzt.append(xyz)
|
|
856
|
+
out.append(xyzt)
|
|
857
|
+
|
|
858
|
+
im = ImageStack(ListWrapper(out, strict_dims=True), titleStub = self.outputName)
|
|
859
|
+
im.mdh.copyEntriesFrom(image.mdh)
|
|
860
|
+
im.mdh['Parent'] = image.filename
|
|
861
|
+
|
|
862
|
+
self.completeMetadata(im)
|
|
863
|
+
|
|
864
|
+
return im
|
|
865
|
+
|
|
866
|
+
def _chunk_dims(self, chunksize):
|
|
867
|
+
chunksize = np.array(chunksize)
|
|
868
|
+
logger.debug('chunksize: %s' % chunksize)
|
|
869
|
+
|
|
870
|
+
# flatten last dimensions
|
|
871
|
+
if (self.dimensionality == 'XY'):
|
|
872
|
+
chunksize[2:] = 1
|
|
873
|
+
elif (self.dimensionality == 'XYZ'):
|
|
874
|
+
if (chunksize[2] == 1):
|
|
875
|
+
logger.warning('XYZ dimensionality chosen, but z chunk size is 1')
|
|
876
|
+
chunksize[3:] = 1
|
|
877
|
+
elif (self.dimensionality == 'XYZT'):
|
|
878
|
+
if (chunksize[2] == 1):
|
|
879
|
+
logger.warning('XYZT dimensionality chosen, but z chunk size is 1')
|
|
880
|
+
if (chunksize[2] == 1):
|
|
881
|
+
logger.warning('XYZT dimensionality chosen, but t chunk size is 1')
|
|
882
|
+
|
|
883
|
+
return tuple(chunksize)
|
|
884
|
+
|
|
885
|
+
def dfilter(self, image, chunksize=None):
|
|
886
|
+
from PYME.IO.DataSources import ArrayDataSource
|
|
887
|
+
|
|
888
|
+
if not chunksize:
|
|
889
|
+
# chunksize not specified, infer
|
|
890
|
+
# Use input chunck size (if chunked), otherwise a single, large chunk
|
|
891
|
+
chunksize = getattr(image.data_xyztc, 'chunksize', tuple(image.data_xyztc.shape))
|
|
892
|
+
|
|
893
|
+
chunksize = self._chunk_dims(chunksize)
|
|
894
|
+
|
|
895
|
+
c_image = da.from_array(image.data_xyztc, chunks = chunksize)
|
|
896
|
+
#NB - map_overlap reduces to map_chunks if depth is None (or 0) - the default case
|
|
897
|
+
out = c_image.map_overlap(self.__apply_filter, depth=self._block_overlap(), voxelsize=image.voxelsize, dtype='f')
|
|
898
|
+
|
|
899
|
+
im = ImageStack(ArrayDataSource.XYZTCArrayDataSource(out), titleStub = self.outputName)
|
|
900
|
+
im.mdh.copyEntriesFrom(image.mdh)
|
|
901
|
+
im.mdh['Parent'] = image.filename
|
|
902
|
+
|
|
903
|
+
self.completeMetadata(im)
|
|
904
|
+
|
|
905
|
+
return im
|
|
906
|
+
|
|
907
|
+
def __apply_filter(self, data, voxelsize):
|
|
908
|
+
d2 = np.array(data, copy=False).squeeze().astype('f')
|
|
909
|
+
return np.array(self.apply_filter(d2,voxelsize), copy=False, ndmin=5)
|
|
910
|
+
|
|
911
|
+
def _apply_filter(self, data, image, z=None, t=None, c=None):
|
|
912
|
+
if hasattr(self, 'applyFilter'):
|
|
913
|
+
import warnings
|
|
914
|
+
warnings.warn('applyFilter() is deprecated, derived classes should implement `apply_filter()` instead')
|
|
915
|
+
return self.applyFilter(data, c, z, image)
|
|
916
|
+
else:
|
|
917
|
+
return self.apply_filter(data, voxelsize=image.voxelsize)
|
|
918
|
+
|
|
919
|
+
def apply_filter(self, data, voxelsize):
|
|
920
|
+
raise NotImplementedError('Should be over-ridden in derived class')
|
|
921
|
+
|
|
922
|
+
# def execute(self, namespace):
|
|
923
|
+
# namespace[self.outputName] = self.filter(namespace[self.inputName])
|
|
924
|
+
|
|
925
|
+
def run(self, inputName):
|
|
926
|
+
if da and config.get('recipes-use_dask', False):
|
|
927
|
+
return self.dfilter(inputName)
|
|
928
|
+
else:
|
|
929
|
+
return self.filter(inputName)
|
|
930
|
+
|
|
931
|
+
def completeMetadata(self, im):
|
|
932
|
+
pass
|
|
933
|
+
|
|
934
|
+
@classmethod
|
|
935
|
+
def dsviewer_plugin_callback(cls, dsviewer, showGUI=True, **kwargs):
|
|
936
|
+
"""Implements a callback which allows this module to be used as a plugin for dsviewer.
|
|
937
|
+
|
|
938
|
+
Parameters
|
|
939
|
+
----------
|
|
940
|
+
|
|
941
|
+
dsviewer : :class:`PYME.DSView.dsviewer.DSViewFrame` instance
|
|
942
|
+
This is the current :class:`~PYME.DSView.dsviewer.DSViewFrame` instance. The filter will be run with the
|
|
943
|
+
associated ``.image`` as input and display the output in a new window.
|
|
944
|
+
|
|
945
|
+
showGUI : bool
|
|
946
|
+
Should we show a GUI to set parameters (generated by calling configure_traits()), or just run with default
|
|
947
|
+
parameters.
|
|
948
|
+
|
|
949
|
+
**kwargs : dict
|
|
950
|
+
Optionally, provide default values for parameters. Makes most sense when used with showGUI = False
|
|
951
|
+
|
|
952
|
+
"""
|
|
953
|
+
from PYME.DSView import ViewIm3D
|
|
954
|
+
|
|
955
|
+
mod = cls(inputName='input', outputName='output', **kwargs)
|
|
956
|
+
if (not showGUI) or mod.configure_traits(kind='modal'):
|
|
957
|
+
namespace = {'input' : dsviewer.image}
|
|
958
|
+
mod.execute(namespace)
|
|
959
|
+
|
|
960
|
+
ViewIm3D(mod['output'], parent=dsviewer, glCanvas=dsviewer.glCanvas)
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
class ArithmaticFilter(ModuleBase):
|
|
964
|
+
"""
|
|
965
|
+
Module with two image inputs and one image output
|
|
966
|
+
|
|
967
|
+
Parameters
|
|
968
|
+
----------
|
|
969
|
+
inputName0: PYME.IO.image.ImageStack
|
|
970
|
+
inputName1: PYME.IO.image.ImageStack
|
|
971
|
+
outputName: PYME.IO.image.ImageStack
|
|
972
|
+
|
|
973
|
+
"""
|
|
974
|
+
inputName0 = Input('input')
|
|
975
|
+
inputName1 = Input('input')
|
|
976
|
+
outputName = Output('filtered_image')
|
|
977
|
+
|
|
978
|
+
processFramesIndividually = Bool(False)
|
|
979
|
+
|
|
980
|
+
def filter(self, image0, image1):
|
|
981
|
+
if self.processFramesIndividually:
|
|
982
|
+
filt_ims = []
|
|
983
|
+
for chanNum in range(image0.data.shape[3]):
|
|
984
|
+
out = []
|
|
985
|
+
for i in range(image0.data.shape[2]):
|
|
986
|
+
d0 = image0.data[:,:,i,chanNum].squeeze().astype('f')
|
|
987
|
+
d1 = image1.data[:,:,i,chanNum].squeeze().astype('f')
|
|
988
|
+
out.append(np.atleast_3d(self.applyFilter(d0, d1, chanNum, i, image0)))
|
|
989
|
+
filt_ims.append(np.concatenate(out, 2))
|
|
990
|
+
else:
|
|
991
|
+
filt_ims = []
|
|
992
|
+
for chanNum in range(image0.data.shape[3]):
|
|
993
|
+
d0 = image0.data[:,:,:,chanNum].squeeze().astype('f')
|
|
994
|
+
d1 = image1.data[:,:,:,chanNum].squeeze().astype('f')
|
|
995
|
+
filt_ims.append(np.atleast_3d(self.applyFilter(d0, d1, chanNum, 0, image0)))
|
|
996
|
+
|
|
997
|
+
im = ImageStack(filt_ims, titleStub = self.outputName)
|
|
998
|
+
im.mdh.copyEntriesFrom(image0.mdh)
|
|
999
|
+
im.mdh['Parents'] = '%s, %s' % (image0.filename, image1.filename)
|
|
1000
|
+
|
|
1001
|
+
self.completeMetadata(im)
|
|
1002
|
+
|
|
1003
|
+
return im
|
|
1004
|
+
|
|
1005
|
+
#def execute(self, namespace):
|
|
1006
|
+
# namespace[self.outputName] = self.filter(namespace[self.inputName0], namespace[self.inputName1])
|
|
1007
|
+
|
|
1008
|
+
def run(self, inputName0, inputName1):
|
|
1009
|
+
return self.filter(inputName0, inputName1)
|
|
1010
|
+
|
|
1011
|
+
def completeMetadata(self, im):
|
|
1012
|
+
pass
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
@register_module('ExtractChannel')
|
|
1016
|
+
class ExtractChannel(ModuleBase):
|
|
1017
|
+
"""Extract one channel from an image"""
|
|
1018
|
+
inputName = Input('input')
|
|
1019
|
+
outputName = Output('filtered_image')
|
|
1020
|
+
|
|
1021
|
+
channelToExtract = Int(0)
|
|
1022
|
+
|
|
1023
|
+
def _pickChannel(self, image):
|
|
1024
|
+
chan = image.data[:,:,:,self.channelToExtract]
|
|
1025
|
+
|
|
1026
|
+
im = ImageStack(chan, titleStub = 'Filtered Image')
|
|
1027
|
+
im.mdh.copyEntriesFrom(image.mdh)
|
|
1028
|
+
try:
|
|
1029
|
+
im.mdh['ChannelNames'] = [image.names[self.channelToExtract],]
|
|
1030
|
+
except (KeyError, AttributeError):
|
|
1031
|
+
logger.warn("Error setting channel name")
|
|
1032
|
+
|
|
1033
|
+
im.mdh['Parent'] = image.filename
|
|
1034
|
+
|
|
1035
|
+
return im
|
|
1036
|
+
|
|
1037
|
+
#def execute(self, namespace):
|
|
1038
|
+
# namespace[self.outputName] = self._pickChannel(namespace[self.inputName])
|
|
1039
|
+
|
|
1040
|
+
def run(self, inputName):
|
|
1041
|
+
return self._pickChannel(inputName)
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
@register_module('JoinChannels')
|
|
1045
|
+
class JoinChannels(ModuleBase):
|
|
1046
|
+
"""Join multiple channels to form a composite image"""
|
|
1047
|
+
inputChan0 = Input('input0')
|
|
1048
|
+
inputChan1 = Input('')
|
|
1049
|
+
inputChan2 = Input('')
|
|
1050
|
+
inputChan3 = Input('')
|
|
1051
|
+
outputName = Output('output')
|
|
1052
|
+
|
|
1053
|
+
#channelToExtract = Int(0)
|
|
1054
|
+
|
|
1055
|
+
# def _joinChannels(self, namespace):
|
|
1056
|
+
# chans = []
|
|
1057
|
+
|
|
1058
|
+
# image = namespace[self.inputChan0]
|
|
1059
|
+
|
|
1060
|
+
# chans.append(np.atleast_3d(image.data[:,:,:,0]))
|
|
1061
|
+
|
|
1062
|
+
# channel_names = [self.inputChan0,]
|
|
1063
|
+
|
|
1064
|
+
# if not self.inputChan1 == '':
|
|
1065
|
+
# chans.append(namespace[self.inputChan1].data[:,:,:,0])
|
|
1066
|
+
# channel_names.append(self.inputChan1)
|
|
1067
|
+
# if not self.inputChan2 == '':
|
|
1068
|
+
# chans.append(namespace[self.inputChan2].data[:,:,:,0])
|
|
1069
|
+
# channel_names.append(self.inputChan2)
|
|
1070
|
+
# if not self.inputChan3 == '':
|
|
1071
|
+
# chans.append(namespace[self.inputChan3].data[:,:,:,0])
|
|
1072
|
+
# channel_names.append(self.inputChan3)
|
|
1073
|
+
|
|
1074
|
+
# im = ImageStack(chans, titleStub = 'Composite Image')
|
|
1075
|
+
# im.mdh.copyEntriesFrom(image.mdh)
|
|
1076
|
+
# im.names = channel_names
|
|
1077
|
+
# im.mdh['Parent'] = image.filename
|
|
1078
|
+
|
|
1079
|
+
# return im
|
|
1080
|
+
|
|
1081
|
+
# def execute(self, namespace):
|
|
1082
|
+
# #TODO - make convert to .run() (and find a way of handling variable inputs)
|
|
1083
|
+
# namespace[self.outputName] = self._joinChannels(namespace)
|
|
1084
|
+
|
|
1085
|
+
def run(self, inputChan0, inputChan1, inputChan2=None, inputChan3=None):
|
|
1086
|
+
chans = []
|
|
1087
|
+
channel_names = []
|
|
1088
|
+
|
|
1089
|
+
for i, c in enumerate([inputChan0, inputChan1, inputChan2, inputChan3]):
|
|
1090
|
+
if c:
|
|
1091
|
+
chans.append(np.atleast_3d(c.data_xyztc[:,:,:,:,0])) #FIXME .... so as not to drag everything into memory if not needed
|
|
1092
|
+
channel_names.append(getattr(self, 'inputChan%d' %i))
|
|
1093
|
+
|
|
1094
|
+
im = ImageStack(chans, titleStub = 'Composite Image')
|
|
1095
|
+
im.mdh.copyEntriesFrom(inputChan0.mdh)
|
|
1096
|
+
im.names = channel_names
|
|
1097
|
+
im.mdh['Parent'] = inputChan0.filename
|
|
1098
|
+
|
|
1099
|
+
return im
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
@register_module('Add')
|
|
1105
|
+
class Add(ArithmaticFilter):
|
|
1106
|
+
"""
|
|
1107
|
+
Add two images
|
|
1108
|
+
|
|
1109
|
+
Parameters
|
|
1110
|
+
----------
|
|
1111
|
+
inputName0: PYME.IO.image.ImageStack
|
|
1112
|
+
inputName1: PYME.IO.image.ImageStack
|
|
1113
|
+
outputName: PYME.IO.image.ImageStack
|
|
1114
|
+
|
|
1115
|
+
"""
|
|
1116
|
+
|
|
1117
|
+
def applyFilter(self, data0, data1, chanNum, i, image0):
|
|
1118
|
+
return data0 + data1
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
@register_module('Subtract')
|
|
1122
|
+
class Subtract(ArithmaticFilter):
|
|
1123
|
+
"""
|
|
1124
|
+
Subtract two images. inputName1 is subtracted from inputName0.
|
|
1125
|
+
|
|
1126
|
+
Parameters
|
|
1127
|
+
----------
|
|
1128
|
+
inputName0: PYME.IO.image.ImageStack
|
|
1129
|
+
image to be subtracted from
|
|
1130
|
+
inputName1: PYME.IO.image.ImageStack
|
|
1131
|
+
image being subtracted
|
|
1132
|
+
outputName: PYME.IO.image.ImageStack
|
|
1133
|
+
difference image
|
|
1134
|
+
|
|
1135
|
+
"""
|
|
1136
|
+
|
|
1137
|
+
def applyFilter(self, data0, data1, chanNum, i, image0):
|
|
1138
|
+
return data0 - data1
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
@register_module('Multiply')
|
|
1142
|
+
class Multiply(ArithmaticFilter):
|
|
1143
|
+
"""
|
|
1144
|
+
Multiply two images
|
|
1145
|
+
|
|
1146
|
+
Parameters
|
|
1147
|
+
----------
|
|
1148
|
+
inputName0: PYME.IO.image.ImageStack
|
|
1149
|
+
inputName1: PYME.IO.image.ImageStack
|
|
1150
|
+
outputName: PYME.IO.image.ImageStack
|
|
1151
|
+
|
|
1152
|
+
"""
|
|
1153
|
+
|
|
1154
|
+
def applyFilter(self, data0, data1, chanNum, i, image0):
|
|
1155
|
+
return data0 * data1
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
@register_module('Divide')
|
|
1159
|
+
class Divide(ArithmaticFilter):
|
|
1160
|
+
"""
|
|
1161
|
+
Divide two images. inputName0 is divided by inputName1.
|
|
1162
|
+
|
|
1163
|
+
Parameters
|
|
1164
|
+
----------
|
|
1165
|
+
inputName0: PYME.IO.image.ImageStack
|
|
1166
|
+
numerator
|
|
1167
|
+
inputName1: PYME.IO.image.ImageStack
|
|
1168
|
+
denominator
|
|
1169
|
+
outputName: PYME.IO.image.ImageStack
|
|
1170
|
+
|
|
1171
|
+
"""
|
|
1172
|
+
|
|
1173
|
+
def applyFilter(self, data0, data1, chanNum, i, image0):
|
|
1174
|
+
return data0 / data1
|
|
1175
|
+
|
|
1176
|
+
|
|
1177
|
+
@register_module('Pow')
|
|
1178
|
+
class Pow(Filter):
|
|
1179
|
+
"Raise an image to a given power (can be fractional for sqrt)"
|
|
1180
|
+
power = Float(2)
|
|
1181
|
+
|
|
1182
|
+
def applyFilter(self, data, chanNum, i, image0):
|
|
1183
|
+
return np.power(data, self.power)
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
@register_module('Scale')
|
|
1187
|
+
class Scale(Filter):
|
|
1188
|
+
"""Scale an image intensities by a constant"""
|
|
1189
|
+
|
|
1190
|
+
scale = Float(1)
|
|
1191
|
+
|
|
1192
|
+
def applyFilter(self, data, chanNum, i, image0):
|
|
1193
|
+
return self.scale * data
|
|
1194
|
+
|
|
1195
|
+
@register_module('Offset')
|
|
1196
|
+
class Offset(Filter):
|
|
1197
|
+
"""Offset an image intensities by a constant"""
|
|
1198
|
+
|
|
1199
|
+
offset = Float(0)
|
|
1200
|
+
|
|
1201
|
+
def applyFilter(self, data, chanNum, i, image0):
|
|
1202
|
+
return data + self.offset
|
|
1203
|
+
|
|
1204
|
+
@register_module('Clip')
|
|
1205
|
+
class Clip(Filter):
|
|
1206
|
+
"""Clip an image to a given range"""
|
|
1207
|
+
|
|
1208
|
+
min = Float(0)
|
|
1209
|
+
max = Float(np.finfo(np.float32).max)
|
|
1210
|
+
|
|
1211
|
+
def applyFilter(self, data, chanNum, i, image0):
|
|
1212
|
+
return np.clip(data, self.min, self.max)
|
|
1213
|
+
|
|
1214
|
+
|
|
1215
|
+
@register_module('Normalize')
|
|
1216
|
+
class Normalize(Filter):
|
|
1217
|
+
"""Normalize an image so that the maximum is 1"""
|
|
1218
|
+
|
|
1219
|
+
#scale = Float(1)
|
|
1220
|
+
|
|
1221
|
+
def applyFilter(self, data, chanNum, i, image0):
|
|
1222
|
+
return data / float(data.max())
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
@register_module('NormalizeMean')
|
|
1226
|
+
class NormalizeMean(Filter):
|
|
1227
|
+
"""Normalize an image so that the mean is 1"""
|
|
1228
|
+
|
|
1229
|
+
offset = Float(0)
|
|
1230
|
+
|
|
1231
|
+
def applyFilter(self, data, chanNum, i, image0):
|
|
1232
|
+
data = data - self.offset
|
|
1233
|
+
return data / float(data.mean())
|
|
1234
|
+
|
|
1235
|
+
|
|
1236
|
+
@register_module('Invert')
|
|
1237
|
+
class Invert(Filter):
|
|
1238
|
+
"""Invert image
|
|
1239
|
+
|
|
1240
|
+
This is implemented as :math:`B = (1-A)`. As such the results only really make sense for binary images / masks and
|
|
1241
|
+
for images which have been normalized such that the maximum value is 1.
|
|
1242
|
+
"""
|
|
1243
|
+
|
|
1244
|
+
#scale = Float(1)
|
|
1245
|
+
|
|
1246
|
+
def applyFilter(self, data, chanNum, i, image0):
|
|
1247
|
+
return 1 - data
|
|
1248
|
+
|
|
1249
|
+
|
|
1250
|
+
@register_module('BinaryOr')
|
|
1251
|
+
class BinaryOr(ArithmaticFilter):
|
|
1252
|
+
"""
|
|
1253
|
+
Perform a bitwise OR on images
|
|
1254
|
+
|
|
1255
|
+
Parameters
|
|
1256
|
+
----------
|
|
1257
|
+
inputName0: PYME.IO.image.ImageStack
|
|
1258
|
+
inputName1: PYME.IO.image.ImageStack
|
|
1259
|
+
outputName: PYME.IO.image.ImageStack
|
|
1260
|
+
|
|
1261
|
+
Notes
|
|
1262
|
+
-----
|
|
1263
|
+
|
|
1264
|
+
This is actually implemented as :math:`(A + B) > .5`
|
|
1265
|
+
"""
|
|
1266
|
+
|
|
1267
|
+
def applyFilter(self, data0, data1, chanNum, i, image0):
|
|
1268
|
+
return (data0 + data1) > .5
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
@register_module('LogicalAnd')
|
|
1272
|
+
class LogicalAnd(ArithmaticFilter):
|
|
1273
|
+
"""
|
|
1274
|
+
Perform a logical AND on images
|
|
1275
|
+
|
|
1276
|
+
Parameters
|
|
1277
|
+
----------
|
|
1278
|
+
inputName0: PYME.IO.image.ImageStack
|
|
1279
|
+
inputName1: PYME.IO.image.ImageStack
|
|
1280
|
+
outputName: PYME.IO.image.ImageStack
|
|
1281
|
+
"""
|
|
1282
|
+
|
|
1283
|
+
def applyFilter(self, data0, data1, chanNum, i, image0):
|
|
1284
|
+
return np.logical_and(data0, data1)
|
|
1285
|
+
|
|
1286
|
+
|
|
1287
|
+
@register_module('IsClose')
|
|
1288
|
+
class IsClose(ArithmaticFilter):
|
|
1289
|
+
"""
|
|
1290
|
+
Wrapper for numpy.isclose
|
|
1291
|
+
|
|
1292
|
+
Parameters
|
|
1293
|
+
----------
|
|
1294
|
+
abs_tolerance: Float
|
|
1295
|
+
absolute tolerance
|
|
1296
|
+
rel_tolerance: Float
|
|
1297
|
+
relative tolerance
|
|
1298
|
+
|
|
1299
|
+
Notes
|
|
1300
|
+
-----
|
|
1301
|
+
from numpy docs, tolerances are combined as: absolute(a - b) <= (atol + rtol * absolute(b))
|
|
1302
|
+
|
|
1303
|
+
"""
|
|
1304
|
+
abs_tolerance = Float(1e-8)
|
|
1305
|
+
rel_tolerance = Float(1e-5)
|
|
1306
|
+
def applyFilter(self, data0, data1, chanNum, i, image0):
|
|
1307
|
+
return np.isclose(data0, data1, atol=self.abs_tolerance, rtol=self.rel_tolerance)
|
|
1308
|
+
|
|
1309
|
+
def _issubclass(cl, c):
|
|
1310
|
+
try:
|
|
1311
|
+
return issubclass(cl, c)
|
|
1312
|
+
except TypeError:
|
|
1313
|
+
return False
|
|
1314
|
+
|
|
1315
|
+
@register_module('Crop')
|
|
1316
|
+
class Crop(ModuleBase):
|
|
1317
|
+
# adapted from PR #831
|
|
1318
|
+
input = Input('input')
|
|
1319
|
+
x_range = List(Int)([0, -1])
|
|
1320
|
+
y_range = List(Int)([0, -1])
|
|
1321
|
+
z_range = List(Int)([0, -1])
|
|
1322
|
+
t_range = List(Int)([0, -1])
|
|
1323
|
+
output = Output('cropped')
|
|
1324
|
+
|
|
1325
|
+
# def execute(self, namespace):
|
|
1326
|
+
# from PYME.IO.DataSources.CropDataSource import crop_image
|
|
1327
|
+
|
|
1328
|
+
# im = namespace[self.input]
|
|
1329
|
+
# cropped = crop_image(im, xrange=slice(*self.x_range), yrange=slice(*self.y_range), zrange=slice(*self.z_range), trange=slice(*self.t_range))
|
|
1330
|
+
# namespace[self.output] = cropped
|
|
1331
|
+
|
|
1332
|
+
def run(self, input):
|
|
1333
|
+
from PYME.IO.DataSources.CropDataSource import crop_image
|
|
1334
|
+
return crop_image(input, xrange=slice(*self.x_range), yrange=slice(*self.y_range), zrange=slice(*self.z_range), trange=slice(*self.t_range))
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
@register_module('Redimension')
|
|
1338
|
+
class Redimension(ModuleBase):
|
|
1339
|
+
"""
|
|
1340
|
+
Interprete input image as one having a different dimension order / slicing
|
|
1341
|
+
|
|
1342
|
+
Used for, e.g. recovering colour dimensions in data saved without metadata correctly indicating dimensionality
|
|
1343
|
+
|
|
1344
|
+
Treats the input data as a flat series of XY slices (using default ordering of the input data) and then interprets into 5D using
|
|
1345
|
+
the given dimention ordering.
|
|
1346
|
+
|
|
1347
|
+
Parameters
|
|
1348
|
+
----------
|
|
1349
|
+
|
|
1350
|
+
dim_order : enum, the order of dimensions in the image sequence
|
|
1351
|
+
size_z : int, number of z slices
|
|
1352
|
+
size_t : int, number of t slices
|
|
1353
|
+
size_c : int, number of c slices
|
|
1354
|
+
|
|
1355
|
+
Notes
|
|
1356
|
+
-----
|
|
1357
|
+
|
|
1358
|
+
The size_ parameters accept two special values:
|
|
1359
|
+
|
|
1360
|
+
0 : this dimension should be the same size as it is in the input
|
|
1361
|
+
-1 : set this dimension automatically based on the total number of slices / the product of the other two dimentsions. Only one of the dimensions can have a size
|
|
1362
|
+
of -1
|
|
1363
|
+
"""
|
|
1364
|
+
input = Input('imput')
|
|
1365
|
+
output = Output('redimensioned')
|
|
1366
|
+
|
|
1367
|
+
dim_order = Enum('XYZTC', values=['XYZTC', 'XYTZC', 'XYCZT', 'XYCTZ', 'XYZCT', 'XYTCZ'])
|
|
1368
|
+
size_z = Int(-1)
|
|
1369
|
+
size_t = Int(1)
|
|
1370
|
+
size_c = Int(1)
|
|
1371
|
+
|
|
1372
|
+
# def execute(self, namespace):
|
|
1373
|
+
# from PYME.IO.image import ImageStack
|
|
1374
|
+
# from PYME.IO.DataSources.BaseDataSource import XYZTCWrapper
|
|
1375
|
+
|
|
1376
|
+
# im = namespace[self.input]
|
|
1377
|
+
|
|
1378
|
+
# d = XYZTCWrapper(im.data_xyztc)
|
|
1379
|
+
# d.set_dim_order_and_size(self.dim_order, size_z=self.size_z,size_t=self.size_t, size_c=self.size_c)
|
|
1380
|
+
# im = ImageStack(data=d, titleStub='Redimensioned')
|
|
1381
|
+
|
|
1382
|
+
# im.mdh.copyEntriesFrom(getattr(im, 'mdh', {}))
|
|
1383
|
+
|
|
1384
|
+
# namespace[self.output] = d
|
|
1385
|
+
|
|
1386
|
+
def run(self, input):
|
|
1387
|
+
from PYME.IO.image import ImageStack
|
|
1388
|
+
from PYME.IO.DataSources.BaseDataSource import XYZTCWrapper
|
|
1389
|
+
|
|
1390
|
+
d = XYZTCWrapper(input.data_xyztc)
|
|
1391
|
+
d.set_dim_order_and_size(self.dim_order, size_z=self.size_z,size_t=self.size_t, size_c=self.size_c)
|
|
1392
|
+
return ImageStack(data=d, titleStub='Redimensioned')
|
|
1393
|
+
|