python-microscopy 25.11.20__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.cp313-win_amd64.dll.a +0 -0
- PYME/Acquire/Hardware/Simulator/illuminate.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/Analysis/PSFGen/ps_app.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/Analysis/points/DeClump/deClump.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/Analysis/points/DistHist/distHist.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/Analysis/points/EdgeDB/edgeDB.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/Analysis/points/SoftRend/triRend.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/Analysis/points/arcfit/arcmf.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/Analysis/points/astigmatism/astiglookup.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/Analysis/points/traveling_salesperson/two_opt_utils.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/DSView/LUT/lut.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/IO/buffer_helpers.cp313-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 +204 -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.cp313-win_amd64.dll.a +0 -0
- PYME/contrib/gohlke/_tifffile.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/experimental/_octree.cp313-win_amd64.pyd +0 -0
- PYME/experimental/_octree.pyx +477 -0
- PYME/experimental/_treap.cp313-win_amd64.dll.a +0 -0
- PYME/experimental/_treap.cp313-win_amd64.pyd +0 -0
- PYME/experimental/_treap.pyx +267 -0
- PYME/experimental/_triangle_mesh.cp313-win_amd64.dll.a +0 -0
- PYME/experimental/_triangle_mesh.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/experimental/func_octree.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/experimental/triangle_mesh_utils.cp313-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.cp313-win_amd64.dll.a +0 -0
- PYME/localization/cInterp/cInterp.cp313-win_amd64.pyd +0 -0
- PYME/localization/cInterp/setup.py +54 -0
- PYME/localization/cModels/__init__.py +24 -0
- PYME/localization/cModels/gauss_app.cp313-win_amd64.dll.a +0 -0
- PYME/localization/cModels/gauss_app.cp313-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 +62 -0
- python_microscopy-25.11.20.dist-info/METADATA +68 -0
- python_microscopy-25.11.20.dist-info/RECORD +1278 -0
- python_microscopy-25.11.20.dist-info/WHEEL +4 -0
- python_microscopy-25.11.20.dist-info/entry_points.txt +18 -0
PYME/IO/clusterIO.py
ADDED
|
@@ -0,0 +1,1076 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
API interface to PYME cluster storage.
|
|
4
|
+
--------------------------------------
|
|
5
|
+
|
|
6
|
+
The cluster storage effectively aggregates storage across a number of cluster nodes. In contrast to a standard file-system,
|
|
7
|
+
we only support atomic reads and writes of entire files, and only support a single write to a given file (no modification
|
|
8
|
+
or replacement). Under the hood, the file system is implemented as a bunch of HTTP servers, with the `clusterIO` library
|
|
9
|
+
simply presenting a unified view of the files on all servers.
|
|
10
|
+
|
|
11
|
+
.. note::
|
|
12
|
+
|
|
13
|
+
PYME cluster storage has a number of design aspects which trade some safety for speed. Importantly it lacks features
|
|
14
|
+
such as locking found in traditional filesystems. This is largely offset by only supporting atomic writes, and being
|
|
15
|
+
write once (no deletion or modification), but does rely on clients being well behaved (i.e. not trying to write to
|
|
16
|
+
the same file concurrently) - see `put_file()` for more details. Directory listings etc .. are also not guaranteed
|
|
17
|
+
to update immediately after file puts, with a latency of up to 2s for directory updates being possible.
|
|
18
|
+
|
|
19
|
+
The most important functions are:
|
|
20
|
+
|
|
21
|
+
| :func:`get_file` which performs an atomic get
|
|
22
|
+
| :func:`put_file` which performs an atomic put to a randomly [#f1]_ chosen server
|
|
23
|
+
| :func:`listdir` which performs a (unified) directory listing
|
|
24
|
+
|
|
25
|
+
There are also a bunch of utility functions, mirroring some of those available in the os, os.path, and glob modules:
|
|
26
|
+
|
|
27
|
+
:func:`exists`
|
|
28
|
+
:func:`cglob`
|
|
29
|
+
:func:`walk`
|
|
30
|
+
:func:`isdir`
|
|
31
|
+
:func:`stat`
|
|
32
|
+
|
|
33
|
+
And finally some functions to facilitate efficient (and data local) operations
|
|
34
|
+
|
|
35
|
+
| :func:`is_local` which determines if a file is hosted on the local machine
|
|
36
|
+
| :func:`get_local_path` which returns a local path if a file is local
|
|
37
|
+
| :func:`locate_file` which returns a list of http urls where the given file can be found
|
|
38
|
+
| :func:`put_files` which implements a streamed, high performance, put of multiple files
|
|
39
|
+
|
|
40
|
+
There are are also higher level functions in :mod:`PYME.IO.unifiedIO` which allows files to be accessed in a consistent
|
|
41
|
+
way given either a cluster URI or a local path and :mod:`PYME.IO.clusterResults` which helps with saving tabular data to
|
|
42
|
+
the cluster.
|
|
43
|
+
|
|
44
|
+
Cluster identification
|
|
45
|
+
----------------------
|
|
46
|
+
|
|
47
|
+
clusterIO automatically identifies the individual data servers that make up the cluster using the mDNS (zeroconf) protocol.
|
|
48
|
+
If you run a (or multiple) server(s) (see :mod:`PYME.cluster.HTTPDataServer`) clusterIO will find them with no additional
|
|
49
|
+
configuration. To support multiple clusters on a single network segment, however, we have the concept of a *cluster name*.
|
|
50
|
+
Servers will broadcast the name of the cluster they belong to as part of their mDNS advertisement.
|
|
51
|
+
|
|
52
|
+
On the client side, you can select which cluster you want to talk to with the ``serverfilter`` argument to the
|
|
53
|
+
clusterIO functions. Each function will access all servers which include the value of ``serverfilter`` in their name. If
|
|
54
|
+
unspecified, the value of the :mod:`PYME.config` configuration option ``dataserver-filter`` is used, which in turn defaults
|
|
55
|
+
to the local computer name. This enables the use of a local "cluster of one" for analysis without any additional configuration
|
|
56
|
+
and without interfering with any clusters which are already on the network. When setting up a proper, multi-computer cluster,
|
|
57
|
+
set the ``dataserver-filter`` config option on all members of the cluster o a common value. Once setup in this manner, it
|
|
58
|
+
should not be necessary to actually specify ``serverfilter`` when using clusterIO.
|
|
59
|
+
|
|
60
|
+
.. note::
|
|
61
|
+
|
|
62
|
+
The nature of ``serverfilter`` matches is both powerful and requires some care. A value of ``serverfilter=''`` will match
|
|
63
|
+
every data server running on the local network and present them as an aggregated cluster. Similarly ``serverfilter='cluster'``
|
|
64
|
+
will match ``cluster``, ``cluster1``, ``cluster2``, ``3cluster`` etc and prevent them all as an aggregated cluster. This
|
|
65
|
+
cluster aggregation opens up interesting postprocessing and display options, but to avoid unexpected effects it would
|
|
66
|
+
be prudent to follow the following recommendations.
|
|
67
|
+
|
|
68
|
+
1) Avoid cluster names which are substrings of other cluster names
|
|
69
|
+
2) Always use the full cluster name for ``serverfilter``.
|
|
70
|
+
|
|
71
|
+
Depending on how useful aggregation actually proves to be
|
|
72
|
+
``serverfilter`` might change to either requiring an exact match or compiling to a regex at some point in the future.
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
.. rubric:: Footnotes
|
|
76
|
+
|
|
77
|
+
.. [#f1] technically we do some basic load balancing
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
Function Documentation
|
|
81
|
+
-----------------------
|
|
82
|
+
|
|
83
|
+
"""
|
|
84
|
+
import six
|
|
85
|
+
#import urllib
|
|
86
|
+
import socket
|
|
87
|
+
import requests
|
|
88
|
+
import time
|
|
89
|
+
import numpy as np
|
|
90
|
+
import threading
|
|
91
|
+
from PYME.IO import unifiedIO
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
import http.client as httplib
|
|
96
|
+
except ImportError:
|
|
97
|
+
#py2
|
|
98
|
+
import httplib # type: ignore
|
|
99
|
+
|
|
100
|
+
import socket
|
|
101
|
+
import os
|
|
102
|
+
|
|
103
|
+
USE_RAW_SOCKETS = True
|
|
104
|
+
|
|
105
|
+
from PYME.misc.computerName import GetComputerName
|
|
106
|
+
compName = GetComputerName()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def to_bytes(input):
|
|
110
|
+
"""
|
|
111
|
+
Helper function for python3k to force urls etc to byte strings
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
input
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
if isinstance(input, str):
|
|
123
|
+
return input.encode('utf8')
|
|
124
|
+
else:
|
|
125
|
+
return input
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
from PYME import config
|
|
129
|
+
from PYME.misc.computerName import GetComputerName
|
|
130
|
+
local_dataroot = (config.get('dataserver-root'))
|
|
131
|
+
local_serverfilter = (config.get('dataserver-filter', GetComputerName()))
|
|
132
|
+
|
|
133
|
+
import sys
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
# noinspection PyCompatibility
|
|
137
|
+
from urlparse import urlparse # type: ignore
|
|
138
|
+
except ImportError:
|
|
139
|
+
#py3
|
|
140
|
+
# noinspection PyCompatibility
|
|
141
|
+
from urllib.parse import urlparse
|
|
142
|
+
|
|
143
|
+
import logging
|
|
144
|
+
|
|
145
|
+
logging.getLogger("requests").setLevel(logging.WARNING)
|
|
146
|
+
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
|
147
|
+
|
|
148
|
+
logger = logging.getLogger(__name__)
|
|
149
|
+
|
|
150
|
+
from .cluster_directory import _LimitedSizeDict, get_ns, DirectoryInfoManager
|
|
151
|
+
|
|
152
|
+
#_locateCache = _LimitedSizeDict(size_limit=500)
|
|
153
|
+
#_dirCache = _LimitedSizeDict(size_limit=100)
|
|
154
|
+
#DIR_CACHE_TIME = 1
|
|
155
|
+
_fileCache = _LimitedSizeDict(size_limit=100)
|
|
156
|
+
_dir_managers = {}
|
|
157
|
+
|
|
158
|
+
def get_dir_manager(serverfilter=local_serverfilter):
|
|
159
|
+
try:
|
|
160
|
+
return _dir_managers[serverfilter]
|
|
161
|
+
except KeyError:
|
|
162
|
+
_dir_managers[serverfilter] = DirectoryInfoManager(serverfilter=serverfilter)
|
|
163
|
+
|
|
164
|
+
return _dir_managers[serverfilter]
|
|
165
|
+
|
|
166
|
+
#use one session for each server (to allow http keep-alives)
|
|
167
|
+
sessions = {}
|
|
168
|
+
def _getSession(url):
|
|
169
|
+
if not isinstance(url, bytes):
|
|
170
|
+
url = url.encode()
|
|
171
|
+
|
|
172
|
+
servinfo = url.split(b'/')[2]
|
|
173
|
+
try:
|
|
174
|
+
session = sessions[servinfo]
|
|
175
|
+
except KeyError:
|
|
176
|
+
session = requests.Session()
|
|
177
|
+
session.trust_env = False
|
|
178
|
+
sessions[servinfo] = session
|
|
179
|
+
|
|
180
|
+
return session
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def locate_file(filename, serverfilter=local_serverfilter, return_first_hit=False):
|
|
184
|
+
"""
|
|
185
|
+
Searches the cluster to find which server(s) a given file is stored on
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
filename : str
|
|
190
|
+
The file name
|
|
191
|
+
serverfilter : str
|
|
192
|
+
The name of our cluster (allows for having multiple clusters on the same network segment)
|
|
193
|
+
return_first_hit : bool
|
|
194
|
+
Whether to try and find all locations, or return when we find the first copy
|
|
195
|
+
|
|
196
|
+
Returns
|
|
197
|
+
-------
|
|
198
|
+
|
|
199
|
+
"""
|
|
200
|
+
|
|
201
|
+
return get_dir_manager(serverfilter).locate_file(filename, return_first_hit)
|
|
202
|
+
|
|
203
|
+
def listdirectory(dirname, serverfilter=local_serverfilter, timeout=5):
|
|
204
|
+
"""Lists the contents of a directory on the cluster.
|
|
205
|
+
|
|
206
|
+
Returns a dictionary mapping filenames to clusterListing.FileInfo named tuples.
|
|
207
|
+
"""
|
|
208
|
+
return get_dir_manager(serverfilter).listdirectory(dirname, timeout)
|
|
209
|
+
|
|
210
|
+
def listdir(dirname, serverfilter=local_serverfilter):
|
|
211
|
+
"""Lists the contents of a directory on the cluster. Similar to os.listdir,
|
|
212
|
+
but directories are indicated by a trailing slash
|
|
213
|
+
"""
|
|
214
|
+
|
|
215
|
+
return get_dir_manager(serverfilter).listdir(dirname)
|
|
216
|
+
|
|
217
|
+
def isdir(name, serverfilter=local_serverfilter):
|
|
218
|
+
"""
|
|
219
|
+
Tests if a given path on the cluster is a directory. Analogous to os.path.isdir
|
|
220
|
+
|
|
221
|
+
Parameters
|
|
222
|
+
----------
|
|
223
|
+
name
|
|
224
|
+
serverfilter
|
|
225
|
+
|
|
226
|
+
Returns
|
|
227
|
+
-------
|
|
228
|
+
|
|
229
|
+
True or False
|
|
230
|
+
|
|
231
|
+
"""
|
|
232
|
+
return get_dir_manager(serverfilter).isdir(name)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def cglob(pattern, serverfilter=local_serverfilter):
|
|
236
|
+
"""
|
|
237
|
+
Find files matching a given glob on the cluster. Analogous to the python glob.glob function.
|
|
238
|
+
|
|
239
|
+
Parameters
|
|
240
|
+
----------
|
|
241
|
+
pattern : string glob
|
|
242
|
+
serverfilter : cluster name (optional)
|
|
243
|
+
|
|
244
|
+
Returns
|
|
245
|
+
-------
|
|
246
|
+
|
|
247
|
+
a list of files matching the glob
|
|
248
|
+
|
|
249
|
+
"""
|
|
250
|
+
return get_dir_manager(serverfilter).cglob(pattern)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def exists(name, serverfilter=local_serverfilter):
|
|
254
|
+
"""
|
|
255
|
+
Test whether a file exists on the cluster. Analogue to os.path.exists for local files.
|
|
256
|
+
|
|
257
|
+
Parameters
|
|
258
|
+
----------
|
|
259
|
+
name : string, file path
|
|
260
|
+
serverfilter : name of the cluster (optional)
|
|
261
|
+
|
|
262
|
+
Returns
|
|
263
|
+
-------
|
|
264
|
+
|
|
265
|
+
True if file exists, else False
|
|
266
|
+
|
|
267
|
+
"""
|
|
268
|
+
return get_dir_manager(serverfilter).exists(name)
|
|
269
|
+
|
|
270
|
+
class _StatResult(object):
|
|
271
|
+
def __init__(self, file_info):
|
|
272
|
+
self.st_size = file_info.size
|
|
273
|
+
self.size = self.st_size
|
|
274
|
+
self.st_ctime = time.time()
|
|
275
|
+
self.st_atime = self.st_ctime
|
|
276
|
+
self.st_mtime = self.st_ctime
|
|
277
|
+
self.type = file_info.type
|
|
278
|
+
|
|
279
|
+
def stat(name, serverfilter=local_serverfilter):
|
|
280
|
+
"""
|
|
281
|
+
Cluster analog to os.stat
|
|
282
|
+
|
|
283
|
+
Parameters
|
|
284
|
+
----------
|
|
285
|
+
name
|
|
286
|
+
serverfilter
|
|
287
|
+
|
|
288
|
+
Returns
|
|
289
|
+
-------
|
|
290
|
+
|
|
291
|
+
"""
|
|
292
|
+
from . import clusterListing as cl
|
|
293
|
+
|
|
294
|
+
name = (name)
|
|
295
|
+
serverfilter = (serverfilter)
|
|
296
|
+
|
|
297
|
+
rname = name.rstrip('/')
|
|
298
|
+
dirname, fname = os.path.split(rname)
|
|
299
|
+
|
|
300
|
+
listing = listdirectory(dirname, serverfilter)
|
|
301
|
+
#print name, listing
|
|
302
|
+
|
|
303
|
+
if fname == '':
|
|
304
|
+
#special case for the root directory
|
|
305
|
+
return _StatResult(cl.FileInfo(cl.FILETYPE_DIRECTORY, 0))
|
|
306
|
+
|
|
307
|
+
try:
|
|
308
|
+
r = _StatResult(listing[fname])
|
|
309
|
+
except KeyError:
|
|
310
|
+
try:
|
|
311
|
+
r = _StatResult(listing[fname + '/'])
|
|
312
|
+
except:
|
|
313
|
+
logger.exception('error stating: %s' % name)
|
|
314
|
+
#print dirname, fname
|
|
315
|
+
#print listing.keys()
|
|
316
|
+
raise
|
|
317
|
+
|
|
318
|
+
return r
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def walk(top, topdown=True, on_error=None, followlinks=False, serverfilter=local_serverfilter):
|
|
322
|
+
"""Directory tree generator. Adapted from the os.walk
|
|
323
|
+
function in the python std library.
|
|
324
|
+
|
|
325
|
+
see docs for os.walk for usage details
|
|
326
|
+
|
|
327
|
+
"""
|
|
328
|
+
|
|
329
|
+
top = (top)
|
|
330
|
+
serverfilter = (serverfilter)
|
|
331
|
+
|
|
332
|
+
# islink, join, isdir = path.islink, path.join, path.isdir
|
|
333
|
+
def islink(name):
|
|
334
|
+
# cluster does not currently have the concept of symlinks
|
|
335
|
+
return False
|
|
336
|
+
|
|
337
|
+
def join(*args):
|
|
338
|
+
j = '/'.join(args)
|
|
339
|
+
return j.replace('//', '/')
|
|
340
|
+
|
|
341
|
+
def isdir(name):
|
|
342
|
+
return name.endswith('/')
|
|
343
|
+
|
|
344
|
+
# We may not have read permission for top, in which case we can't
|
|
345
|
+
# get a list of the files the directory contains. os.path.walk
|
|
346
|
+
# always suppressed the exception then, rather than blow up for a
|
|
347
|
+
# minor reason when (say) a thousand readable directories are still
|
|
348
|
+
# left to visit. That logic is copied here.
|
|
349
|
+
try:
|
|
350
|
+
# Note that listdir and error are globals in this module due
|
|
351
|
+
# to earlier import-*.
|
|
352
|
+
names = listdir(top, serverfilter=serverfilter)
|
|
353
|
+
except Exception as err:
|
|
354
|
+
if on_error is not None:
|
|
355
|
+
on_error(err)
|
|
356
|
+
return
|
|
357
|
+
|
|
358
|
+
dirs, nondirs = [], []
|
|
359
|
+
for name in names:
|
|
360
|
+
if isdir(join(top, name)):
|
|
361
|
+
dirs.append(name)
|
|
362
|
+
else:
|
|
363
|
+
nondirs.append(name)
|
|
364
|
+
|
|
365
|
+
if topdown:
|
|
366
|
+
yield top, dirs, nondirs
|
|
367
|
+
for name in dirs:
|
|
368
|
+
new_path = join(top, name)
|
|
369
|
+
if followlinks or not islink(new_path):
|
|
370
|
+
for x in walk(new_path, topdown, on_error, followlinks):
|
|
371
|
+
yield x
|
|
372
|
+
if not topdown:
|
|
373
|
+
yield top, dirs, nondirs
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def _chooseLocation(locs):
|
|
377
|
+
"""Chose the location to load the file from
|
|
378
|
+
|
|
379
|
+
default to choosing the "closest" (currently the one with the shortest response
|
|
380
|
+
time to our directory query)
|
|
381
|
+
|
|
382
|
+
"""
|
|
383
|
+
|
|
384
|
+
#logger.debug('choosing location from: %s' % locs)
|
|
385
|
+
cost = np.array([l[1] for l in locs])
|
|
386
|
+
|
|
387
|
+
return locs[cost.argmin()][0]
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def parseURL(URL):
|
|
391
|
+
URL = (URL)
|
|
392
|
+
|
|
393
|
+
scheme, body = URL.split('://')
|
|
394
|
+
parts = body.split('/')
|
|
395
|
+
|
|
396
|
+
serverfilter = parts[0]
|
|
397
|
+
filename = '/'.join(parts[1:])
|
|
398
|
+
|
|
399
|
+
return filename, serverfilter
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def is_local(filename, serverfilter):
|
|
403
|
+
"""
|
|
404
|
+
Test to see if a file is held on the local computer.
|
|
405
|
+
|
|
406
|
+
This is used in the distributed scheduler to score tasks.
|
|
407
|
+
|
|
408
|
+
Parameters
|
|
409
|
+
----------
|
|
410
|
+
filename
|
|
411
|
+
serverfilter
|
|
412
|
+
|
|
413
|
+
Returns
|
|
414
|
+
-------
|
|
415
|
+
|
|
416
|
+
"""
|
|
417
|
+
filename = (filename)
|
|
418
|
+
serverfilter = (serverfilter)
|
|
419
|
+
|
|
420
|
+
if serverfilter == local_serverfilter and local_dataroot:
|
|
421
|
+
#look for the file in the local server folder (short-circuit the server)
|
|
422
|
+
localpath = os.path.join(local_dataroot, filename)
|
|
423
|
+
return os.path.exists(localpath)
|
|
424
|
+
else:
|
|
425
|
+
return False
|
|
426
|
+
|
|
427
|
+
def get_local_path(filename, serverfilter):
|
|
428
|
+
"""
|
|
429
|
+
Get a local path, if available based on a cluster filename
|
|
430
|
+
|
|
431
|
+
Parameters
|
|
432
|
+
----------
|
|
433
|
+
filename
|
|
434
|
+
serverfilter
|
|
435
|
+
|
|
436
|
+
Returns
|
|
437
|
+
-------
|
|
438
|
+
|
|
439
|
+
"""
|
|
440
|
+
filename = (filename)
|
|
441
|
+
serverfilter = (serverfilter)
|
|
442
|
+
|
|
443
|
+
if (serverfilter == local_serverfilter or serverfilter == '') and local_dataroot:
|
|
444
|
+
# look for the file in the local server folder (short-circuit the server)
|
|
445
|
+
# force file-name expansion so that we can verify that the requested file is actually under our
|
|
446
|
+
# dataroot.
|
|
447
|
+
localpath = os.path.abspath(os.path.join(local_dataroot, filename))
|
|
448
|
+
if localpath.startswith(local_dataroot) and os.path.exists(localpath):
|
|
449
|
+
return localpath
|
|
450
|
+
else:
|
|
451
|
+
return None
|
|
452
|
+
|
|
453
|
+
def get_file(filename, serverfilter=local_serverfilter, numRetries=3, use_file_cache=True, local_short_circuit=True, timeout=5):
|
|
454
|
+
"""
|
|
455
|
+
Get a file from the cluster.
|
|
456
|
+
|
|
457
|
+
Parameters
|
|
458
|
+
----------
|
|
459
|
+
filename : string
|
|
460
|
+
filename relative to cluster root
|
|
461
|
+
serverfilter : string
|
|
462
|
+
A filter to use when finding servers - used to facilitate the operation for multiple clusters on the one network
|
|
463
|
+
segment. Note that this is still not fully supported.
|
|
464
|
+
numRetries : int
|
|
465
|
+
The number of times to retry on failure
|
|
466
|
+
use_file_cache : bool
|
|
467
|
+
By default we cache the last 100 files requested locally. This cache never expires, although entries are dropped
|
|
468
|
+
when we get over 100 entries. Under our working assumption that data on the cluster is immutable, this is generally
|
|
469
|
+
safe, with the exception of log files and files streamed using the _aggregate functionality. We can optionally
|
|
470
|
+
request a non-cached version of the file.
|
|
471
|
+
local_short_circuit: bool
|
|
472
|
+
if file exists locally, load/read/return contents directly in this thread unless this flag is False in which case
|
|
473
|
+
we will get the contents through the dataserver over the network.
|
|
474
|
+
|
|
475
|
+
Returns
|
|
476
|
+
-------
|
|
477
|
+
|
|
478
|
+
"""
|
|
479
|
+
#filename = (filename)
|
|
480
|
+
#serverfilter = (serverfilter)
|
|
481
|
+
|
|
482
|
+
if use_file_cache:
|
|
483
|
+
try:
|
|
484
|
+
return _fileCache[(filename, serverfilter)]
|
|
485
|
+
except KeyError:
|
|
486
|
+
pass
|
|
487
|
+
|
|
488
|
+
#look for the file in the local server folder (short-circuit the server)
|
|
489
|
+
localpath = get_local_path(filename, serverfilter) if local_short_circuit else None
|
|
490
|
+
if localpath:
|
|
491
|
+
with open(localpath, 'rb') as f:
|
|
492
|
+
return f.read()
|
|
493
|
+
|
|
494
|
+
locs = locate_file(filename, serverfilter, return_first_hit=True)
|
|
495
|
+
|
|
496
|
+
nTries = 1
|
|
497
|
+
while nTries < numRetries and len(locs) == 0:
|
|
498
|
+
#retry, giving a little bit of time for the data servers to come up
|
|
499
|
+
logger.debug('Could not find %s, retrying ...' % filename)
|
|
500
|
+
time.sleep(1)
|
|
501
|
+
nTries += 1
|
|
502
|
+
locs = locate_file(filename, serverfilter, return_first_hit=True)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
if (len(locs) == 0):
|
|
506
|
+
# we did not find the file
|
|
507
|
+
logger.debug('could not find file %s on cluster: cluster nodes = %s' % (filename, get_ns().list()))
|
|
508
|
+
raise IOError("Specified file could not be found: %s" % filename)
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
url = _chooseLocation(locs)#.encode()
|
|
512
|
+
haveResult = False
|
|
513
|
+
nTries = 0
|
|
514
|
+
while nTries < numRetries and not haveResult:
|
|
515
|
+
try:
|
|
516
|
+
nTries += 1
|
|
517
|
+
s = _getSession(url)
|
|
518
|
+
t = time.time()
|
|
519
|
+
r = s.get(url, timeout=timeout)
|
|
520
|
+
dt = time.time() - t
|
|
521
|
+
if dt > 1:
|
|
522
|
+
logger.warning('get_file(%s) took > 1s (%3.2fs)' % (url, dt))
|
|
523
|
+
haveResult = True
|
|
524
|
+
except (requests.Timeout, requests.ConnectionError):
|
|
525
|
+
# s.get sometimes raises ConnectionError instead of ReadTimeoutError
|
|
526
|
+
# see https://github.com/requests/requests/issues/2392
|
|
527
|
+
logger.exception('Timeout on get file %s' % url)
|
|
528
|
+
logger.info('%d retries left' % (numRetries - nTries))
|
|
529
|
+
if nTries == numRetries:
|
|
530
|
+
raise
|
|
531
|
+
|
|
532
|
+
#s = _getSession(url)
|
|
533
|
+
#r = s.get(url, timeout=.5)
|
|
534
|
+
|
|
535
|
+
if not r.status_code == 200:
|
|
536
|
+
msg = 'Request for %s failed with error: %d' % (url, r.status_code)
|
|
537
|
+
logger.error(msg)
|
|
538
|
+
raise RuntimeError(msg)
|
|
539
|
+
|
|
540
|
+
content = r.content
|
|
541
|
+
|
|
542
|
+
if len(content) < 1000000:
|
|
543
|
+
#cache small files
|
|
544
|
+
_fileCache[(filename, serverfilter)] = content
|
|
545
|
+
|
|
546
|
+
return content
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
_last_access_time = {}
|
|
550
|
+
_lastwritespeed = {}
|
|
551
|
+
#_diskfreespace = {}
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
def _netloc(info):
|
|
555
|
+
return ('%s:%s' % (socket.inet_ntoa(info.address), info.port))
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
_choose_server_lock = threading.Lock()
|
|
559
|
+
def _chooseServer(serverfilter=local_serverfilter, exclude_netlocs=[]):
|
|
560
|
+
"""chose a server to save to by minimizing a cost function
|
|
561
|
+
|
|
562
|
+
currently takes the server which has been waiting longest
|
|
563
|
+
|
|
564
|
+
TODO: add free disk space and improve metrics/weightings
|
|
565
|
+
|
|
566
|
+
"""
|
|
567
|
+
serv_candidates = [((k), (v)) for k, v in get_ns().get_advertised_services() if
|
|
568
|
+
(serverfilter in (k)) and not (_netloc(v) in exclude_netlocs)]
|
|
569
|
+
|
|
570
|
+
with _choose_server_lock:
|
|
571
|
+
t = time.time()
|
|
572
|
+
|
|
573
|
+
costs = []
|
|
574
|
+
for k, v in serv_candidates:
|
|
575
|
+
try:
|
|
576
|
+
cost = _last_access_time[k] - t
|
|
577
|
+
except KeyError:
|
|
578
|
+
cost = -100
|
|
579
|
+
|
|
580
|
+
# try:
|
|
581
|
+
# cost -= 0*_lastwritespeed[k]/1e3
|
|
582
|
+
# except KeyError:
|
|
583
|
+
# pass
|
|
584
|
+
|
|
585
|
+
#try:
|
|
586
|
+
# cost -= _lastwritespeed[k]
|
|
587
|
+
#except KeyError:
|
|
588
|
+
# pass
|
|
589
|
+
|
|
590
|
+
costs.append(cost) # + .1*np.random.normal())
|
|
591
|
+
|
|
592
|
+
name, info = serv_candidates[np.argmin(costs)]
|
|
593
|
+
|
|
594
|
+
#t = time.time()
|
|
595
|
+
_last_access_time[name] = t
|
|
596
|
+
|
|
597
|
+
return name, info
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
def mirror_file(filename, serverfilter=local_serverfilter):
|
|
601
|
+
"""Copies a given file to another server on the cluster (chosen by algorithm)
|
|
602
|
+
|
|
603
|
+
The actual copy is performed peer to peer.
|
|
604
|
+
|
|
605
|
+
This is used in cluster duplication and should not (usually) be called by end-user code
|
|
606
|
+
"""
|
|
607
|
+
filename = (filename)
|
|
608
|
+
serverfilter = (serverfilter)
|
|
609
|
+
|
|
610
|
+
locs = locate_file(filename, serverfilter)
|
|
611
|
+
|
|
612
|
+
# where is the data currently located - exclude these from destinations
|
|
613
|
+
currentCopyNetlocs = [urlparse(l[0]).netloc for l in locs]
|
|
614
|
+
|
|
615
|
+
# choose a server to mirror onto
|
|
616
|
+
destName, destInfo = _chooseServer(serverfilter, exclude_netlocs=currentCopyNetlocs)
|
|
617
|
+
|
|
618
|
+
# and a source to copy from
|
|
619
|
+
sourceUrl = _chooseLocation(locs)
|
|
620
|
+
|
|
621
|
+
url = 'http://%s:%d/%s?MirrorSource=%s' % (socket.inet_ntoa(destInfo.address), destInfo.port, filename, sourceUrl)
|
|
622
|
+
url = url.encode()
|
|
623
|
+
s = _getSession(url)
|
|
624
|
+
r = s.put(url, timeout=1)
|
|
625
|
+
|
|
626
|
+
if not r.status_code == 200:
|
|
627
|
+
raise RuntimeError('Mirror failed with %d: %s' % (r.status_code, r.content))
|
|
628
|
+
|
|
629
|
+
r.close()
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
def put_file(filename, data, serverfilter=local_serverfilter, timeout=10):
|
|
633
|
+
"""
|
|
634
|
+
Put a file to the cluster. The server on which the file resides is chosen by a crude load-balancing algorithm
|
|
635
|
+
designed to uniformly distribute data across the servers within the cluster. The target file must not exist.
|
|
636
|
+
|
|
637
|
+
.. warning::
|
|
638
|
+
Putting a file is not strictly safe when run from multiple processes, and might result in unexpected behaviour
|
|
639
|
+
if puts with identical filenames are made concurrently (within ~2s). It is up to the calling code to ensure that such
|
|
640
|
+
filename collisions cannot occur. In practice this is reasonably easy to achieve when machine generated filenames
|
|
641
|
+
are used, but implies that interfaces which allow the user to specify arbitrary filenames should run through a
|
|
642
|
+
single user interface with external locking (e.g. clusterUI), particularly if there is any chance that multiple
|
|
643
|
+
users will be creating files simultaneously.
|
|
644
|
+
|
|
645
|
+
Parameters
|
|
646
|
+
----------
|
|
647
|
+
filename : string
|
|
648
|
+
path to new file, which much not exist
|
|
649
|
+
data : bytes
|
|
650
|
+
the data to put
|
|
651
|
+
serverfilter : string
|
|
652
|
+
the cluster name (optional)
|
|
653
|
+
timeout: float
|
|
654
|
+
timeout in seconds for http operations. **Warning:** alter from the default setting of 1s only with extreme care.
|
|
655
|
+
If operations are timing out it is usually an indication that something else is going wrong and you should usually
|
|
656
|
+
fix this first. The serverless and lockless architecture depends on having low latency.
|
|
657
|
+
|
|
658
|
+
Returns
|
|
659
|
+
-------
|
|
660
|
+
|
|
661
|
+
"""
|
|
662
|
+
|
|
663
|
+
from . import clusterListing as cl
|
|
664
|
+
|
|
665
|
+
if not isinstance(data, bytes):
|
|
666
|
+
raise TypeError('data should be bytes (not a unicode string)')
|
|
667
|
+
unifiedIO.assert_name_ok(filename)
|
|
668
|
+
|
|
669
|
+
success = False
|
|
670
|
+
nAttempts = 0
|
|
671
|
+
|
|
672
|
+
while not success and nAttempts < 3:
|
|
673
|
+
nAttempts +=1
|
|
674
|
+
name, info = _chooseServer(serverfilter)
|
|
675
|
+
|
|
676
|
+
url = 'http://%s:%d/%s' % (socket.inet_ntoa(info.address), info.port, filename)
|
|
677
|
+
print(repr(url))
|
|
678
|
+
|
|
679
|
+
t = time.time()
|
|
680
|
+
|
|
681
|
+
#url = str(url) # force tp string (not unicode)
|
|
682
|
+
try:
|
|
683
|
+
s = _getSession(url)
|
|
684
|
+
r = s.put(url, data=data, timeout=timeout)
|
|
685
|
+
dt = time.time() - t
|
|
686
|
+
#print r.status_code
|
|
687
|
+
if not r.status_code == 200:
|
|
688
|
+
raise RuntimeError('Put failed with %d: %s' % (r.status_code, r.content))
|
|
689
|
+
|
|
690
|
+
_lastwritespeed[name] = len(data) / (dt + .001)
|
|
691
|
+
|
|
692
|
+
if dt > 1:
|
|
693
|
+
logger.warning('put_file(%s) on %s took more than 1s (%3.2f s)' % (filename, url, dt))
|
|
694
|
+
|
|
695
|
+
success = True
|
|
696
|
+
|
|
697
|
+
# add file to location cache
|
|
698
|
+
get_dir_manager(serverfilter).register_file(filename, url, len(data))
|
|
699
|
+
|
|
700
|
+
except requests.ConnectTimeout:
|
|
701
|
+
if nAttempts >= 3:
|
|
702
|
+
logger.error('Timeout attempting to put file: %s, after 3 retries, aborting' % url)
|
|
703
|
+
raise
|
|
704
|
+
else:
|
|
705
|
+
logger.warn('Timeout attempting to put file: %s, retrying' % url)
|
|
706
|
+
finally:
|
|
707
|
+
try:
|
|
708
|
+
r.close()
|
|
709
|
+
except:
|
|
710
|
+
pass
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
if USE_RAW_SOCKETS:
|
|
715
|
+
def _read_status(fp):
|
|
716
|
+
line = fp.readline()
|
|
717
|
+
#print('STATUS: %s' % line)
|
|
718
|
+
try:
|
|
719
|
+
[version, status, reason] = line.split(None, 2)
|
|
720
|
+
except ValueError:
|
|
721
|
+
[version, status] = line.split(None, 1)
|
|
722
|
+
reason = ""
|
|
723
|
+
|
|
724
|
+
status = int(status)
|
|
725
|
+
|
|
726
|
+
return version, status, reason
|
|
727
|
+
|
|
728
|
+
_MAXLINE = 65536
|
|
729
|
+
|
|
730
|
+
def _parse_response(fp):
|
|
731
|
+
'''A striped down version of httplib.HttpResponse.begin'''
|
|
732
|
+
|
|
733
|
+
headers = {}
|
|
734
|
+
# read until we get a non-100 response
|
|
735
|
+
while True:
|
|
736
|
+
version, status, reason = _read_status(fp)
|
|
737
|
+
if status != httplib.CONTINUE:
|
|
738
|
+
break
|
|
739
|
+
# skip the header from the 100 response
|
|
740
|
+
while True:
|
|
741
|
+
skip = fp.readline(_MAXLINE + 1)
|
|
742
|
+
if len(skip) > _MAXLINE:
|
|
743
|
+
raise httplib.LineTooLong("header line")
|
|
744
|
+
skip = skip.strip()
|
|
745
|
+
if not skip:
|
|
746
|
+
break
|
|
747
|
+
|
|
748
|
+
# read the rest of the headers
|
|
749
|
+
n_headers = 0
|
|
750
|
+
while True:
|
|
751
|
+
line = fp.readline(_MAXLINE +1)
|
|
752
|
+
if len(line) > _MAXLINE:
|
|
753
|
+
raise httplib.LineTooLong("header line")
|
|
754
|
+
line = line.strip()
|
|
755
|
+
#print(line)
|
|
756
|
+
|
|
757
|
+
if line in (b'\r\n', b'\n', b''):
|
|
758
|
+
break
|
|
759
|
+
|
|
760
|
+
n_headers += 1
|
|
761
|
+
if n_headers > httplib._MAXHEADERS:
|
|
762
|
+
raise httplib.HTTPException("got more than %d headers" % httplib._MAXHEADERS)
|
|
763
|
+
|
|
764
|
+
key, value = line.split(b': ')
|
|
765
|
+
|
|
766
|
+
headers[key.strip().lower()] = value.strip()
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
#print(headers)
|
|
770
|
+
|
|
771
|
+
#if six.PY2:
|
|
772
|
+
# msg = httplib.HTTPMessage(fp, 0)
|
|
773
|
+
# msg.fp = None #force the message to relinquish it's file pointer
|
|
774
|
+
# length = msg.getheader('content-length')
|
|
775
|
+
#else:
|
|
776
|
+
# # noting that httplib here is actually http.client
|
|
777
|
+
# msg = httplib.parse_headers(fp)
|
|
778
|
+
|
|
779
|
+
length = int(headers.get(b'content-length', 0))
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
if length > 0:
|
|
783
|
+
data = fp.read(length)
|
|
784
|
+
else:
|
|
785
|
+
data = b''
|
|
786
|
+
|
|
787
|
+
return status, reason, data
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
def _put_files_on_server(address, port, files, nChunksRemaining=None, dir_manager=None, serverfilter=local_serverfilter):
|
|
791
|
+
if nChunksRemaining is None:
|
|
792
|
+
nChunksRemaining = len(files)
|
|
793
|
+
|
|
794
|
+
if dir_manager is None:
|
|
795
|
+
dir_manager = get_dir_manager(serverfilter)
|
|
796
|
+
|
|
797
|
+
if not isinstance(address, str):
|
|
798
|
+
address = socket.inet_ntoa(address)
|
|
799
|
+
|
|
800
|
+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
801
|
+
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
|
802
|
+
s.settimeout(30)
|
|
803
|
+
|
|
804
|
+
#conect to the server
|
|
805
|
+
s.connect((address, port))
|
|
806
|
+
|
|
807
|
+
try:
|
|
808
|
+
datalen = 0
|
|
809
|
+
|
|
810
|
+
#_last_access_time[name] = t
|
|
811
|
+
|
|
812
|
+
url_ = 'http://%s:%d/' % (address, port)
|
|
813
|
+
|
|
814
|
+
rs = []
|
|
815
|
+
|
|
816
|
+
#nChunksRemaining = len(files)
|
|
817
|
+
connection = b'keep-alive'
|
|
818
|
+
#pipeline the sends
|
|
819
|
+
|
|
820
|
+
nChunksSpooled = 0
|
|
821
|
+
while nChunksRemaining > 0:
|
|
822
|
+
filename, data = files[-nChunksRemaining]
|
|
823
|
+
unifiedIO.assert_name_ok(filename)
|
|
824
|
+
dl = len(data)
|
|
825
|
+
if nChunksRemaining <= 1:
|
|
826
|
+
connection = b'close'
|
|
827
|
+
|
|
828
|
+
header = b'PUT /%s HTTP/1.1\r\nConnection: %s\r\nContent-Length: %d\r\n\r\n' % (
|
|
829
|
+
filename.encode(), connection, dl)
|
|
830
|
+
s.sendall(header)
|
|
831
|
+
s.sendall(data)
|
|
832
|
+
|
|
833
|
+
# register file now (TODO - wait until we get spooling confirmation?)
|
|
834
|
+
url = url_ + filename
|
|
835
|
+
dir_manager.register_file(filename, url, dl)
|
|
836
|
+
|
|
837
|
+
datalen += dl
|
|
838
|
+
nChunksSpooled += 1
|
|
839
|
+
nChunksRemaining -= 1
|
|
840
|
+
|
|
841
|
+
# # TODO - FIXME so that reading replies is fast enough
|
|
842
|
+
# for i in range(nChunksSpooled):
|
|
843
|
+
# #read all our replies
|
|
844
|
+
# #print(i, files[i][0])
|
|
845
|
+
# resp = httplib.HTTPResponse(s, buffering=False)
|
|
846
|
+
# resp.begin()
|
|
847
|
+
# status = resp.status
|
|
848
|
+
# msg = resp.read()
|
|
849
|
+
# if not status == 200:
|
|
850
|
+
# logging.debug(('Response %d - status: %d' % (i,status)) + ' msg: ' + msg)
|
|
851
|
+
# raise RuntimeError('Error spooling chunk %d: status: %d, msg: %s' % (i, status, msg))
|
|
852
|
+
|
|
853
|
+
fp = s.makefile('rb', 65536)
|
|
854
|
+
try:
|
|
855
|
+
for i in range(nChunksSpooled):
|
|
856
|
+
status, reason, msg = _parse_response(fp)
|
|
857
|
+
if not status == 200:
|
|
858
|
+
logging.error(('Response %d - status: %d' % (i, status)) + ' msg: ' + str(msg))
|
|
859
|
+
raise RuntimeError('Error spooling chunk %d: status: %d, msg: %s' % (i, status, str(msg)))
|
|
860
|
+
finally:
|
|
861
|
+
fp.close()
|
|
862
|
+
|
|
863
|
+
finally:
|
|
864
|
+
# this causes the far end to close the connection after sending all the replies
|
|
865
|
+
# it is important for the connection to close, otherwise the subsequent recieves will block forever
|
|
866
|
+
# TODO: This is probably a bug/feature of SimpleHTTPServer. The correct way of doing this is probably to send
|
|
867
|
+
# a "Connection: close" header in the last request.
|
|
868
|
+
# s.sendall('\r\n')
|
|
869
|
+
|
|
870
|
+
# try:
|
|
871
|
+
# #perform all the recieves at once
|
|
872
|
+
# resp = s.recv(4096)
|
|
873
|
+
# while len(resp) > 0:
|
|
874
|
+
# resp = s.recv(4096)
|
|
875
|
+
# except:
|
|
876
|
+
# logger.error('Failure to read from server %s' % socket.inet_ntoa(info.address))
|
|
877
|
+
# s.close()
|
|
878
|
+
# raise
|
|
879
|
+
#print resp
|
|
880
|
+
#TODO: Parse responses
|
|
881
|
+
s.close()
|
|
882
|
+
|
|
883
|
+
return nChunksRemaining, datalen
|
|
884
|
+
|
|
885
|
+
def put_files(files, serverfilter=local_serverfilter, timeout=30):
|
|
886
|
+
"""
|
|
887
|
+
Put a bunch of files to a single server in the cluster (chosen by algorithm)
|
|
888
|
+
|
|
889
|
+
This uses a long-lived http2 session with keep-alive to avoid the connection overhead in creating a new
|
|
890
|
+
session for each file, and puts files before waiting for a response to the last put. This function exists to
|
|
891
|
+
facilitate fast streaming
|
|
892
|
+
|
|
893
|
+
As it reads the replies *after* attempting to put all the files, this is currently not as safe as put_file (in
|
|
894
|
+
handling failures we assume that no attempts were successful after the first failed file).
|
|
895
|
+
|
|
896
|
+
Parameters
|
|
897
|
+
----------
|
|
898
|
+
files : list of tuple
|
|
899
|
+
a list of tuples of the form (<string> filepath, <bytes> data) for the files to be uploaded
|
|
900
|
+
|
|
901
|
+
serverfilter: str
|
|
902
|
+
the cluster name (optional), to select a specific cluster
|
|
903
|
+
|
|
904
|
+
Returns
|
|
905
|
+
-------
|
|
906
|
+
|
|
907
|
+
"""
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
files = [(f) for f in files]
|
|
911
|
+
serverfilter = (serverfilter)
|
|
912
|
+
|
|
913
|
+
nRetries = 0
|
|
914
|
+
nChunksRemaining = len(files)
|
|
915
|
+
|
|
916
|
+
dir_manager = get_dir_manager(serverfilter)
|
|
917
|
+
|
|
918
|
+
while nRetries < 3 and nChunksRemaining > 0:
|
|
919
|
+
name, info = _chooseServer(serverfilter)
|
|
920
|
+
#logger.debug('Chose server: %s:%d' % (name, info.port))
|
|
921
|
+
try:
|
|
922
|
+
t = time.time()
|
|
923
|
+
|
|
924
|
+
nChunksRemaining, datalen = _put_files_on_server(info.address, info.port, files, nChunksRemaining, dir_manager)
|
|
925
|
+
|
|
926
|
+
dt = time.time() - t
|
|
927
|
+
_lastwritespeed[name] = datalen / (dt + .001)
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
except socket.timeout:
|
|
931
|
+
if nRetries < 2:
|
|
932
|
+
nRetries += 1
|
|
933
|
+
logger.error('Timeout writing to %s, trying another server for %d remaining files' % (socket.inet_ntoa(info.address), nChunksRemaining))
|
|
934
|
+
else:
|
|
935
|
+
logger.exception('Timeout writing to %s after 3 retries, aborting - DATA WILL BE LOST' % socket.inet_ntoa(info.address))
|
|
936
|
+
raise
|
|
937
|
+
|
|
938
|
+
except socket.error:
|
|
939
|
+
if nRetries < 2:
|
|
940
|
+
nRetries += 1
|
|
941
|
+
logger.exception('Error writing to %s, trying another server for %d remaining files' % (socket.inet_ntoa(info.address), nChunksRemaining))
|
|
942
|
+
else:
|
|
943
|
+
logger.exception('Error writing to %s after 3 retries, aborting - DATA WILL BE LOST' % socket.inet_ntoa(info.address))
|
|
944
|
+
raise
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
#r.close()
|
|
951
|
+
else:
|
|
952
|
+
def put_files(files, serverfilter=local_serverfilter):
|
|
953
|
+
"""
|
|
954
|
+
Put a bunch of files to a single server in the cluster (chosen by algorithm)
|
|
955
|
+
|
|
956
|
+
This version does not normally get called, but is between put_file and the raw sockets version of put_files in speed.
|
|
957
|
+
|
|
958
|
+
Parameters
|
|
959
|
+
----------
|
|
960
|
+
files : list of tuple
|
|
961
|
+
a list of tuples of the form (<string> filepath, <bytes> data) for the files to be uploaded
|
|
962
|
+
|
|
963
|
+
serverfilter: str
|
|
964
|
+
the cluster name (optional), to select a specific cluster
|
|
965
|
+
|
|
966
|
+
Returns
|
|
967
|
+
-------
|
|
968
|
+
|
|
969
|
+
"""
|
|
970
|
+
files = [(f) for f in files]
|
|
971
|
+
serverfilter = (serverfilter)
|
|
972
|
+
|
|
973
|
+
name, info = _chooseServer(serverfilter)
|
|
974
|
+
dir_manager = get_dir_manager(serverfilter)
|
|
975
|
+
|
|
976
|
+
for filename, data in files:
|
|
977
|
+
unifiedIO.assert_name_ok(filename)
|
|
978
|
+
url = 'http://%s:%d/%s' % (socket.inet_ntoa(info.address), info.port, filename)
|
|
979
|
+
|
|
980
|
+
t = time.time()
|
|
981
|
+
#_last_access_time[name] = t
|
|
982
|
+
#url = str(url) #force to string on py2
|
|
983
|
+
s = _getSession(url)
|
|
984
|
+
r = s.put(url, data=data, timeout=1)
|
|
985
|
+
dt = time.time() - t
|
|
986
|
+
#print r.status_code
|
|
987
|
+
if not r.status_code == 200:
|
|
988
|
+
raise RuntimeError('Put failed with %d: %s' % (r.status_code, r.content))
|
|
989
|
+
|
|
990
|
+
dir_manager.register_file(filename, url, len(data))
|
|
991
|
+
_lastwritespeed[name] = len(data) / (dt + .001)
|
|
992
|
+
|
|
993
|
+
r.close()
|
|
994
|
+
|
|
995
|
+
_cached_status = None
|
|
996
|
+
_cached_status_expiry = 0
|
|
997
|
+
_status_lock = threading.Lock()
|
|
998
|
+
def get_status(serverfilter=local_serverfilter):
|
|
999
|
+
"""
|
|
1000
|
+
Get status of cluster servers (currently only used in the clusterIO web service)
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
Parameters
|
|
1004
|
+
----------
|
|
1005
|
+
serverfilter: str
|
|
1006
|
+
the cluster name (optional), to select a specific cluster
|
|
1007
|
+
|
|
1008
|
+
Returns
|
|
1009
|
+
-------
|
|
1010
|
+
status_list: list
|
|
1011
|
+
a status dictionary for each node. See PYME.cluster.HTTPDataServer.updateStatus
|
|
1012
|
+
Disk: dict
|
|
1013
|
+
total: int
|
|
1014
|
+
storage on the node [bytes]
|
|
1015
|
+
used: int
|
|
1016
|
+
used storage on the node [bytes]
|
|
1017
|
+
free: int
|
|
1018
|
+
available storage on the node [bytes]
|
|
1019
|
+
CPUUsage: float
|
|
1020
|
+
cpu usage as a percentile
|
|
1021
|
+
MemUsage: dict
|
|
1022
|
+
total: int
|
|
1023
|
+
total RAM [bytes]
|
|
1024
|
+
available: int
|
|
1025
|
+
free RAM [bytes]
|
|
1026
|
+
percent: float
|
|
1027
|
+
percent usage
|
|
1028
|
+
used: int
|
|
1029
|
+
used RAM [bytes], calculated differently depending on platform
|
|
1030
|
+
free: int
|
|
1031
|
+
RAM which is zero'd and ready to go [bytes]
|
|
1032
|
+
[other]:
|
|
1033
|
+
more platform-specific fields
|
|
1034
|
+
Network: dict
|
|
1035
|
+
send: int
|
|
1036
|
+
bytes sent per second since the last status update
|
|
1037
|
+
recv: int
|
|
1038
|
+
bytes received per second since the last status update
|
|
1039
|
+
GPUUsage: list of float
|
|
1040
|
+
[optional] returned for NVIDIA GPUs only. Should be compute usage per gpu as percent?
|
|
1041
|
+
GPUMem: list of float
|
|
1042
|
+
[optional] returned for NVIDIA GPUs only. Should be memory usage per gpu as percent?
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
"""
|
|
1046
|
+
global _cached_status, _cached_status_expiry
|
|
1047
|
+
|
|
1048
|
+
serverfilter = (serverfilter)
|
|
1049
|
+
|
|
1050
|
+
with _status_lock:
|
|
1051
|
+
t = time.time()
|
|
1052
|
+
if t > _cached_status_expiry:
|
|
1053
|
+
status = []
|
|
1054
|
+
|
|
1055
|
+
for name, info in get_ns().get_advertised_services():
|
|
1056
|
+
if serverfilter in name:
|
|
1057
|
+
surl = 'http://%s:%d/__status' % (socket.inet_ntoa(info.address), info.port)
|
|
1058
|
+
url = surl.encode()
|
|
1059
|
+
s = _getSession(url)
|
|
1060
|
+
try:
|
|
1061
|
+
r = s.get(url, timeout=.5)
|
|
1062
|
+
st = r.json()
|
|
1063
|
+
st['Responsive'] = True
|
|
1064
|
+
status.append(st)
|
|
1065
|
+
except (requests.Timeout, requests.ConnectionError):
|
|
1066
|
+
# s.get sometimes raises ConnectionError instead of ReadTimeoutError
|
|
1067
|
+
# see https://github.com/requests/requests/issues/2392
|
|
1068
|
+
status.append({"IPAddress":socket.inet_ntoa(info.address), 'Port':info.port, 'Responsive' : False})
|
|
1069
|
+
|
|
1070
|
+
_cached_status = status
|
|
1071
|
+
_cached_status_expiry = time.time() + 1.0
|
|
1072
|
+
|
|
1073
|
+
return _cached_status
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
|