diff --git a/config/.DS_Store b/config/.DS_Store index 1daa08e..29eb642 100644 Binary files a/config/.DS_Store and b/config/.DS_Store differ diff --git a/config/config.properties b/config/config.properties index 914b94b..ef23751 100755 --- a/config/config.properties +++ b/config/config.properties @@ -1,48 +1,72 @@ -#Tue Mar 30 11:55:18 CEST 2021 +#Mon May 01 11:27:46 CEST 2023 +XScanAppendSuffix=true +XScanCrlogicAbortable=true +XScanCrlogicChannel=null +XScanCrlogicIoc=null +XScanCrlogicPrefix=null +XScanCrlogicSimulated=false +XScanMoveTimeout=600 autoSaveScanData=true -simulation=false commandExecutionEvents=true -logDaysToLive=50 +createSessionFiles=false +dataLayout=default +dataPath={data}/{year}_{month}/{date}/{date}_{time}_{name} +dataProvider=h5 +dataScanFlushRecords=true +dataScanLazy=false +dataScanLazyTableCreation=false +dataScanPreserveTypes=false +dataScanReleaseRecords=false dataScanSaveOutput=false -handleSessions=true -userAuthenticator=ch.psi.pshell.security.LdapAuthenticator | ldap\://d.psi.ch | d.psi.ch | users.psi -logLevelConsole=Off -scanStreamerPort=5563 dataScanSaveScript=false -dataScanSaveSetpoints=false +dataScanSaveSetpoints=true +dataServerPort=5573 +dataTransferHost= +dataTransferMode=Off +dataTransferPath=~/test/transfer +dataTransferUser=gobbo_a +depthDimension=0 +disableDataFileLogs=false +disableEmbeddedAttributes=true +fdaSerialization=true +filePermissionsConfig=Default +filePermissionsData=Default +filePermissionsLogs=Protected +filePermissionsScripts=Default +generateCommandExecutionEvents=true +handleSessions=true +hideServerMessages=false +hostName= +instanceName=Dev +logDaysToLive=50 +logLevel=Fine +logLevelConsole=Off +logPath={logs}/{date}_{time} +noBytecodeFiles=false +notificationLevel=User notifiedTasks=Test1,TestDate, xxx parallelInitialization=false -dataTransferPath=~/test/transfer -saveConsoleSessionFiles=false -dataTransferHost= -versionTrackingManual=true -dataTransferMode=Off -hostName= -userManagement=true -instanceName=Dev -disableEmbeddedAttributes=true -dataServerPort=5573 -hideServerMessages=false -serverPort=8080 -versionTrackingEnabled=true -dataPath={data}/{year}_{month}/{date}/{date}_{time}_{name} -serverEnabled=false -dataScanReleaseRecords=false -depthDimension=0 -dataScanPreserveTypes=false -logLevel=Fine -dataScanFlushRecords=false -logPath={logs}/{date}_{time} -dataLayout=default -disableDataFileLogs=false -sessionHandling=On -generateCommandExecutionEvents=true -terminalEnabled=false -notificationLevel=Off -terminalPort=0 -dataTransferUser=gobbo_a -createSessionFiles=false -versionTrackingLogin={context}/svcusr-hlapp_robot -versionTrackingRemote=git@git.psi.ch\:pshell_config/dev.git -dataProvider=h5 saveCommandStatistics=true +saveConsoleSessionFiles=false +scanStreamerPort=5563 +serverEnabled=false +serverPort=8080 +sessionHandling=On +simulation=false +terminalEnabled=false +terminalPort=0 +userAuthenticator=ch.psi.pshell.security.LdapAuthenticator | ldap\://d.psi.ch | d.psi.ch | users.psi +userManagement=true +versionTrackingEnabled=true +versionTrackingLogin={context}/svcusr-hlapp_robot +versionTrackingManual=true +versionTrackingRemote=git@git.psi.ch\:pshell_config/dev.git +xScanUsesFDASerialization=true +xscanAppendSuffix=true +xscanContinuousUpdate=false +xscanCrlogicAbortable=true +xscanCrlogicChannel=null +xscanCrlogicIoc=null +xscanCrlogicPrefix=null +xscanCrlogicSimulated=false +xscanMoveTimeout=600 diff --git a/config/devices.properties b/config/devices.properties index 37bb6cd..4d2fec6 100755 --- a/config/devices.properties +++ b/config/devices.properties @@ -1,14 +1,18 @@ +$det=ch.psi.pshell.epics.AreaDetector|13SIM1||1000|true +$bc=ch.psi.pshell.epics.AreaDetector|X09DA-FE-BEAMSZX|||true +bi=ch.psi.pshell.imaging.CameraSource|bc||-1000| sp=ch.psi.pshell.serial.SerialPortDevice|||| $pol_offset=ch.psi.pshell.epics.ChannelDouble|TEST|||false -$det=ch.psi.pshell.epics.AreaDetector|13SIM1|||false #det2=ch.psi.pshell.epics.AreaDetector|CCCC||| -image=ch.psi.pshell.imaging.CameraSource|det||-500|false +image=ch.psi.pshell.imaging.CameraSource|det|||true #image2=ch.psi.pshell.imaging.CameraSource|det2||| dispatcher=ch.psi.pshell.bs.Provider|tcp://localhost:9999||| bs=ch.psi.pshell.bs.Provider|tcp://SFTEST-CVME-DBPM1:9000||| #cam_server_local=ch.psi.pshell.bs.PipelineServer|localhost:8889|||true cam_server=ch.psi.pshell.bs.PipelineServer|localhost:8889|||true -#ts1=ch.psi.pshell.epics.GenericArray|TESTIOC:TESTWF2:MyWF||| +cs=ch.psi.pshell.bs.CameraServer|localhost:8888|||true +pip=ch.psi.pshell.camserver.PipelineStream|localhost:8889 simulation_sp|||true +#ts1=ch.psi.pshell.epics.GenericArray|TESTIOC:TESTWF2:MyWF|||false #monit_cam=ch.psi.pshell.imaging.MjpegSource|http://axis-accc8e9cc87b.psi.ch/axis-cgi/mjpg/video.cgi?camera=2 reopen||-200|false #tststr=ch.psi.pshell.epics.ChannelString|TESTIOC:TESTSINUS:SinCalc||| #stream=ch.psi.pshell.bs.Stream| #false:boolean||| @@ -56,7 +60,7 @@ dp=ch.psi.pshell.epics.DiscretePositioner|TESTIOC:CMD|||true #dev=ch.psi.pshell.device.DummyRegister|6||| #dev2=ch.psi.pshell.device.MyDevice|||| #$vhq=ch.psi.pshell.epics.ChannelDouble|T-MMDV5:IST:2 6|Read|| -#outc=ch.psi.pshell.epics.ChannelDouble|TESTIOC:TESTCALCOUT:Output|||true +outi=ch.psi.pshell.epics.ChannelInteger|TESTIOC:TESTCALCOUT:Output|||true #inpc=ch.psi.pshell.epics.ChannelDouble|TESTIOC:TESTCALCOUT:Input|||true out=ch.psi.pshell.epics.ChannelDouble|TESTIOC:TESTCALCOUT:Output 6|||true #outx=ch.psi.pshell.epics.ProcessVariable|TESTIOC:TESTCALCOUT:Output|||true @@ -72,7 +76,7 @@ arr1=ch.psi.pshell.epics.ChannelIntegerArray|TESTIOC:TESTWF2:MyWF -1 false||| mt=ch.psi.pshell.epics.GenericMatrix|TESTIOC:TESTWF2:MyWF 2 3 false||| mt1=ch.psi.pshell.epics.GenericMatrix|TESTIOC:TESTWF2:MyWF 3 2 False None [i||| as1=ch.psi.pshell.imaging.RegisterArraySource|arr1||| -cm1=ch.psi.pshell.epics.ChannelIntegerMatrix|TESTIOC:TESTWF2:MyWF 3 3 false||| +cm1=ch.psi.pshell.epics.ChannelIntegerMatrix|TESTIOC:TESTWF2:MyWF 3 2 false||| pv=ch.psi.pshell.epics.ProcessVariable|TESTIOC:TESTCALCOUT:Input|||true shutter=ch.psi.pshell.epics.BinaryPositioner|TESTIOC:TESTBO:MyBO TESTIOC:TESTBO:MyBO|||true $motor=ch.psi.pshell.epics.Motor|MTEST-GOBBO:MOT1|||true @@ -93,7 +97,7 @@ cv=ch.psi.pshell.epics.ControlledVariable|TESTIOC:TESTCALCOUT:Input TESTIOC:TEST #tcp=ch.psi.pshell.serial.TcpDevice|127.0.0.1:5554||| #beeper=Beeper|||| #imgbis=ch.psi.pshell.imaging.CameraSource|det||-500| -#sc=ch.psi.pshell.imaging.CameraSource|scienta||-500| +sc=ch.psi.pshell.imaging.CameraSource|scienta||-500| tst=ch.psi.pshell.imaging.FileSource|/Users/gobbo_a/Pictures/rsz_spine_pin.png||| ca=ch.psi.pshell.imaging.ColormapAdapter|tst||-500| #tst2=ch.psi.pshell.imaging.FileSource|C:\\Users\\gobbo_a\\Pictures\\tst.png||-500| @@ -101,8 +105,8 @@ ca=ch.psi.pshell.imaging.ColormapAdapter|tst||-500| #rec=ch.psi.pshell.detector.Receiver|tcp://127.0.0.1:5444|||true #rec2=ch.psi.pshell.detector.Receiver|tcp://127.0.0.1:5555||-500|false #pvt=ch.psi.pshell.epics.ProcessVariable|TESTIOC:TESTCALCOUT:Input|Read|| -#$master=ch.psi.pshell.modbus.ModbusTCP|127.0.0.1||| -#ai=ch.psi.pshell.modbus.AnalogOutput|master 0||| +#$tcp_master=ch.psi.pshell.modbus.ModbusTCP|127.0.0.1||| +#ai=ch.psi.pshell.modbus.AnalogOutput|tcp_master 0||| #cache=ch.psi.pshell.device.RegisterCache|sin||| #$scaler=ch.psi.pshell.epics.Scaler|SCALER||| #testpos=ch.psi.pshell.device.DummyPositioner||||true @@ -129,6 +133,7 @@ phi=ch.psi.pshell.device.DummyMotor||||true #fourc=ch.psi.pshell.device.MotorGroupBase|delta eta chi phi||| fourcv=ch.psi.pshell.device.MotorGroupBase|mu delta gamma eta||| energy=ch.psi.pshell.device.DummyPositioner||||true -gch=ch.psi.pshell.epics.GenericChannel|TESTIOC:TESTSINUS:SinCalc||| +gch=ch.psi.pshell.epics.GenericChannel|TESTIOC:TESTSINUS:SinCalc false||| garr=ch.psi.pshell.epics.GenericArray|TESTIOC:TESTWF2:MyWF -1 False||| darr=ch.psi.pshell.epics.ChannelDoubleArray|TESTIOC:TESTWF2:MyWF||| +master=ch.psi.pshell.device.MasterPositioner|mu delta gamma eta||| diff --git a/config/diffcalc/.DS_Store b/config/diffcalc/.DS_Store new file mode 100644 index 0000000..127c5c6 Binary files /dev/null and b/config/diffcalc/.DS_Store differ diff --git a/config/jcae.properties b/config/jcae.properties old mode 100755 new mode 100644 index d142e0e..a073710 --- a/config/jcae.properties +++ b/config/jcae.properties @@ -1,12 +1,12 @@ -#Mon Mar 08 09:04:03 CET 2021 -ch.psi.jcae.ContextFactory.maxArrayBytes=10000000 -ch.psi.jcae.impl.DefaultChannelService.timeout=500 -ch.psi.jcae.ChannelFactory.timeout=500 -ch.psi.jcae.ContextFactory.maxSendArrayBytes=1000000 -ch.psi.jcae.ChannelFactory.retries=1 -ch.psi.jcae.ContextFactory.useShellVariables=false -ch.psi.jcae.ContextFactory.addLocalBroadcastInterfaces=false -ch.psi.jcae.ContextFactory.addressList=127.0.0.1 127.0.0.1\:54321 +#Wed Aug 17 16:47:59 CEST 2022 +ch.psi.jcae.ContextFactory.addressList=localhost\:54321 sls-cagw.psi.ch\:5062 ch.psi.jcae.ContextFactory.serverPort= +ch.psi.jcae.ContextFactory.maxArrayBytes=20000000 +ch.psi.jcae.ContextFactory.maxSendArrayBytes=20000000 +ch.psi.jcae.ChannelFactory.retries=1 +ch.psi.jcae.ChannelFactory.timeout=3000 ch.psi.jcae.impl.DefaultChannelService.retries=1 +ch.psi.jcae.impl.DefaultChannelService.timeout=1000 ch.psi.jcae.ContextFactory.autoAddressList=true +ch.psi.jcae.ContextFactory.useShellVariables=false +ch.psi.jcae.ContextFactory.addLocalBroadcastInterfaces=true diff --git a/config/jcae.properties.back.properties b/config/jcae.properties.back.properties new file mode 100755 index 0000000..d142e0e --- /dev/null +++ b/config/jcae.properties.back.properties @@ -0,0 +1,12 @@ +#Mon Mar 08 09:04:03 CET 2021 +ch.psi.jcae.ContextFactory.maxArrayBytes=10000000 +ch.psi.jcae.impl.DefaultChannelService.timeout=500 +ch.psi.jcae.ChannelFactory.timeout=500 +ch.psi.jcae.ContextFactory.maxSendArrayBytes=1000000 +ch.psi.jcae.ChannelFactory.retries=1 +ch.psi.jcae.ContextFactory.useShellVariables=false +ch.psi.jcae.ContextFactory.addLocalBroadcastInterfaces=false +ch.psi.jcae.ContextFactory.addressList=127.0.0.1 127.0.0.1\:54321 +ch.psi.jcae.ContextFactory.serverPort= +ch.psi.jcae.impl.DefaultChannelService.retries=1 +ch.psi.jcae.ContextFactory.autoAddressList=true diff --git a/config/plugins.properties b/config/plugins.properties index 925fe4d..831e9c3 100755 --- a/config/plugins.properties +++ b/config/plugins.properties @@ -1,3 +1,21 @@ +sc.java=disabled +Regine.java=disabled +ScreenPanel11.java=disabled +ScreenPanel1.java=disabled +ScreenPanel10.java=disabled +MXSC-1.15.0.jar=disabled +Standard.java=disabled +TstProc.java=disabled +SIStem.java=disabled +ShiftsIO.java=disabled +Align_ComputeShifts2.java=disabled +Align_TranslationFilter2.java=disabled +Align_ComplexEdgeFiltering.java=disabled +Align_TranslationFilter.java=disabled +Align_ComputeShifts.java=disabled +ScreenPanel8.java=disabled +ScreenPanel9.java=disabled +ScreenPanel7.java=disabled HarmonicScan.java=disabled Sven.java=disabled ScreenPanel6.java=disabled @@ -11,7 +29,7 @@ ScreenPanel3OLD.java=disabled ScreenPanel3New.java=disabled a.java=disabled maxsize.java=disabled -MiniPID.java=enabled +MiniPID.java=disabled SpinnerLayoutTest.java=disabled MXSC-1.10.0.jar=disabled ScreenPanel3.java=disabled @@ -30,7 +48,7 @@ LayoutParallelScan.py=disabled PhaseScan.java=disabled PythonInteractive.java=disabled RotationReadback.java=disabled -SfCamera.java=enabled +SfCamera.java=disabled ScreenPanel.java=disabled Didier.java=disabled PersonalizedTheme.java=disabled diff --git a/config/preferences.bin b/config/preferences.bin new file mode 100644 index 0000000..a85b08d Binary files /dev/null and b/config/preferences.bin differ diff --git a/config/preferences.json b/config/preferences.json new file mode 100644 index 0000000..83e7a64 --- /dev/null +++ b/config/preferences.json @@ -0,0 +1,137 @@ +{ + "fontShellPanel" : { + "name" : "Monospaced", + "style" : 0, + "size" : 12 + }, + "fontShellCommand" : { + "name" : "SansSerif", + "style" : 0, + "size" : 13 + }, + "fontOutput" : { + "name" : "Monospaced", + "style" : 0, + "size" : 12 + }, + "fontEditor" : { + "name" : "Monospaced", + "style" : 0, + "size" : 12 + }, + "fontPlotLabel" : { + "name" : "SansSerif", + "style" : 0, + "size" : 11 + }, + "fontPlotTick" : { + "name" : "SansSerif", + "style" : 0, + "size" : 10 + }, + "fontPlotTitle" : { + "name" : "SansSerif", + "style" : 1, + "size" : 13 + }, + "fontTerminal" : { + "name" : "Menlo", + "style" : 0, + "size" : 14 + }, + "tabSize" : 4, + "contentWidth" : 0, + "editorBackground" : null, + "editorForeground" : null, + "simpleEditor" : false, + "hideEditorLineNumbers" : false, + "hideEditorContextMenu" : false, + "consoleLocation" : "Left", + "dataPanelLocation" : "Status", + "openDataFilesInDocTab" : false, + "noVariableEvaluationPropagation" : false, + "processingScripts" : [ ], + "asyncViewersUpdate" : false, + "asyncHistoryPlotsUpdate" : true, + "scanPlotDisabled" : false, + "scanTableDisabled" : false, + "cachedDataPanel" : false, + "dataExtensions" : "log txt xml py png tif tiff mat", + "dataSubFiles" : "*", + "hideFileName" : false, + "showEmergencyStop" : false, + "showHomingButtons" : false, + "showJogButtons" : false, + "hideScanPanel" : false, + "hideOutputPanel" : false, + "showXScanFileBrowser" : true, + "showQueueBrowser" : true, + "backgroundRendering" : false, + "showImageStatusBar" : true, + "persistRendererWindows" : false, + "defaultRendererColormap" : "Grayscale", + "linePlot" : "ch.psi.pshell.plot.LinePlotJFree", + "matrixPlot" : "ch.psi.pshell.plot.MatrixPlotJFree", + "surfacePlot" : "null", + "timePlot" : "ch.psi.pshell.plot.TimePlotJFree", + "plotsDetached" : false, + "plotsHidden" : false, + "plotLayout" : "Vertical", + "quality" : "High", + "defaultPlotColormap" : "Temperature", + "markerSize" : 2, + "plotBackground" : null, + "gridColor" : null, + "outlineColor" : null, + "disableOffscreenBuffer" : false, + "defaultPanels" : [ { + "deviceClassName" : "ch.psi.pshell.epics.Scaler", + "panelClassName" : "ch.psi.pshell.swing.ScalerPanel" + }, { + "deviceClassName" : "ch.psi.pshell.epics.Scienta", + "panelClassName" : "ch.psi.pshell.swing.ScientaPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.Motor", + "panelClassName" : "ch.psi.pshell.swing.MotorPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.MasterPositioner", + "panelClassName" : "ch.psi.pshell.swing.MasterPositionerPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.ProcessVariable", + "panelClassName" : "ch.psi.pshell.swing.ProcessVariablePanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.MotorGroup", + "panelClassName" : "ch.psi.pshell.swing.MotorGroupPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.DiscretePositioner", + "panelClassName" : "ch.psi.pshell.swing.DiscretePositionerPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.Camera", + "panelClassName" : "ch.psi.pshell.swing.CameraPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.Slit", + "panelClassName" : "ch.psi.pshell.swing.SlitPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.HistogramGenerator", + "panelClassName" : "ch.psi.pshell.swing.HistogramGeneratorPanel" + }, { + "deviceClassName" : "ch.psi.pshell.bs.Stream", + "panelClassName" : "ch.psi.pshell.swing.StreamPanel" + }, { + "deviceClassName" : "ch.psi.pshell.bs.StreamChannel", + "panelClassName" : "ch.psi.pshell.swing.StreamChannelPanel" + }, { + "deviceClassName" : "ch.psi.pshell.camserver.CamServerStream", + "panelClassName" : "ch.psi.pshell.swing.CamServerStreamPanel" + }, { + "deviceClassName" : "ch.psi.pshell.camserver.CamServerService", + "panelClassName" : "ch.psi.pshell.swing.CamServerServicePanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.ReadonlyRegister$ReadonlyRegisterArray", + "panelClassName" : "ch.psi.pshell.swing.DeviceValueChart" + }, { + "deviceClassName" : "ch.psi.pshell.device.ReadonlyRegister$ReadonlyRegisterMatrix", + "panelClassName" : "ch.psi.pshell.swing.DeviceValueChart" + } ], + "scriptPopupDialog" : "Exception" +} \ No newline at end of file diff --git a/config/scicat.properties b/config/scicat.properties index 702e6a9..5c2bdc9 100644 --- a/config/scicat.properties +++ b/config/scicat.properties @@ -1,4 +1,4 @@ -#Wed Feb 03 15:17:53 CET 2021 +#Thu May 06 14:19:02 CEST 2021 environment=test testParameters=-testenv -user slssim\:4DMGBarXmr sourceFolder=/Users/gobbo_a/dev/pshell/config/home/data @@ -8,4 +8,4 @@ ownerGroup=p00001 type=raw parameters=-ingest -allowexistingsource -noninteractive creationLocation=/PSI/SLS/SIM -principalInvestigator= +principalInvestigator=asd diff --git a/config/sessions.properties b/config/sessions.properties index 5f147e7..e54591a 100644 --- a/config/sessions.properties +++ b/config/sessions.properties @@ -1,3 +1,3 @@ -#Mon Mar 08 08:50:39 CET 2021 -SessionCounter=161 -CurrentSession=161 +#Mon Apr 03 15:43:39 CEST 2023 +CurrentSession=177 +SessionCounter=177 diff --git a/config/settings.properties b/config/settings.properties index e35f65d..d9dd8d0 100644 --- a/config/settings.properties +++ b/config/settings.properties @@ -1,6 +1,7 @@ -#Wed Apr 28 09:28:40 CEST 2021 -test=1 -geometry=fourcv -ScanIndex=5 -RSYNC_PATH=~/test/transfer +#Fri Aug 12 13:48:45 CEST 2022 FdaBrowser=true +OUTLIERS_THRESHOLD=200 +RSYNC_PATH=~/test/transfer +ScanIndex=5 +geometry=fourcv +test=1 diff --git a/config/setup.properties b/config/setup.properties index 844a8a2..6fc893c 100755 --- a/config/setup.properties +++ b/config/setup.properties @@ -1,7 +1,9 @@ -#Thu Feb 11 17:17:34 CET 2021 +#Fri Jun 10 11:48:34 CEST 2022 scriptPath={home}/script sessionsPath={outp}/sessions configFileDevices={config}/devices.properties +xscanPath={script}/test +queuePath={script}/queues extensionsPath={home}/extensions configFileUpdateStrategy={config}/update.properties configPath={home}/config @@ -16,7 +18,7 @@ configFileTasks={config}/tasks.properties configFileImageSources={config}/imaging.properties pluginsPath={home}/plugins consoleSessionsPath={sessions}/console -libraryPath={script}; {script}/Lib; src/main/assembly/script/tutorial +libraryPath={script}; {script}/Lib; src/main/assembly/script/tutorial; {script}/imaging configFilePlugins={config}/plugins.properties contextPath={outp}/context devicesPath={home}/devices diff --git a/config/tasks.properties b/config/tasks.properties index e9abe87..ac1d6a2 100755 --- a/config/tasks.properties +++ b/config/tasks.properties @@ -1,5 +1,5 @@ -#outupdate=0.0 -#spectrum=1.0 -#back=-1.0 -#task1=2.0 -#task2=1.0 +#outupdate=-1.0;3.0 +#spectrum=1.0;1.0 +#back=-1.0;1.0 +#task1=10.0;0.0 +#task2=1.0;1.0 diff --git a/config/variables.properties b/config/variables.properties index 65f7320..b7902cb 100644 --- a/config/variables.properties +++ b/config/variables.properties @@ -1,6 +1,7 @@ -#Mon Apr 12 12:26:10 CEST 2021 -LastRunDate=210412 -SessionCounter=127 +#Tue Apr 18 14:30:53 CEST 2023 CurrentSession=122 -FileSequentialNumber=1859 DaySequentialNumber=1 +FileSequentialNumber=5709 +LastRunDate=230418 +SessionCounter=127 +xxx=[1, 2, 3, 4] diff --git a/config/xscan.properties b/config/xscan.properties new file mode 100644 index 0000000..45e7147 --- /dev/null +++ b/config/xscan.properties @@ -0,0 +1,11 @@ +#Tue Mar 14 09:40:01 CET 2023 +actorMoveTimeout=600 +appendSuffix=true +channelCreationRetries=1 +crlogicAbortable=false +crlogicChannel= +crlogicIoc= +crlogicPrefix= +crlogicSimulated=false +dataBaseDirectory={data} +dataFilePrefix= diff --git a/devices/.DS_Store b/devices/.DS_Store new file mode 100644 index 0000000..1dccf7b Binary files /dev/null and b/devices/.DS_Store differ diff --git a/devices/0000.tiff.properties b/devices/0000.tiff.properties new file mode 100644 index 0000000..ab681c1 --- /dev/null +++ b/devices/0000.tiff.properties @@ -0,0 +1,20 @@ +#Mon Nov 07 11:49:02 CET 2022 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/0001.tiff.properties b/devices/0001.tiff.properties new file mode 100644 index 0000000..f7d13ee --- /dev/null +++ b/devices/0001.tiff.properties @@ -0,0 +1,20 @@ +#Thu Sep 29 09:20:02 CEST 2022 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/0002.tiff.properties b/devices/0002.tiff.properties new file mode 100644 index 0000000..6bf19f6 --- /dev/null +++ b/devices/0002.tiff.properties @@ -0,0 +1,20 @@ +#Thu Sep 29 09:21:24 CEST 2022 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/0003.tiff.properties b/devices/0003.tiff.properties new file mode 100644 index 0000000..b53cee4 --- /dev/null +++ b/devices/0003.tiff.properties @@ -0,0 +1,20 @@ +#Thu Sep 29 16:50:04 CEST 2022 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/20221027_155808_simulation_snapshot.h5.png.properties b/devices/20221027_155808_simulation_snapshot.h5.png.properties new file mode 100644 index 0000000..a93f370 --- /dev/null +++ b/devices/20221027_155808_simulation_snapshot.h5.png.properties @@ -0,0 +1,20 @@ +#Thu Oct 27 16:24:34 CEST 2022 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/20221027_162805_simulation_snapshot.h5.png.properties b/devices/20221027_162805_simulation_snapshot.h5.png.properties new file mode 100644 index 0000000..d9982bb --- /dev/null +++ b/devices/20221027_162805_simulation_snapshot.h5.png.properties @@ -0,0 +1,20 @@ +#Thu Oct 27 16:28:20 CEST 2022 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/A1.properties b/devices/A1.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/A1.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/A2.properties b/devices/A2.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/A2.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/A3.properties b/devices/A3.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/A3.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/A4.properties b/devices/A4.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/A4.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/A5.properties b/devices/A5.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/A5.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/B1.properties b/devices/B1.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/B1.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/B2.properties b/devices/B2.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/B2.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/B3.properties b/devices/B3.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/B3.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/B4.properties b/devices/B4.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/B4.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/B5.properties b/devices/B5.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/B5.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/C1.properties b/devices/C1.properties index 9f4654d..8ec6c1d 100644 --- a/devices/C1.properties +++ b/devices/C1.properties @@ -1,6 +1,8 @@ -#Fri Mar 19 09:06:16 CET 2021 +#Thu Mar 10 13:02:31 CET 2022 unit= +detection=null offset=10.0 precision=0 sign_bit=0 scale=4.0 +disabled=false diff --git a/devices/C2.properties b/devices/C2.properties index 564dd2e..c8d8a89 100644 --- a/devices/C2.properties +++ b/devices/C2.properties @@ -1,6 +1,8 @@ -#Fri Mar 19 09:06:16 CET 2021 +#Thu Mar 10 13:02:31 CET 2022 unit= +detection=null offset=20.0 precision=0 sign_bit=0 scale=1.0 +disabled=false diff --git a/devices/C3.properties b/devices/C3.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/C3.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/C4.properties b/devices/C4.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/C4.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/C5.properties b/devices/C5.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/C5.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/CameraServer.properties b/devices/CameraServer.properties new file mode 100644 index 0000000..7fb17af --- /dev/null +++ b/devices/CameraServer.properties @@ -0,0 +1,25 @@ +#Mon Nov 07 19:00:17 CET 2022 +colormap=Grayscale +colormapAutomatic=false +colormapLogarithmic=false +colormapMax=NaN +colormapMin=NaN +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/CurrentCamera.properties b/devices/CurrentCamera.properties index abe48d1..daafb6c 100755 --- a/devices/CurrentCamera.properties +++ b/devices/CurrentCamera.properties @@ -1,31 +1,31 @@ -#Fri Apr 23 13:56:44 CEST 2021 -spatialCalOffsetY=-485.427166868422 -spatialCalOffsetX=-638.5965043983313 -colormapLogarithmic=false -scale=1.0 -grayscale=false -spatialCalScaleX=-35.21126791588346 -spatialCalScaleY=-48.38709170854271 -colormapMax=16542.0 -serverURL=http\://gfa-lc6-64\:8889 -rescaleOffset=0.0 -roiWidth=-1 +#Mon Dec 05 15:49:55 CET 2022 colormap=Flame -imageWidth=0 -invert=false +colormapAutomatic=true +colormapLogarithmic=false +colormapMax=255.0 colormapMin=0.0 custom=12345 -rotation=0.0 -rotationCrop=false -rescaleFactor=1.0 -imageHeight=0 -spatialCalUnits=mm -flipVertically=false -roiHeight=-1 flipHorizontally=false -colormapAutomatic=true -roiY=0 -roiX=0 -transpose=false +flipVertically=false +grayscale=false +imageHeight=0 +imageWidth=0 +invert=false regionStartX=0 regionStartY=0 +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +serverURL=http\://gfa-lc6-64\:8889 +spatialCalOffsetX=-638.5965043983313 +spatialCalOffsetY=-485.427166868422 +spatialCalScaleX=-35.21126791588346 +spatialCalScaleY=-48.38709170854271 +spatialCalUnits=mm +transpose=false diff --git a/devices/D1.properties b/devices/D1.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/D1.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/D2.properties b/devices/D2.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/D2.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/D3.properties b/devices/D3.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/D3.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/D4.properties b/devices/D4.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/D4.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/D5.properties b/devices/D5.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/D5.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/E1.properties b/devices/E1.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/E1.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/E2.properties b/devices/E2.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/E2.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/E3.properties b/devices/E3.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/E3.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/E4.properties b/devices/E4.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/E4.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/E5.properties b/devices/E5.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/E5.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/F1.properties b/devices/F1.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/F1.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/F2.properties b/devices/F2.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/F2.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/F3.properties b/devices/F3.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/F3.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/F4.properties b/devices/F4.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/F4.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/F5.properties b/devices/F5.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/F5.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/R1.properties b/devices/R1.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/R1.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/R2.properties b/devices/R2.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/R2.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/R3.properties b/devices/R3.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/R3.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/R4.properties b/devices/R4.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/R4.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/R5.properties b/devices/R5.properties new file mode 100644 index 0000000..d1b8b54 --- /dev/null +++ b/devices/R5.properties @@ -0,0 +1,3 @@ +#Thu Mar 10 13:02:31 CET 2022 +detection=Both +disabled=false diff --git a/devices/RoomTemperatureBasePlate.properties b/devices/RoomTemperatureBasePlate.properties new file mode 100644 index 0000000..c0818ed --- /dev/null +++ b/devices/RoomTemperatureBasePlate.properties @@ -0,0 +1 @@ +#Thu Mar 10 13:02:31 CET 2022 diff --git a/devices/SS_20220610_o_SS_an5_10x10_20s_0636.tif.properties b/devices/SS_20220610_o_SS_an5_10x10_20s_0636.tif.properties new file mode 100644 index 0000000..a9bc250 --- /dev/null +++ b/devices/SS_20220610_o_SS_an5_10x10_20s_0636.tif.properties @@ -0,0 +1,20 @@ +#Fri Sep 30 13:20:13 CEST 2022 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/Time.properties b/devices/Time.properties index 2ca7570..56c0516 100755 --- a/devices/Time.properties +++ b/devices/Time.properties @@ -1,10 +1,11 @@ -#Wed Jul 25 10:47:11 CEST 2018 -maxValue=NaN +#Mon Jun 27 08:53:55 CEST 2022 minValue=NaN -offset=0.0 -precision=-1 -resolution=NaN -rotation=false -scale=1.0 -sign_bit=0 unit=null +offset=0.0 +maxValue=NaN +precision=-1 +rotation=false +sign_bit=0 +scale=1.0 +description=null +resolution=NaN diff --git a/devices/bi.properties b/devices/bi.properties new file mode 100644 index 0000000..95ca136 --- /dev/null +++ b/devices/bi.properties @@ -0,0 +1,25 @@ +#Wed Apr 20 15:41:28 CEST 2022 +spatialCalOffsetY=NaN +spatialCalOffsetX=NaN +colormapLogarithmic=false +scale=1.0 +grayscale=false +spatialCalScaleX=NaN +spatialCalScaleY=NaN +colormapMax=NaN +rescaleOffset=0.0 +roiWidth=-1 +colormap=Temperature +invert=false +colormapMin=NaN +rotation=0.0 +rotationCrop=false +rescaleFactor=1.0 +spatialCalUnits=mm +flipVertically=false +roiHeight=-1 +flipHorizontally=false +colormapAutomatic=true +roiY=0 +roiX=0 +transpose=false diff --git a/devices/bs.properties b/devices/bs.properties index f2c5ab3..c2c8702 100755 --- a/devices/bs.properties +++ b/devices/bs.properties @@ -1,7 +1,8 @@ -#Thu Nov 14 15:52:50 CET 2019 +#Tue Apr 18 14:14:16 CEST 2023 alignmentRetries=21 byteBufferAllocator=false disableCompression=true +headerReservingAllocator=false highWaterMark=100 keepListeningOnStop=false parallelHandlerProcessing=true diff --git a/devices/ca.properties b/devices/ca.properties index 821a40d..446c60e 100644 --- a/devices/ca.properties +++ b/devices/ca.properties @@ -1,4 +1,4 @@ -#Mon Mar 22 14:17:46 CET 2021 +#Fri May 07 11:51:42 CEST 2021 spatialCalOffsetY=NaN spatialCalOffsetX=NaN colormapLogarithmic=false diff --git a/devices/cam_server.properties b/devices/cam_server.properties index a654acc..4d985df 100755 --- a/devices/cam_server.properties +++ b/devices/cam_server.properties @@ -1,26 +1,26 @@ -#Thu Oct 15 09:46:07 CEST 2020 -spatialCalOffsetY=-485.427166868422 -spatialCalOffsetX=-638.5965043983313 +#Thu Oct 20 10:17:33 CEST 2022 +colormap=Flame +colormapAutomatic=true colormapLogarithmic=false -scale=1.0 -logarithmic=true +colormapMax=NaN +colormapMin=NaN +flipHorizontally=false +flipVertically=false grayscale=false +invert=false +logarithmic=true +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=-638.5965043983313 +spatialCalOffsetY=-485.427166868422 spatialCalScaleX=-35.21126791588346 spatialCalScaleY=-48.38709170854271 -colormapMax=NaN -rescaleOffset=0.0 -roiWidth=-1 -colormap=Flame -invert=false -colormapMin=NaN -rotationCrop=false -rotation=0.0 -rescaleFactor=1.0 spatialCalUnits=mm -flipVertically=false -roiHeight=-1 -flipHorizontally=false -colormapAutomatic=true -roiY=0 -roiX=0 transpose=false diff --git a/devices/chi.properties b/devices/chi.properties index 5789fcb..cfda8e1 100644 --- a/devices/chi.properties +++ b/devices/chi.properties @@ -1,16 +1,17 @@ -#Thu Aug 22 16:30:36 CEST 2019 -defaultSpeed=50.0 -estbilizationDelay=0 -maxSpeed=50.0 -maxValue=360.0 -minSpeed=0.1 -minValue=-360.0 -monitorByPosition=false +#Tue Jun 07 17:34:49 CEST 2022 offset=0.0 +maxValue=360.0 precision=2 -resolution=NaN rotation=false scale=1.0 -sign_bit=0 +description=null +estbilizationDelay=0 +maxSpeed=50.0 +resolution=NaN startRetries=1 +minValue=-360.0 unit=mm +defaultSpeed=50.0 +sign_bit=0 +monitorByPosition=false +minSpeed=0.1 diff --git a/devices/cm1.properties b/devices/cm1.properties index f461649..2ab2b3d 100644 --- a/devices/cm1.properties +++ b/devices/cm1.properties @@ -1,9 +1,10 @@ -#Tue Oct 30 09:41:22 CET 2018 -mirror_x=false -mirror_y=false +#Tue Jun 07 17:34:49 CEST 2022 precision=-1 -roi_height=-1 roi_width=-1 -roi_x=0 -roi_y=0 +mirror_y=false +mirror_x=false +description=null transpose=false +roi_y=0 +roi_height=-1 +roi_x=0 diff --git a/devices/cs.properties b/devices/cs.properties index 46b78df..0a96d1b 100755 --- a/devices/cs.properties +++ b/devices/cs.properties @@ -1,24 +1,25 @@ -#Wed Aug 09 16:33:39 CEST 2017 -colormap=Flame -colormapAutomatic=true -colormapMax=NaN -colormapMin=NaN -flipHorizontally=false -flipVertically=false -grayscale=false -invert=false -rescaleFactor=1.0 -rescaleOffset=0.0 -roiHeight=-1 -roiWidth=-1 -roiX=0 -roiY=0 -rotation=0.0 -rotationCrop=false -scale=1.0 -spatialCalOffsetX=NaN -spatialCalOffsetY=NaN -spatialCalScaleX=NaN -spatialCalScaleY=NaN -spatialCalUnits=mm -transpose=false +#Thu Oct 20 10:27:45 CEST 2022 +colormap=Flame +colormapAutomatic=true +colormapLogarithmic=false +colormapMax=NaN +colormapMin=NaN +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=-638.5965043983313 +spatialCalOffsetY=-485.427166868422 +spatialCalScaleX=-35.21126791588346 +spatialCalScaleY=-48.38709170854271 +spatialCalUnits=mm +transpose=false diff --git a/devices/curve_fitting.png.properties b/devices/curve_fitting.png.properties new file mode 100644 index 0000000..a801b6c --- /dev/null +++ b/devices/curve_fitting.png.properties @@ -0,0 +1,20 @@ +#Fri Jun 10 09:17:40 CEST 2022 +spatialCalOffsetY=NaN +invert=false +spatialCalOffsetX=NaN +rotation=0.0 +rotationCrop=false +scale=1.0 +rescaleFactor=1.0 +grayscale=false +spatialCalUnits=mm +flipVertically=false +roiHeight=-1 +spatialCalScaleX=NaN +spatialCalScaleY=NaN +flipHorizontally=false +roiY=0 +roiX=0 +rescaleOffset=0.0 +transpose=false +roiWidth=-1 diff --git a/devices/cv.properties b/devices/cv.properties index 3d57b9d..42eda39 100755 --- a/devices/cv.properties +++ b/devices/cv.properties @@ -1,10 +1,11 @@ -#Tue Jun 19 17:19:36 CEST 2018 +#Wed Jun 08 14:29:43 CEST 2022 accessType=ReadWrite -maxValue=1000.0 minValue=-1000.0 +unit=mm offset=0.0 -precision=3 -resolution=1.0 -scale=1.0 +maxValue=1000.0 +precision=5 sign_bit=0 -unit=C +scale=1.0 +description=Test Calcout Inopput +resolution=1.0 diff --git a/devices/delta.properties b/devices/delta.properties index 7adb232..f5f59da 100644 --- a/devices/delta.properties +++ b/devices/delta.properties @@ -1,16 +1,17 @@ -#Thu Aug 22 16:30:36 CEST 2019 -defaultSpeed=50.0 -estbilizationDelay=0 -maxSpeed=50.0 -maxValue=190.0 -minSpeed=0.1 -minValue=-19.0 -monitorByPosition=false +#Tue Jun 07 17:34:49 CEST 2022 offset=0.0 +maxValue=190.0 precision=2 -resolution=NaN rotation=false scale=1.0 -sign_bit=0 +description=null +estbilizationDelay=0 +maxSpeed=50.0 +resolution=NaN startRetries=1 +minValue=-19.0 unit=mm +defaultSpeed=50.0 +sign_bit=0 +monitorByPosition=false +minSpeed=0.1 diff --git a/devices/dispatcher.properties b/devices/dispatcher.properties index 6a28723..3b85b77 100755 --- a/devices/dispatcher.properties +++ b/devices/dispatcher.properties @@ -1,8 +1,9 @@ -#Thu Nov 14 15:57:07 CET 2019 +#Tue Apr 18 14:14:16 CEST 2023 alignmentRetries=20 byteBufferAllocator=false disableCompression=true dropIncomplete=true +headerReservingAllocator=false keepListeningOnStop=true mappingIncomplete=fill_null parallelHandlerProcessing=false diff --git a/devices/dp1.properties b/devices/dp1.properties index 6719cb3..c86dd93 100755 --- a/devices/dp1.properties +++ b/devices/dp1.properties @@ -1,11 +1,12 @@ -#Tue Jan 17 10:47:10 CET 2017 -motor1=0.0|4.0|8.0|0.0 -motor2=0.0|5.0|3.0|NaN -motor3=null -motor4=null -motor5=null -motor6=null -motor7=null -motor8=null -positions=Park|Ready|Out|Clear -precision=-1 +#Wed Jun 15 15:14:06 CEST 2022 +motor7=null +motor8=null +motor5=null +motor6=null +precision=-1 +description=null +positions=Park|Ready|Out|Clear +motor3=null +motor4=null +motor1=0.0|4.0|8.0|0.0 +motor2=0.0|5.0|3.0|NaN diff --git a/devices/eiger.properties b/devices/eiger.properties new file mode 100644 index 0000000..1933f9c --- /dev/null +++ b/devices/eiger.properties @@ -0,0 +1,17 @@ +#Wed Oct 05 10:33:50 CEST 2022 +defaultSpeed=1.0 +description=null +estbilizationDelay=0 +maxSpeed=10.0 +maxValue=10.0 +minSpeed=0.1 +minValue=-10.0 +monitorByPosition=false +offset=0.0 +precision=2 +resolution=NaN +rotation=false +scale=1.0 +sign_bit=0 +startRetries=1 +unit=mm diff --git a/devices/energy.properties b/devices/energy.properties index f443fec..cea9e32 100644 --- a/devices/energy.properties +++ b/devices/energy.properties @@ -1,10 +1,17 @@ -#Fri Aug 24 11:58:39 CEST 2018 -maxValue=NaN -minValue=NaN +#Tue Jun 07 17:34:49 CEST 2022 offset=0.0 +maxValue=200.0 precision=-1 -resolution=NaN rotation=false scale=1.0 -sign_bit=0 +description=null +estbilizationDelay=0 +maxSpeed=50.0 +resolution=NaN +startRetries=1 +minValue=-200.0 unit=null +defaultSpeed=50.0 +sign_bit=0 +monitorByPosition=false +minSpeed=0.1 diff --git a/devices/eta.properties b/devices/eta.properties index 8dcfd70..b091203 100644 --- a/devices/eta.properties +++ b/devices/eta.properties @@ -1,5 +1,6 @@ -#Thu Aug 22 16:30:36 CEST 2019 +#Fri Mar 10 11:21:22 CET 2023 defaultSpeed=50.0 +description=null estbilizationDelay=0 maxSpeed=50.0 maxValue=189.0 diff --git a/devices/gamma.properties b/devices/gamma.properties index e540ac5..5b8d424 100644 --- a/devices/gamma.properties +++ b/devices/gamma.properties @@ -1,16 +1,17 @@ -#Thu Aug 22 16:30:36 CEST 2019 -defaultSpeed=50.0 -estbilizationDelay=0 -maxSpeed=50.0 -maxValue=164.0 -minSpeed=0.1 -minValue=-61.0 -monitorByPosition=false +#Tue Jun 07 17:34:49 CEST 2022 offset=0.0 +maxValue=164.0 precision=2 -resolution=NaN rotation=false scale=1.0 -sign_bit=0 +description=null +estbilizationDelay=0 +maxSpeed=50.0 +resolution=NaN startRetries=1 +minValue=-61.0 unit=mm +defaultSpeed=50.0 +sign_bit=0 +monitorByPosition=false +minSpeed=0.1 diff --git a/devices/histo.properties b/devices/histo.properties index ff1e6b8..d333a86 100644 --- a/devices/histo.properties +++ b/devices/histo.properties @@ -1,7 +1,8 @@ -#Wed Nov 27 17:20:46 CET 2019 +#Tue Jun 07 17:34:49 CEST 2022 bins=100 -interval=0 -max=150.0 min=80.0 -numberOfSamples=1000 +max=150.0 precision=-1 +description=null +interval=0 +numberOfSamples=1000 diff --git a/devices/image.properties b/devices/image.properties index 88471a5..90114e9 100644 --- a/devices/image.properties +++ b/devices/image.properties @@ -1,25 +1,25 @@ -#Wed Oct 30 11:35:11 CET 2019 -spatialCalOffsetY=NaN -spatialCalOffsetX=NaN +#Thu Nov 10 09:48:10 CET 2022 +colormap=Viridis +colormapAutomatic=true colormapLogarithmic=false -scale=1.0 -grayscale=false -spatialCalScaleX=NaN -spatialCalScaleY=NaN colormapMax=NaN -rescaleOffset=0.0 -roiWidth=-1 -colormap=Grayscale -invert=false colormapMin=NaN +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 rotation=0.0 rotationCrop=false -rescaleFactor=1.0 +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN spatialCalUnits=mm -flipVertically=false -roiHeight=-1 -flipHorizontally=false -colormapAutomatic=false -roiY=0 -roiX=0 transpose=false diff --git a/devices/m1.properties b/devices/m1.properties index e52ab5f..4faeae6 100755 --- a/devices/m1.properties +++ b/devices/m1.properties @@ -1,18 +1,19 @@ -#Thu Nov 07 10:43:19 CET 2019 -defaultSpeed=1.0 -estbilizationDelay=0 -hasEnable=false -homingType=null -maxSpeed=10.0 -maxValue=10.0 -minSpeed=0.1 -minValue=-10.0 -monitorByPosition=false +#Wed Jun 15 15:14:06 CEST 2022 offset=0.0 +maxValue=10.0 precision=2 -resolution=NaN rotation=false scale=1.0 -sign_bit=0 +description=null +estbilizationDelay=0 +maxSpeed=10.0 +resolution=NaN +homingType=null startRetries=1 +minValue=-10.0 unit=mm +defaultSpeed=1.0 +hasEnable=false +sign_bit=0 +monitorByPosition=false +minSpeed=0.1 diff --git a/devices/m2.properties b/devices/m2.properties index 5480605..f6ea5a0 100755 --- a/devices/m2.properties +++ b/devices/m2.properties @@ -1,9 +1,10 @@ -#Tue Oct 29 14:15:33 CET 2019 +#Wed Jun 15 15:14:06 CEST 2022 offset=0.0 maxValue=10.0 precision=4 rotation=false scale=1.0 +description=null estbilizationDelay=0 maxSpeed=10.0 resolution=NaN diff --git a/devices/m3.properties b/devices/m3.properties new file mode 100644 index 0000000..4572867 --- /dev/null +++ b/devices/m3.properties @@ -0,0 +1,17 @@ +#Mon Oct 03 14:50:52 CEST 2022 +defaultSpeed=1.0 +description=null +estbilizationDelay=0 +maxSpeed=10.0 +maxValue=10.0 +minSpeed=0.1 +minValue=-10.0 +monitorByPosition=false +offset=0.0 +precision=2 +resolution=NaN +rotation=false +scale=1.0 +sign_bit=0 +startRetries=1 +unit=mm diff --git a/devices/m4.properties b/devices/m4.properties new file mode 100644 index 0000000..155d291 --- /dev/null +++ b/devices/m4.properties @@ -0,0 +1,17 @@ +#Mon Oct 03 14:53:36 CEST 2022 +defaultSpeed=1.0 +description=null +estbilizationDelay=0 +maxSpeed=10.0 +maxValue=10.0 +minSpeed=0.1 +minValue=-10.0 +monitorByPosition=false +offset=0.0 +precision=2 +resolution=NaN +rotation=false +scale=1.0 +sign_bit=0 +startRetries=1 +unit=mm diff --git a/devices/m5.properties b/devices/m5.properties new file mode 100644 index 0000000..607a382 --- /dev/null +++ b/devices/m5.properties @@ -0,0 +1,17 @@ +#Mon Oct 03 14:54:33 CEST 2022 +defaultSpeed=1.0 +description=null +estbilizationDelay=0 +maxSpeed=10.0 +maxValue=10.0 +minSpeed=0.1 +minValue=-10.0 +monitorByPosition=false +offset=0.0 +precision=2 +resolution=NaN +rotation=false +scale=1.0 +sign_bit=0 +startRetries=1 +unit=mm diff --git a/devices/m6.properties b/devices/m6.properties new file mode 100644 index 0000000..4af44f6 --- /dev/null +++ b/devices/m6.properties @@ -0,0 +1,17 @@ +#Mon Oct 03 17:17:36 CEST 2022 +defaultSpeed=1.0 +description=null +estbilizationDelay=0 +maxSpeed=10.0 +maxValue=10.0 +minSpeed=0.1 +minValue=-10.0 +monitorByPosition=false +offset=0.0 +precision=2 +resolution=NaN +rotation=false +scale=1.0 +sign_bit=0 +startRetries=1 +unit=mm diff --git a/devices/manip.properties b/devices/manip.properties index 195d6c5..b4c907b 100755 --- a/devices/manip.properties +++ b/devices/manip.properties @@ -1,8 +1,9 @@ -#Tue Mar 17 16:26:08 CET 2015 -accessType=ReadWrite -position_pvs=TESTIOC-MA\:RETRACTED|TESTIOC-MA\:YAG |TESTIOC-MA\:NE |TESTIOC-MA\:TRCL|TESTIOC-MA\:SHIELD|TESTIOC-MA\:CLAMP|TESTIOC-MA\:HEATER|TESTIOC-MA\:SAMPLE -positions=Retracted |YAG |Normal emission|Transfer \t | Shield |Clamping screw |Heater screw |Sample access -positions_pvs=asd|zxc -precision=-1 -readback_pv=TESTIOC-MA\:STS -stop_pv=TESTIOC-MA-STOP\:ALL +#Tue Jun 07 17:34:49 CEST 2022 +accessType=ReadWrite +positions_pvs=asd|zxc +precision=-1 +description=null +positions=Retracted |YAG |Normal emission|Transfer \t | Shield |Clamping screw |Heater screw |Sample access +readback_pv=TESTIOC-MA\:STS +position_pvs=TESTIOC-MA\:RETRACTED|TESTIOC-MA\:YAG |TESTIOC-MA\:NE |TESTIOC-MA\:TRCL|TESTIOC-MA\:SHIELD|TESTIOC-MA\:CLAMP|TESTIOC-MA\:HEATER|TESTIOC-MA\:SAMPLE +stop_pv=TESTIOC-MA-STOP\:ALL diff --git a/devices/maser.properties b/devices/maser.properties new file mode 100644 index 0000000..d367a39 --- /dev/null +++ b/devices/maser.properties @@ -0,0 +1,10 @@ +#Thu Sep 09 14:40:03 CEST 2021 +minValue=NaN +unit=null +offset=0.0 +maxValue=NaN +rotation=false +precision=-1 +sign_bit=0 +scale=1.0 +resolution=NaN diff --git a/devices/master.properties b/devices/master.properties index 42f7e5f..54bac11 100755 --- a/devices/master.properties +++ b/devices/master.properties @@ -1,8 +1,26 @@ -#Thu Dec 24 09:57:56 CET 2015 -offsetReadAnalogInput=0 -offsetReadAnalogOutput=0 -offsetReadDigitalInput=0 -offsetReadDigitalOutput=0 -offsetWriteAnalogOutput=0 -offsetWriteDigitalOutput=0 -timeout=1000 +#Tue Jun 07 17:34:49 CEST 2022 +slave2Positions=-2.0|0.22|2.0 +offsetReadDigitalOutput=0 +slave5Positions=null +precision=2 +scale=1.0 +description=null +resolution=NaN +timeout=1000 +offsetWriteAnalogOutput=0 +mode=LINEAR +minValue=-13.0 +sign_bit=0 +masterPositions=-1.0|0.0|2.0 +offsetWriteDigitalOutput=0 +offsetReadDigitalInput=0 +offset=0.0 +maxValue=116.0 +rotation=false +slave4Positions=null +offsetReadAnalogOutput=0 +unit=mm +offsetReadAnalogInput=0 +slave1Positions=-1.5|0.02|1.5 +slave3Positions=-2.5|0.4|2.5 +slave6Positions=null diff --git a/devices/motor.properties b/devices/motor.properties index 8e52640..05df8ca 100755 --- a/devices/motor.properties +++ b/devices/motor.properties @@ -1,18 +1,19 @@ -#Thu Aug 22 16:30:36 CEST 2019 -defaultSpeed=1.0 -estbilizationDelay=0 -hasEnable=true -homingType=Backward -maxSpeed=20.0 -maxValue=75.0 -minSpeed=0.001 -minValue=-5.0 -monitorByPosition=false +#Tue Jun 07 17:34:49 CEST 2022 offset=0.0 +maxValue=100.0 precision=4 -resolution=0.00125 rotation=false scale=1.0 -sign_bit=0 +description=null +estbilizationDelay=0 +maxSpeed=20.0 +resolution=0.00125 +homingType=Backward startRetries=2 +minValue=-100.0 unit=mm +defaultSpeed=1.0 +sign_bit=0 +hasEnable=true +monitorByPosition=false +minSpeed=0.001 diff --git a/devices/motor2.properties b/devices/motor2.properties index 197cf8a..856cebe 100755 --- a/devices/motor2.properties +++ b/devices/motor2.properties @@ -1,22 +1,23 @@ -#Thu Aug 22 16:30:36 CEST 2019 -accessType=ReadWrite -channel=MTEST-GOBBO\:MOT2 -defaultSpeed=0.2 -estbilizationDelay=0 -hasEnable=true -homingDirection=Backward -homingType=Backward -maxSpeed=100.0 -maxValue=100.0 -minSpeed=0.001 -minValue=-100.0 -monitorByPosition=false +#Tue Jun 07 17:34:49 CEST 2022 offset=10.0 -precision=3 -resolution=NaN -rotation=false -scale=2.0 -sign_bit=0 +maxValue=100.0 simulation=false +precision=3 +rotation=false +channel=MTEST-GOBBO\:MOT2 +scale=2.0 +description=null +estbilizationDelay=0 +maxSpeed=100.0 +resolution=NaN +homingType=Backward +accessType=ReadWrite startRetries=1 +minValue=-100.0 unit=null +defaultSpeed=0.2 +homingDirection=Backward +hasEnable=true +sign_bit=0 +monitorByPosition=false +minSpeed=0.001 diff --git a/devices/mt.properties b/devices/mt.properties index 96d7bad..2ab2b3d 100644 --- a/devices/mt.properties +++ b/devices/mt.properties @@ -1,9 +1,10 @@ -#Tue Oct 30 08:49:48 CET 2018 -mirror_x=false -mirror_y=false +#Tue Jun 07 17:34:49 CEST 2022 precision=-1 -roi_height=-1 roi_width=-1 -roi_x=0 -roi_y=0 +mirror_y=false +mirror_x=false +description=null transpose=false +roi_y=0 +roi_height=-1 +roi_x=0 diff --git a/devices/mt1.properties b/devices/mt1.properties index 96d7bad..2ab2b3d 100644 --- a/devices/mt1.properties +++ b/devices/mt1.properties @@ -1,9 +1,10 @@ -#Tue Oct 30 08:49:48 CET 2018 -mirror_x=false -mirror_y=false +#Tue Jun 07 17:34:49 CEST 2022 precision=-1 -roi_height=-1 roi_width=-1 -roi_x=0 -roi_y=0 +mirror_y=false +mirror_x=false +description=null transpose=false +roi_y=0 +roi_height=-1 +roi_x=0 diff --git a/devices/mu.properties b/devices/mu.properties index fe59d0d..4e5f45c 100644 --- a/devices/mu.properties +++ b/devices/mu.properties @@ -1,16 +1,17 @@ -#Thu Aug 22 16:30:36 CEST 2019 -defaultSpeed=0.2 -estbilizationDelay=0 -maxSpeed=50.0 -maxValue=116.0 -minSpeed=0.1 -minValue=-13.0 -monitorByPosition=false +#Tue Jun 07 17:34:49 CEST 2022 offset=0.0 +maxValue=116.0 precision=2 -resolution=NaN rotation=false scale=1.0 -sign_bit=0 +description=null +estbilizationDelay=0 +maxSpeed=50.0 +resolution=NaN startRetries=1 +minValue=-13.0 unit=mm +defaultSpeed=0.2 +sign_bit=0 +monitorByPosition=false +minSpeed=0.1 diff --git a/devices/p1.properties b/devices/p1.properties index ab9746b..21d89dc 100755 --- a/devices/p1.properties +++ b/devices/p1.properties @@ -1,10 +1,11 @@ -#Mon Aug 06 08:57:31 CEST 2018 -maxValue=NaN +#Wed Jun 15 15:14:06 CEST 2022 minValue=NaN -offset=0.0 -precision=-1 -resolution=NaN -rotation=false -scale=1.0 -sign_bit=0 unit=null +offset=0.0 +maxValue=NaN +precision=-1 +rotation=false +sign_bit=0 +scale=1.0 +description=null +resolution=NaN diff --git a/devices/pe.properties b/devices/pe.properties index d7f9bfd..5f4eef2 100755 --- a/devices/pe.properties +++ b/devices/pe.properties @@ -1,11 +1,12 @@ -#Tue Jun 19 17:19:36 CEST 2018 +#Tue Jun 07 17:34:49 CEST 2022 accessType=ReadWrite -maxValue=1000.0 -minValue=0.0 -offset=0.0 -precision=5 -resolution=NaN -rotation=true -scale=1.0 -sign_bit=0 +minValue=-1000.0 unit=mm +offset=0.0 +maxValue=1000.0 +precision=5 +rotation=true +sign_bit=0 +scale=1.0 +description=null +resolution=NaN diff --git a/devices/phi.properties b/devices/phi.properties index 5789fcb..cfda8e1 100644 --- a/devices/phi.properties +++ b/devices/phi.properties @@ -1,16 +1,17 @@ -#Thu Aug 22 16:30:36 CEST 2019 -defaultSpeed=50.0 -estbilizationDelay=0 -maxSpeed=50.0 -maxValue=360.0 -minSpeed=0.1 -minValue=-360.0 -monitorByPosition=false +#Tue Jun 07 17:34:49 CEST 2022 offset=0.0 +maxValue=360.0 precision=2 -resolution=NaN rotation=false scale=1.0 -sign_bit=0 +description=null +estbilizationDelay=0 +maxSpeed=50.0 +resolution=NaN startRetries=1 +minValue=-360.0 unit=mm +defaultSpeed=50.0 +sign_bit=0 +monitorByPosition=false +minSpeed=0.1 diff --git a/devices/pkh1mot.properties b/devices/pkh1mot.properties new file mode 100644 index 0000000..270ae9c --- /dev/null +++ b/devices/pkh1mot.properties @@ -0,0 +1,16 @@ +#Thu Jul 01 09:27:29 CEST 2021 +offset=0.0 +maxValue=10.0 +rotation=false +precision=2 +scale=1.0 +estbilizationDelay=0 +maxSpeed=10.0 +resolution=NaN +startRetries=1 +minValue=-10.0 +unit=mm +defaultSpeed=1.0 +sign_bit=0 +monitorByPosition=false +minSpeed=0.1 diff --git a/devices/proc_data.properties b/devices/proc_data.properties new file mode 100644 index 0000000..b370f9a --- /dev/null +++ b/devices/proc_data.properties @@ -0,0 +1,25 @@ +#Thu Nov 10 13:19:15 CET 2022 +colormap=Flame +colormapAutomatic=false +colormapLogarithmic=false +colormapMax=NaN +colormapMin=NaN +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/proc_image.properties b/devices/proc_image.properties new file mode 100644 index 0000000..f1089d5 --- /dev/null +++ b/devices/proc_image.properties @@ -0,0 +1,25 @@ +#Thu Nov 10 10:04:38 CET 2022 +colormap=Viridis +colormapAutomatic=true +colormapLogarithmic=false +colormapMax=NaN +colormapMin=NaN +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/pv.properties b/devices/pv.properties index 22025fe..651b544 100755 --- a/devices/pv.properties +++ b/devices/pv.properties @@ -1,12 +1,13 @@ -#Tue Jun 19 17:19:36 CEST 2018 -accessType=ReadWrite -channel=TESTIOC\:TESTCALCOUT\:Input -maxValue=180.0 -minValue=-180.0 +#Wed Jun 08 14:15:08 CEST 2022 offset=1.0 -precision=5 -resolution=-1.0 -scale=2.0 -sign_bit=0 +maxValue=1000.0 simulation=false +precision=5 +channel=TESTIOC\:TESTCALCOUT\:Input +scale=2.0 +description=Test Calcout Inopput +resolution=-1.0 +accessType=ReadWrite +minValue=-1000.0 unit=mm +sign_bit=0 diff --git a/devices/sc.properties b/devices/sc.properties index 2f33b5d..fd6e9f3 100755 --- a/devices/sc.properties +++ b/devices/sc.properties @@ -1,33 +1,34 @@ -#Wed Sep 21 16:35:18 CEST 2016 -binning=1 -calOffsetX=NaN -calOffsetY=NaN -calScaleX=NaN -calScaleY=NaN -colormap=Grayscale -colormapAutomatic=true -colormapMax=NaN -colormapMin=NaN -dataMonitoring=true -dataPolling=1000 -flipHorizontally=true -flipVertically=true -grayscale=false -invert=false -pollingBackground=false -pollingInterval=0 -rescaleFactor=1.0 -rescaleOffset=0.0 -roiHeight=-1 -roiWidth=-1 -roiX=0 -roiY=0 -rotation=0.0 -rotationCrop=false -scale=1.0 -spatialCalOffsetX=NaN -spatialCalOffsetY=NaN -spatialCalScaleX=NaN -spatialCalScaleY=NaN -spatialCalUnits=mm -transpose=false +#Wed Sep 22 11:54:38 CEST 2021 +spatialCalOffsetY=NaN +spatialCalOffsetX=NaN +dataPolling=1000 +pollingInterval=0 +colormapLogarithmic=false +scale=1.0 +grayscale=false +calScaleX=NaN +calScaleY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +colormapMax=NaN +rescaleOffset=0.0 +roiWidth=-1 +colormap=Grayscale +pollingBackground=false +invert=false +colormapMin=NaN +rotation=0.0 +rotationCrop=false +binning=1 +rescaleFactor=1.0 +spatialCalUnits=mm +flipVertically=true +roiHeight=-1 +calOffsetX=NaN +flipHorizontally=true +colormapAutomatic=true +dataMonitoring=true +roiY=0 +calOffsetY=NaN +roiX=0 +transpose=false diff --git a/devices/tab.properties b/devices/tab.properties index 4065134..baec9ab 100755 --- a/devices/tab.properties +++ b/devices/tab.properties @@ -1,14 +1,15 @@ -#Thu Dec 17 09:44:30 CET 2015 -accessType=ReadWrite -motor1=0.0 | 1.0 | 2.0 | 0.1 -motor10=null -motor2=0.0 | 1.0 |2.0 | NaN -motor3= -motor4= -motor5= -motor6= -motor7= -motor8= -motor9=null -positions=Park | Ready | Out | Clear -precision=-1 +#Tue Jun 07 17:34:49 CEST 2022 +precision=-1 +description=null +positions=Park | Ready | Out | Clear +motor3= +motor4= +motor1=0.0 | 1.0 | 2.0 | 0.1 +motor2=0.0 | 1.0 |2.0 | NaN +accessType=ReadWrite +motor7= +motor8= +motor5= +motor10=null +motor6= +motor9=null diff --git a/plugins/.DS_Store b/plugins/.DS_Store new file mode 100644 index 0000000..db29d4e Binary files /dev/null and b/plugins/.DS_Store differ diff --git a/plugins/Align_ComplexEdgeFiltering.java b/plugins/Align_ComplexEdgeFiltering.java new file mode 100644 index 0000000..a6d0884 --- /dev/null +++ b/plugins/Align_ComplexEdgeFiltering.java @@ -0,0 +1,154 @@ +import ij.*; +import ij.ImagePlus; +import ij.ImageStack; +import ij.plugin.filter.PlugInFilter; +import ij.process.ImageProcessor; +import ij.plugin.filter.GaussianBlur; +import ij.gui.GenericDialog; + +/** + * This is a template for a plugin that requires one image to + * be opened, and takes it as parameter. + */ +public class Align_ComplexEdgeFiltering implements PlugInFilter { + protected ImagePlus imp; + private static double g_sigma = 3.0, g_resolution = 1e-4; //filter parameters + private static int filter_output; + //private static int filter_type = 0; + private GaussianBlur gb = new GaussianBlur(); + private int[] sobel_r = new int[] {1,0,-1, 2,0,-2, 1,0,-1}; + private int[] sobel_i = new int[] {1,2,1, 0,0,0, -1,-2,-1}; + + String arg; + final java.util.List output = new java.util.ArrayList(); + public java.util.List getOutput(){ + return output; + } + boolean show=true; + + /** + * This method gets called by ImageJ / Fiji to determine + * whether the current image is of an appropriate type. + * + * @param arg can be specified in plugins.config + * @param image is the currently opened image + */ + public int setup(String arg, ImagePlus image) { + this.imp = image; + this.arg = arg; + /* + * The current return value accepts all gray-scale + * images (if you access the pixels with ip.getf(x, y) + * anyway, that works quite well. + * + * It could also be DOES_ALL; you can add "| NO_CHANGES" + * to indicate that the current image will not be + * changed by this plugin. + * + * Beware of DOES_STACKS: this will call the run() + * method with all slices of the current image + * (channels, z-slices and frames, all). Most likely + * not what you want. + */ + return DOES_8G | DOES_16 | DOES_32 | NO_CHANGES;// | DOES_STACKS; + } + + /** + * This method is run when the current image was accepted. + * + * @param ip is the current slice (typically, plugins use + * the ImagePlus set above instead). + */ + public void run(ImageProcessor ip) { + if ((arg !=null) && (!arg.isBlank())){ + String[] tokens = arg.trim().split(","); + g_sigma = Double.valueOf(tokens[0].trim()); + filter_output = Boolean.valueOf(tokens[1].trim().toLowerCase()) ? 0 : 1; + try{ + show = Boolean.valueOf(tokens[2].trim().toLowerCase()); + } catch (Exception ex){ + show = false; + } + } else { + String[] filter_outputs = {"complex", "real"}; + GenericDialog gd = new GenericDialog("Complex Edge Filtering Options:"); + gd.addSlider("Gaussian blur radius", 0, 20.0, g_sigma); + gd.addChoice("Edge filter output:", filter_outputs, filter_outputs[0]); + //String[] edge_filters = {"Sobel"};//, "Frei&Chen"}; + //gd.addChoice("Task:", edge_filters, edge_filters[0]); + gd.showDialog(); // display the dialog; preview runs in the background now + if (gd.wasCanceled()) return; + g_sigma = gd.getNextNumber(); + filter_output = gd.getNextChoiceIndex(); + } + //filter_type = gd.getNextChoiceIndex(); + exec(); + } + + private void exec() { + // display the results + if (filter_output == 1) { + ImagePlus imp_r = imp.createImagePlus(); + ImageStack stack_r = new ImageStack(imp.getWidth(), imp.getHeight()); + + for (int i = 1; i <= imp.getImageStackSize(); i++) { + ImageProcessor ip_r = imp.getStack().getProcessor(i).duplicate().convertToFloat(); + // Gaussian blurring + gb.blurGaussian(ip_r, g_sigma, g_sigma, g_resolution); + // Sobel edge filtering + ip_r.filter(ImageProcessor.FIND_EDGES); + + stack_r.addSlice(imp.getStack().getSliceLabel(i), ip_r); + IJ.showProgress(i, imp.getImageStackSize()); + } + + //real + imp_r.setStack("EdgeReal_" + imp.getTitle(), stack_r); + imp_r.resetDisplayRange(); + if (show){ + imp_r.show(); + imp_r.updateAndDraw(); + } + output.add(imp_r); + + } else { + ImagePlus imp_r = imp.createImagePlus(); + ImageStack stack_r = new ImageStack(imp.getWidth(), imp.getHeight()); + + ImagePlus imp_i = imp.createImagePlus(); + ImageStack stack_i = new ImageStack(imp.getWidth(), imp.getHeight()); + + for (int i = 1; i <= imp.getImageStackSize(); i++) { + ImageProcessor ip_r = imp.getStack().getProcessor(i).duplicate().convertToFloat(); + // Gaussian blurring + gb.blurGaussian(ip_r, g_sigma, g_sigma, g_resolution); + ImageProcessor ip_i = ip_r.duplicate(); + // Sobel edge filtering + ip_r.convolve3x3(sobel_r); + ip_i.convolve3x3(sobel_i); + + stack_r.addSlice(imp.getStack().getSliceLabel(i), ip_r); + stack_i.addSlice(imp.getStack().getSliceLabel(i), ip_i); + IJ.showProgress(i, imp.getImageStackSize()); + } + + //real + imp_r.setStack("EdgeReal_" + imp.getTitle(), stack_r); + imp_r.resetDisplayRange(); + if (show){ + imp_r.show(); + imp_r.updateAndDraw(); + } + output.add(imp_r); + + //imag + imp_i.setStack("EdgeImag_" + imp.getTitle(), stack_i); + imp_i.resetDisplayRange(); + if (show){ + imp_i.show(); + imp_i.updateAndDraw(); + } + output.add(imp_i); + } + } +} \ No newline at end of file diff --git a/plugins/Align_ComputeShifts.java b/plugins/Align_ComputeShifts.java new file mode 100644 index 0000000..0494acc --- /dev/null +++ b/plugins/Align_ComputeShifts.java @@ -0,0 +1,728 @@ +import ij.*; +import ij.process.*; +import ij.gui.*; +import java.awt.*; +import ij.plugin.PlugIn; +import ij.WindowManager; +//import edu.emory.mathcs.jtransforms.fft.*; +//import edu.emory.mathcs.utils.*; +import org.jtransforms.fft.*; +import org.jtransforms.utils.*; +import flanagan.complex.*; +import flanagan.math.*; +import ij.plugin.frame.RoiManager; +import ij.gui.Roi; + + +public class Align_ComputeShifts implements PlugIn { + protected ImagePlus imp_r, imp_i; + protected int reference_slide; + protected Roi roi; + protected int usfac; + protected boolean debug = true; + + public void run(String arg) { + int[] wList = WindowManager.getIDList(); + + if (null == wList) { //there are no images + IJ.error("There must be at least one open image"); + return; + } + + //get all the image titles so they can be shown in the dialog + String[] titles = new String[wList.length+1]; + ImagePlus[] limps = new ImagePlus[wList.length+1]; + + titles[0] = "None"; + limps[0] = null; + for (int i=0, k=1; i m) { + peak[1] = peak[1] - mlarge; + } + if (peak[2] > n) { + peak[2] = peak[2] - nlarge; + } + + //% If upsampling > 2, then refine estimate with matrix multiply DFT + if (this.usfac > 2) { + // %%% DFT computation %%% + // % Initial shift estimate in upsampled grid + double row_shift = Math.round(peak[1]/2.0*this.usfac)/this.usfac; + double col_shift = Math.round(peak[2]/2.0*this.usfac)/this.usfac; + int dftshift = (int)Math.floor(Math.ceil(this.usfac*1.5)/2); // Center of output array at dftshift+1 + // % Matrix multiply DFT around the current shift estimate + ComplexMatrix in = ElementProduct(drifted, ref.conjugate()); + ComplexMatrix nCC = dftups(in, (int)Math.ceil(this.usfac*1.5), (int)Math.ceil(this.usfac*1.5), + dftshift-row_shift*this.usfac, dftshift-col_shift*this.usfac); + nCC = nCC.times(1.0/(m*n*this.usfac*this.usfac)).conjugate(); + // % Locate maximum and map back to original pixel grid + double[] npeak = cFindPeak(nCC); //max_r, max_i, r, c + + ComplexMatrix mrg00 = dftups(ElementProduct(ref, ref.conjugate()),1,1,0,0); + double rg00 = mrg00.getElementReference(0, 0).abs()/(m*n*this.usfac*this.usfac); + ComplexMatrix mrf00 = dftups(ElementProduct(drifted, drifted.conjugate()),1,1,0,0); + double rf00 = mrf00.getElementReference(0, 0).abs()/(m*n*this.usfac*this.usfac); + + npeak[1] = npeak[1] - dftshift; + npeak[2] = npeak[2] - dftshift; + output[0] = Math.sqrt(Math.abs(1.0 - npeak[0]*npeak[0]/(rg00*rf00))); //error + output[1] = Math.atan2(npeak[4], npeak[3]); //diffphase + output[2] = row_shift + npeak[1]/this.usfac; //delta row + output[3] = col_shift + npeak[2]/this.usfac; //delta col + + } else { + // % If upsampling = 2, no additional pixel shift refinement + double rg00 = SumSquareAbs(ref)/(mlarge*nlarge); + double rf00 = SumSquareAbs(drifted)/(mlarge*nlarge); + + output[0] = Math.sqrt(Math.abs(1.0 - peak[0]*peak[0]/(rg00*rf00))); //error + output[1] = Math.atan2(peak[4], peak[3]); //diffphase + output[2] = peak[1]/2.0; //delta row + output[3] = peak[2]/2.0; //delta col + } + + return output; + } + + private double SumSquareAbs(ComplexMatrix m) { + double sum = 0.0; + + for (int j = 0; j < m.getNrow(); j ++){ + for (int i = 0; i < m.getNcol(); i++) { + sum += m.getElementReference(j, i).squareAbs(); + } + } + + return sum; + } + + private double[] cFindPeak(ComplexMatrix m) { + double max = 0.0; + double realmax = 0.0; + double imagmax = 0.0; + int cmax = 0, rmax = 0; + + for (int j = 0; j < m.getNrow(); j ++){ + for (int i = 0; i < m.getNcol(); i++) { + if (m.getElementReference(j, i).abs() > max) { + max = m.getElementReference(j, i).abs(); + realmax = m.getElementReference(j, i).getReal(); + imagmax = m.getElementReference(j, i).getImag(); + rmax = j; + cmax = i; + } + } + } + + double[] res = new double[5]; + res[0] = Math.sqrt(realmax*realmax+imagmax*imagmax); res[1] = rmax; res[2] = cmax; + res[3] = realmax; res[4] = imagmax; + return res; + } + + private ComplexMatrix fftshift(ComplexMatrix in) { + int nc = in.getNcol(); + int nr = in.getNrow(); + + ComplexMatrix out = new ComplexMatrix (nr, nc); + + int midi = (int)Math.floor(nc/2.0); + int offi = (int)Math.ceil(nc/2.0); + int midj = (int)Math.floor(nr/2.0); + int offj = (int)Math.ceil(nr/2.0); + + for (int j = 0; j < nr; j ++){ + for (int i = 0; i < nc; i++) { + if (j < midj) { + if (i < midi) { + out.setElement(j, i, in.getElementReference(j+offj, i+offi)); + } else { + out.setElement(j, i, in.getElementReference(j+offj, i-midi)); + } + } else { + if (i < midi) { + out.setElement(j, i, in.getElementReference(j-midj, i+offi)); + } else { + out.setElement(j, i, in.getElementReference(j-midj, i-midi)); + } + } + } + } + + return out; + } + + private ComplexMatrix ifftshift(ComplexMatrix in) { + int nc = in.getNcol(); + int nr = in.getNrow(); + + ComplexMatrix out = new ComplexMatrix (nr, nc); + + int midi = (int)Math.ceil(nc/2.0); + int offi = (int)Math.floor(nc/2.0); + int midj = (int)Math.ceil(nr/2.0); + int offj = (int)Math.floor(nr/2.0); + + for (int j = 0; j < nr; j ++){ + for (int i = 0; i < nc; i++) { + if (j < midj) { + if (i < midi) { + out.setElement(j, i, in.getElementReference(j+offj, i+offi)); + } else { + out.setElement(j, i, in.getElementReference(j+offj, i-midi)); + } + } else { + if (i < midi) { + out.setElement(j, i, in.getElementReference(j-midj, i+offi)); + } else { + out.setElement(j, i, in.getElementReference(j-midj, i-midi)); + } + } + } + } + + return out; + } + + private Matrix ifftshift(Matrix in) { + int nc = in.getNcol(); + int nr = in.getNrow(); + + Matrix out = new Matrix (nr, nc); + + int midi = (int)Math.ceil(nc/2.0); + int offi = (int)Math.floor(nc/2.0); + int midj = (int)Math.ceil(nr/2.0); + int offj = (int)Math.floor(nr/2.0); + + for (int j = 0; j < nr; j ++){ + for (int i = 0; i < nc; i++) { + if (j < midj) { + if (i < midi) { + out.setElement(j, i, in.getElement(j+offj, i+offi)); + } else { + out.setElement(j, i, in.getElement(j+offj, i-midi)); + } + } else { + if (i < midi) { + out.setElement(j, i, in.getElement(j-midj, i+offi)); + } else { + out.setElement(j, i, in.getElement(j-midj, i-midi)); + } + } + } + } + + return out; + } + + private ComplexMatrix dftups(ComplexMatrix in, int nor, int noc, double roff, double coff) { + // function out=dftups(in,nor,noc,usfac,roff,coff); + // Upsampled DFT by matrix multiplies, can compute an upsampled DFT in just + // a small region. + // usfac Upsampling factor (default usfac = 1) + // [nor,noc] Number of pixels in the output upsampled DFT, in + // units of upsampled pixels (default = size(in)) + // roff, coff Row and column offsets, allow to shift the output array to + // a region of interest on the DFT (default = 0) + // Recieves DC in upper left corner, image center must be in (1,1) + // Loïc Le Guyader - Jun 11, 2011 Java version for ImageJ plugin + // Manuel Guizar - Dec 13, 2007 + // Modified from dftus, by J.R. Fienup 7/31/06 + + // This code is intended to provide the same result as if the following + // operations were performed + // - Embed the array "in" in an array that is usfac times larger in each + // dimension. ifftshift to bring the center of the image to (1,1). + // - Take the FFT of the larger array + // - Extract an [nor, noc] region of the result. Starting with the + // [roff+1 coff+1] element. + + // It achieves this result by computing the DFT in the output array without + // the need to zeropad. Much faster and memory efficient than the + // zero-padded FFT approach if [nor noc] are much smaller than [nr*usfac nc*usfac] + + + int nr = in.getNrow(); + int nc = in.getNcol(); + + // Compute kernels and obtain DFT by matrix products + double amplitude = -2.0*Math.PI/(nc*usfac); + + Matrix u = new Matrix(nc, 1); + for (int i = 0; i < nc; i++) { + u.setElement(i, 0, i - Math.floor(nc/2.0)); + } + u = ifftshift(u); + + Matrix v = new Matrix(1, noc); + for (int i = 0; i < noc; i++) { + v.setElement(0, i, i-coff); + } + + Matrix phase = u.times(v); + ComplexMatrix kernc = new ComplexMatrix(nc, noc); + for (int j = 0; j < nc; j++) { + for (int i = 0; i < noc; i++) { + Complex t = new Complex(); + t.polar(1.0, amplitude*phase.getElement(j, i)); + kernc.setElement(j, i, t); + } + } + //ComplexMatrixPrint(kernc); + + amplitude = -2.0*Math.PI/(nr*usfac); + + Matrix w = new Matrix(nor, 1); + for (int i = 0; i < nor; i++) { + w.setElement(i, 0, i - roff); + } + + Matrix x = new Matrix(1, nr); + for (int i = 0; i < nr; i++) { + x.setElement(0, i, i - Math.floor(nr/2.0)); + } + x = ifftshift(x); + + Matrix nphase = w.times(x); + ComplexMatrix kernr = new ComplexMatrix(nor, nr); + for (int j = 0; j < nor; j++) { + for (int i = 0; i < nr; i++) { + Complex t = new Complex(); + t.polar(1.0, amplitude*nphase.getElement(j, i)); + kernr.setElement(j, i, t); + } + } + //ComplexMatrixPrint(kernr); + + ComplexMatrix out = kernr.times(in.times(kernc)); + + return out; + } + + private double[][] CrossCorrelation(ComplexMatrix ref, ComplexMatrix drifted) { + int h = ref.getNrow(); + int w = ref.getNcol(); + ComplexMatrix b = drifted.conjugate(); + ComplexMatrix res = ElementProduct(ref, b); + + double[][] data = ComplexMatrix_to_FFTArray2D(res); + DoubleFFT_2D fft = new DoubleFFT_2D(h, w); + fft.realInverse(data, true); + + return data; + } + + private ComplexMatrix ElementProduct(ComplexMatrix a, ComplexMatrix b) { + int nr = a.getNrow(); + int nc = a.getNcol(); + + ComplexMatrix res = new ComplexMatrix(nr, nc); + + for(int j = 0; j < nr; j++) { + for(int i = 0; i < nc; i++) { + res.setElement(j, i, a.getElementReference(j, i).times(b.getElementReference(j, i))); + } + } + + return res; + } + + private double[][] ImageProcessor_to_FFTArray2D(ImageProcessor ip) { + + float[] pixels = (float[])ip.getPixels(); + int w = ip.getWidth(); + int h = ip.getHeight(); + double[][] data = new double[h][w]; + + for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + data[j][i] = (double)pixels[j*w + i]; + } + } + + return data; + } + + private double[][] ImageProcessor_to_FFTComplexArray2D(ImageProcessor ip_r, ImageProcessor ip_i) { + + float[] pixels_r = (float[])ip_r.getPixels(); + float[] pixels_i = (float[])ip_i.getPixels(); + int w = ip_r.getWidth(); + int h = ip_r.getHeight(); + double[][] data = new double[h][2*w]; + + for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + data[j][2*i] = (double)pixels_r[j*w + i]; + data[j][2*i+1] = (double)pixels_i[j*w + i]; + } + } + + return data; + } + + private ComplexMatrix FFTArray2D_to_ComplexMatrix(double[][] data, int h, int w) { + + ComplexMatrix m = new ComplexMatrix(h,w); + + for (int j = 0; j < h; j++) { + for (int i = 0; i <= w/2; i++) { + if (j > 0 && i > 0 && i < w/2) { + m.setElement(j,i, new Complex(data[j][2*i], data[j][2*i+1])); + m.setElement(h-j, w-i, new Complex(data[j][2*i], -data[j][2*i+1])); + } + if (j == 0 && i > 0 && i < w/2) { + m.setElement(0, i, new Complex(data[0][2*i], data[0][2*i+1])); + m.setElement(0, w-i, new Complex(data[0][2*i], -data[0][2*i+1])); + } + if (i == 0 && j > 0 && j < h/2) { + m.setElement(j,0, new Complex(data[j][0], data[j][1])); + m.setElement(h-j, 0, new Complex(data[j][0], -data[j][1])); + m.setElement(j, w/2, new Complex(data[h-j][1], -data[h-j][0])); + m.setElement(h-j, w/2, new Complex(data[h-j][1], data[h-j][0])); + } + if (j == 0 && i == 0) { + m.setElement(0, 0, new Complex(data[0][0], 0)); + } + if (j == 0 && i == w/2) { + m.setElement(0, w/2, new Complex(data[0][1], 0)); + } + if (j == h/2 && i == 0) { + m.setElement(h/2, 0, new Complex(data[h/2][0], 0)); + } + if (j == h/2 && i == w/2) { + m.setElement(h/2, w/2, new Complex(data[h/2][1], 0)); + } + } + } + + return m; + } + + private ComplexMatrix FFTComplexArray2D_to_ComplexMatrix(double[][] data, int h, int w) { + + ComplexMatrix m = new ComplexMatrix(h,w); + + for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + m.setElement(j,i, new Complex(data[j][2*i], data[j][2*i+1])); + } + } + + return m; + } + + private double[][] ComplexMatrix_to_FFTArray2D(ComplexMatrix m) { + int w = m.getNcol(); + int h = m.getNrow(); + double[][] data = new double[h][w]; + + for (int j = 0; j < h; j++) { + for (int i = 0; i <= w/2; i++) { + if (j > 0 && i > 0 && i < w/2) { + data[j][2*i] = m.getElementReference(j,i).getReal(); + data[j][2*i+1] = m.getElementReference(j,i).getImag(); + } + if (j == 0 && i > 0 && i < w/2) { + data[0][2*i] = m.getElementReference(0,i).getReal(); + data[0][2*i+1] = m.getElementReference(0,i).getImag(); + } + if (i == 0 && j > 0 && j < h/2) { + data[j][0] = m.getElementReference(j,0).getReal(); + data[j][1] = m.getElementReference(j,0).getImag(); + data[h-j][1] = m.getElementReference(j,w/2).getReal(); + data[h-j][0] = m.getElementReference(h-j,w/2).getImag(); + } + if (j == 0 && i == 0) { + data[0][0] = m.getElementReference(0,0).getReal(); + } + if (j == 0 && i == w/2) { + data[0][1] = m.getElementReference(0,w/2).getReal(); + } + if (j == h/2 && i == 0) { + data[h/2][0] = m.getElementReference(h/2,0).getReal(); + } + if (j == h/2 && i == w/2) { + data[h/2][1] = m.getElementReference(h/2,w/2).getReal(); + } + } + } + + return data; + } + + // convert a Complex Matrix into an 2d real part array data[0][][] + // and 2d imaginary part data[1][][] + private double[][][] ComplexMatrix_to_RealArray2D(ComplexMatrix m) { + int w = m.getNcol(); + int h = m.getNrow(); + double[][][] data = new double[2][h][w]; + + for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + data[0][j][i] = m.getElementReference(j,i).getReal(); + data[1][j][i] = m.getElementReference(j,i).getImag(); + } + } + + return data; + } +} \ No newline at end of file diff --git a/plugins/Align_ComputeShifts2.java b/plugins/Align_ComputeShifts2.java new file mode 100644 index 0000000..c53a0f5 --- /dev/null +++ b/plugins/Align_ComputeShifts2.java @@ -0,0 +1,701 @@ +import ij.*; +import ij.process.*; +import ij.gui.*; +import java.awt.*; +import ij.plugin.PlugIn; +import ij.WindowManager; +//import edu.emory.mathcs.jtransforms.fft.*; +//import edu.emory.mathcs.utils.*; +import org.jtransforms.fft.*; +import org.jtransforms.utils.*; +import flanagan.complex.*; +import flanagan.math.*; +import ij.plugin.frame.RoiManager; +import ij.gui.Roi; + + +public class Align_ComputeShifts2 implements PlugIn { + protected ImagePlus imp_r, imp_i; + protected int reference_slide; + protected Roi roi; + protected int usfac; + protected boolean debug = true; + double[][] shifts; + boolean allShifts; + + public void setup(int upscaleFactor, boolean allShifts, ImagePlus imp_r, ImagePlus imp_i, + int reference_slide, Roi roi) { + if (imp_r==null){ + throw new RuntimeException("Real part image must exist!"); + } + + if (roi==null){ + roi = new Roi(0,0,imp_r.getWidth(), imp_r.getHeight()); + } + Rectangle box = roi.getBounds(); + if (!ConcurrencyUtils.isPowerOf2(box.height) + || !ConcurrencyUtils.isPowerOf2(box.width)) { + throw new RuntimeException("The selected ROI height and with must be a power of 2"); + } + + this.usfac = upscaleFactor; + this.allShifts = allShifts; + this.imp_r = imp_r; + this.imp_i = imp_i; + this.reference_slide=reference_slide; + this.roi = roi; + + } + + public void run(String arg) { + if (allShifts) { + calculateAllShiftsRun(); + + } else { + calculateShiftsRun(); + } + return; + } + + private void calculateShiftsRun() { + // perform the FFT of each slice + + IJ.showStatus("1/2 Perform FFT of each slice"); + ComplexMatrix[] ffts = computeFFT(); + + // calculate shifts + IJ.showStatus("2/2 Calculate shifts between slices"); + shifts = calculateShifts(ffts); + + /* + // save shifts + ShiftsIO sio = new ShiftsIO(); + sio.save(shifts, "directshifts"); + */ + } + + public double[][] getShifts(){ + return shifts; + } + + private void calculateAllShiftsRun() { + // perform the FFT of each slice + IJ.showStatus("1/2 Perform FFT of each slice"); + ComplexMatrix[] ffts = computeFFT(); + + // calculate shifts + IJ.showStatus("2/2 Calculate shifts between slices"); + double[][] shifts = calculateAllShifts(ffts); + // save shifts + ShiftsIO sio = new ShiftsIO(); + sio.save(shifts, "allshifts"); + } + + // perform the FFT of each slice + private ComplexMatrix[] computeFFT() { + + int slices = imp_r.getStackSize(); + + ComplexMatrix[] ffts = new ComplexMatrix[slices]; + for (int i=1; i <= slices; i++) { + if (imp_i == null) { + ImageProcessor ip = imp_r.getStack().getProcessor(i); + ip.setRoi(roi); + ImageProcessor curr = ip.crop().convertToFloat(); + double[][] data = ImageProcessor_to_FFTArray2D(curr); + ffts[i-1] = fft2(data); + } else { + ImageProcessor ip1, ip2; + ip1 = imp_r.getStack().getProcessor(i); + ip1.setRoi(roi); + ImageProcessor curr_r = ip1.crop().convertToFloat(); + ip2 = imp_i.getStack().getProcessor(i); + ip2.setRoi(roi); + ImageProcessor curr_i = ip2.crop().convertToFloat(); + double[][] data = ImageProcessor_to_FFTComplexArray2D(curr_r, curr_i); + ffts[i-1] = cfft2(data); + } + IJ.showProgress(i, slices); + } + + return ffts; + } + + //calculate the shifts between ffts + private double[][] calculateShifts(ComplexMatrix[] ffts) { + + double[][] shifts = new double[ffts.length][6]; + for (int i = 0; i < ffts.length; i++) { + shifts[i][0] = reference_slide; shifts[i][1] = i+1; + double[] temp = DFTRegistration(ffts[reference_slide - 1], ffts[i]); + shifts[i][2] = temp[2]; shifts[i][3] = temp[3]; + shifts[i][4] = temp[0]; shifts[i][5] = temp[1]; + IJ.showProgress(i + 1, ffts.length); + } + return shifts; // [ref, drifted, dr, dc, error, diffphase] + + } + + //calculate all the shifts between ffts + private double[][] calculateAllShifts(ComplexMatrix[] ffts) { + + double[][] shifts = new double[ffts.length*(ffts.length-1)/2][6]; + int id = 0; + for (int i = 0; i < ffts.length-1; i++) { + for (int j = i+1; j < ffts.length; j++) { + shifts[id][0] = i+1; shifts[id][1] = j+1; + double[] temp = DFTRegistration(ffts[i], ffts[j]); + shifts[id][2] = temp[2]; shifts[id][3] = temp[3]; + shifts[id][4] = temp[0]; shifts[id][5] = temp[1]; + id = id + 1; + IJ.showProgress(id + 1, ffts.length*(ffts.length-1)/2); + } + } + + return shifts; // [ref,drifted,dr,dc,error, diffphase] + } + + // compute 2D fft from an image + private ComplexMatrix fft2(double[][] data) { + + int h = data.length; + int w = data[0].length; + DoubleFFT_2D fft = new DoubleFFT_2D(h, w); + + fft.realForward(data); + ComplexMatrix m = FFTArray2D_to_ComplexMatrix(data, h, w); + + return m; + } + + // compute complex 2D fft from an image + private ComplexMatrix cfft2(double[][] data) { + + int h = data.length; + int w = data[0].length; + DoubleFFT_2D fft = new DoubleFFT_2D(h, w/2); + + fft.complexForward(data); + ComplexMatrix m = FFTComplexArray2D_to_ComplexMatrix(data, h, w/2); + + return m; + } + + // compute inverse 2D fft from a complex matrix + private double[][] ifft2(ComplexMatrix m) { + int w = m.getNcol(); + int h = m.getNrow(); + + DoubleFFT_2D fft = new DoubleFFT_2D(h, w); + + double[][] data = ComplexMatrix_to_FFTArray2D(m); + fft.realInverse(data, true); + + return data; + } + + // compute complex inverse 2D fft from a complex matrix + private ComplexMatrix cifft2(ComplexMatrix m) { + int w = m.getNcol(); + int h = m.getNrow(); + + DoubleFFT_2D fft = new DoubleFFT_2D(h, w); + + double[][] data = new double[h][2*w]; + for (int j=0; j m) { + peak[1] = peak[1] - mlarge; + } + if (peak[2] > n) { + peak[2] = peak[2] - nlarge; + } + + //% If upsampling > 2, then refine estimate with matrix multiply DFT + if (this.usfac > 2) { + // %%% DFT computation %%% + // % Initial shift estimate in upsampled grid + double row_shift = Math.round(peak[1]/2.0*this.usfac)/this.usfac; + double col_shift = Math.round(peak[2]/2.0*this.usfac)/this.usfac; + int dftshift = (int)Math.floor(Math.ceil(this.usfac*1.5)/2); // Center of output array at dftshift+1 + // % Matrix multiply DFT around the current shift estimate + ComplexMatrix in = ElementProduct(drifted, ref.conjugate()); + ComplexMatrix nCC = dftups(in, (int)Math.ceil(this.usfac*1.5), (int)Math.ceil(this.usfac*1.5), + dftshift-row_shift*this.usfac, dftshift-col_shift*this.usfac); + nCC = nCC.times(1.0/(m*n*this.usfac*this.usfac)).conjugate(); + // % Locate maximum and map back to original pixel grid + double[] npeak = cFindPeak(nCC); //max_r, max_i, r, c + + ComplexMatrix mrg00 = dftups(ElementProduct(ref, ref.conjugate()),1,1,0,0); + double rg00 = mrg00.getElementReference(0, 0).abs()/(m*n*this.usfac*this.usfac); + ComplexMatrix mrf00 = dftups(ElementProduct(drifted, drifted.conjugate()),1,1,0,0); + double rf00 = mrf00.getElementReference(0, 0).abs()/(m*n*this.usfac*this.usfac); + + npeak[1] = npeak[1] - dftshift; + npeak[2] = npeak[2] - dftshift; + output[0] = Math.sqrt(Math.abs(1.0 - npeak[0]*npeak[0]/(rg00*rf00))); //error + output[1] = Math.atan2(npeak[4], npeak[3]); //diffphase + output[2] = row_shift + npeak[1]/this.usfac; //delta row + output[3] = col_shift + npeak[2]/this.usfac; //delta col + + } else { + // % If upsampling = 2, no additional pixel shift refinement + double rg00 = SumSquareAbs(ref)/(mlarge*nlarge); + double rf00 = SumSquareAbs(drifted)/(mlarge*nlarge); + + output[0] = Math.sqrt(Math.abs(1.0 - peak[0]*peak[0]/(rg00*rf00))); //error + output[1] = Math.atan2(peak[4], peak[3]); //diffphase + output[2] = peak[1]/2.0; //delta row + output[3] = peak[2]/2.0; //delta col + } + + return output; + } + + private double SumSquareAbs(ComplexMatrix m) { + double sum = 0.0; + + for (int j = 0; j < m.getNrow(); j ++){ + for (int i = 0; i < m.getNcol(); i++) { + sum += m.getElementReference(j, i).squareAbs(); + } + } + + return sum; + } + + private double[] cFindPeak(ComplexMatrix m) { + double max = 0.0; + double realmax = 0.0; + double imagmax = 0.0; + int cmax = 0, rmax = 0; + + for (int j = 0; j < m.getNrow(); j ++){ + for (int i = 0; i < m.getNcol(); i++) { + if (m.getElementReference(j, i).abs() > max) { + max = m.getElementReference(j, i).abs(); + realmax = m.getElementReference(j, i).getReal(); + imagmax = m.getElementReference(j, i).getImag(); + rmax = j; + cmax = i; + } + } + } + + double[] res = new double[5]; + res[0] = Math.sqrt(realmax*realmax+imagmax*imagmax); res[1] = rmax; res[2] = cmax; + res[3] = realmax; res[4] = imagmax; + return res; + } + + private ComplexMatrix fftshift(ComplexMatrix in) { + int nc = in.getNcol(); + int nr = in.getNrow(); + + ComplexMatrix out = new ComplexMatrix (nr, nc); + + int midi = (int)Math.floor(nc/2.0); + int offi = (int)Math.ceil(nc/2.0); + int midj = (int)Math.floor(nr/2.0); + int offj = (int)Math.ceil(nr/2.0); + + for (int j = 0; j < nr; j ++){ + for (int i = 0; i < nc; i++) { + if (j < midj) { + if (i < midi) { + out.setElement(j, i, in.getElementReference(j+offj, i+offi)); + } else { + out.setElement(j, i, in.getElementReference(j+offj, i-midi)); + } + } else { + if (i < midi) { + out.setElement(j, i, in.getElementReference(j-midj, i+offi)); + } else { + out.setElement(j, i, in.getElementReference(j-midj, i-midi)); + } + } + } + } + + return out; + } + + private ComplexMatrix ifftshift(ComplexMatrix in) { + int nc = in.getNcol(); + int nr = in.getNrow(); + + ComplexMatrix out = new ComplexMatrix (nr, nc); + + int midi = (int)Math.ceil(nc/2.0); + int offi = (int)Math.floor(nc/2.0); + int midj = (int)Math.ceil(nr/2.0); + int offj = (int)Math.floor(nr/2.0); + + for (int j = 0; j < nr; j ++){ + for (int i = 0; i < nc; i++) { + if (j < midj) { + if (i < midi) { + out.setElement(j, i, in.getElementReference(j+offj, i+offi)); + } else { + out.setElement(j, i, in.getElementReference(j+offj, i-midi)); + } + } else { + if (i < midi) { + out.setElement(j, i, in.getElementReference(j-midj, i+offi)); + } else { + out.setElement(j, i, in.getElementReference(j-midj, i-midi)); + } + } + } + } + + return out; + } + + private Matrix ifftshift(Matrix in) { + int nc = in.getNcol(); + int nr = in.getNrow(); + + Matrix out = new Matrix (nr, nc); + + int midi = (int)Math.ceil(nc/2.0); + int offi = (int)Math.floor(nc/2.0); + int midj = (int)Math.ceil(nr/2.0); + int offj = (int)Math.floor(nr/2.0); + + for (int j = 0; j < nr; j ++){ + for (int i = 0; i < nc; i++) { + if (j < midj) { + if (i < midi) { + out.setElement(j, i, in.getElement(j+offj, i+offi)); + } else { + out.setElement(j, i, in.getElement(j+offj, i-midi)); + } + } else { + if (i < midi) { + out.setElement(j, i, in.getElement(j-midj, i+offi)); + } else { + out.setElement(j, i, in.getElement(j-midj, i-midi)); + } + } + } + } + + return out; + } + + public Matrix times(Matrix amat, Matrix bmat){ + + if(amat.getNumberOfColumns()!=bmat.getNumberOfRows())throw new IllegalArgumentException("Nonconformable matrices"); + + Matrix cmat = new Matrix(amat.getNumberOfRows(), bmat.getNumberOfColumns()); + double [][] aarray = amat.getArrayReference(); + double [][] barray = bmat.getArrayReference(); + double [][] carray = cmat.getArrayReference(); + double sum = 0.0D; + + for(int i=0; i 0 && i > 0 && i < w/2) { + m.setElement(j,i, new Complex(data[j][2*i], data[j][2*i+1])); + m.setElement(h-j, w-i, new Complex(data[j][2*i], -data[j][2*i+1])); + } + if (j == 0 && i > 0 && i < w/2) { + m.setElement(0, i, new Complex(data[0][2*i], data[0][2*i+1])); + m.setElement(0, w-i, new Complex(data[0][2*i], -data[0][2*i+1])); + } + if (i == 0 && j > 0 && j < h/2) { + m.setElement(j,0, new Complex(data[j][0], data[j][1])); + m.setElement(h-j, 0, new Complex(data[j][0], -data[j][1])); + m.setElement(j, w/2, new Complex(data[h-j][1], -data[h-j][0])); + m.setElement(h-j, w/2, new Complex(data[h-j][1], data[h-j][0])); + } + if (j == 0 && i == 0) { + m.setElement(0, 0, new Complex(data[0][0], 0)); + } + if (j == 0 && i == w/2) { + m.setElement(0, w/2, new Complex(data[0][1], 0)); + } + if (j == h/2 && i == 0) { + m.setElement(h/2, 0, new Complex(data[h/2][0], 0)); + } + if (j == h/2 && i == w/2) { + m.setElement(h/2, w/2, new Complex(data[h/2][1], 0)); + } + } + } + + return m; + } + + private ComplexMatrix FFTComplexArray2D_to_ComplexMatrix(double[][] data, int h, int w) { + + ComplexMatrix m = new ComplexMatrix(h,w); + + for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + m.setElement(j,i, new Complex(data[j][2*i], data[j][2*i+1])); + } + } + + return m; + } + + private double[][] ComplexMatrix_to_FFTArray2D(ComplexMatrix m) { + int w = m.getNcol(); + int h = m.getNrow(); + double[][] data = new double[h][w]; + + for (int j = 0; j < h; j++) { + for (int i = 0; i <= w/2; i++) { + if (j > 0 && i > 0 && i < w/2) { + data[j][2*i] = m.getElementReference(j,i).getReal(); + data[j][2*i+1] = m.getElementReference(j,i).getImag(); + } + if (j == 0 && i > 0 && i < w/2) { + data[0][2*i] = m.getElementReference(0,i).getReal(); + data[0][2*i+1] = m.getElementReference(0,i).getImag(); + } + if (i == 0 && j > 0 && j < h/2) { + data[j][0] = m.getElementReference(j,0).getReal(); + data[j][1] = m.getElementReference(j,0).getImag(); + data[h-j][1] = m.getElementReference(j,w/2).getReal(); + data[h-j][0] = m.getElementReference(h-j,w/2).getImag(); + } + if (j == 0 && i == 0) { + data[0][0] = m.getElementReference(0,0).getReal(); + } + if (j == 0 && i == w/2) { + data[0][1] = m.getElementReference(0,w/2).getReal(); + } + if (j == h/2 && i == 0) { + data[h/2][0] = m.getElementReference(h/2,0).getReal(); + } + if (j == h/2 && i == w/2) { + data[h/2][1] = m.getElementReference(h/2,w/2).getReal(); + } + } + } + + return data; + } + + // convert a Complex Matrix into an 2d real part array data[0][][] + // and 2d imaginary part data[1][][] + private double[][][] ComplexMatrix_to_RealArray2D(ComplexMatrix m) { + int w = m.getNcol(); + int h = m.getNrow(); + double[][][] data = new double[2][h][w]; + + for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + data[0][j][i] = m.getElementReference(j,i).getReal(); + data[1][j][i] = m.getElementReference(j,i).getImag(); + } + } + + return data; + } +} \ No newline at end of file diff --git a/plugins/Align_TranslationFilter.java b/plugins/Align_TranslationFilter.java new file mode 100644 index 0000000..2ed978a --- /dev/null +++ b/plugins/Align_TranslationFilter.java @@ -0,0 +1,115 @@ +import ij.plugin.filter.ExtendedPlugInFilter; +import ij.plugin.filter.PlugInFilterRunner; +import ij.plugin.filter.GaussianBlur; +import ij.*; +import ij.process.*; + +import ij.io.OpenDialog; +import ij.io.SaveDialog; +import java.util.ArrayList; +import java.io.IOException; +import java.io.File; +import jmatio.types.*; +import jmatio.io.*; +import ij.gui.GenericDialog; +import ij.IJ; +import ij.Prefs; + +public class Align_TranslationFilter implements ExtendedPlugInFilter { + private double[][] shifts; + private final int flags = (DOES_ALL-DOES_RGB)|DOES_STACKS|NO_CHANGES|FINAL_PROCESSING; + private ImagePlus imp; + private ImagePlus registred; + private ImageStack translated; + private PlugInFilterRunner pifr; + private int nbslices = 0; + private int processed = 0; + + public void setShifts(double[][] shifts){ + this.shifts = shifts; + } + + public double[][] getShifts(){ + return shifts; + } + + public ImagePlus getOutput(){ + return registred; + } + + public void setImp(ImagePlus imp){ + this.imp = imp; + } + + /** + * This method is called by ImageJ for initialization. + * @param arg Unused here. For plugins in a .jar file this argument string can + * be specified in the plugins.config file of the .jar archive. + * @param imp The ImagePlus containing the image (or stack) to process. + * @return The method returns flags (i.e., a bit mask) specifying the + * capabilities (supported formats, etc.) and needs of the filter. + * See PlugInFilter.java and ExtendedPlugInFilter in the ImageJ + * sources for details. + */ + public int setup(String arg, ImagePlus imp) { + System.out.println("Setup " + arg); + if ("final".equals(arg)) { + registred.setStack("REG_" + this.imp.getTitle(), translated); + return DONE; + } else { + if (imp==null ){ + this.imp = imp; + } + return flags; + } + } + + /** Called by ImageJ after setup. */ + public int showDialog(ImagePlus imp, String command, PlugInFilterRunner pfr) { + pifr = pfr; + + //ShiftsIO sio = new ShiftsIO(); + //shifts = sio.load(null, "directshifts"); + //if (shifts == null) return DONE; + + //IJ.register(this.getClass()); // protect static class variables (filter parameters) from garbage collection + //return IJ.setupDialog(imp, flags); // ask whether to process all slices of stack (if a stack) + return flags; + } + + /** Process a FloatProcessor (with the CONVERT_TO_FLOAT flag, ImageJ does the conversion to float). + * Called by ImageJ for each stack slice (when processing a full stack); for RGB also called once for each color. */ + public void run(ImageProcessor ip) { + // translate from shifts + if (Thread.currentThread().isInterrupted()) return; + + int thisone = pifr.getSliceNumber(); + + ImageProcessor nip = ip.duplicate().convertToFloat(); + nip.setInterpolationMethod(ImageProcessor.BICUBIC); + if (shifts.length != nbslices) { + nip.translate(shifts[1][3], shifts[1][2]); // translate all the frame by the + // same shifts + } else { + nip.translate(shifts[thisone-1][3], shifts[thisone-1][2]); + } + + String lbl = imp.getStack().getSliceLabel(thisone); + if (lbl != null) { + translated.addSlice(lbl, nip, thisone - 1); + } else { + translated.addSlice("" + thisone, nip, thisone - 1); + } + translated.deleteSlice(thisone + 1); + + processed++; + IJ.showProgress(processed, nbslices); + } + + /** Called by ImageJ to set the number of calls to run(ip) corresponding to 100% of the progress bar */ + public void setNPasses(int nPasses) { + nbslices = nPasses; + registred = imp.createImagePlus(); + translated = new ImageStack(imp.getWidth(), imp.getHeight(), nbslices); + } +} \ No newline at end of file diff --git a/plugins/Align_TranslationFilter2.java b/plugins/Align_TranslationFilter2.java new file mode 100644 index 0000000..b42d69b --- /dev/null +++ b/plugins/Align_TranslationFilter2.java @@ -0,0 +1,91 @@ +import ij.plugin.filter.PlugInFilter; +import ij.plugin.filter.PlugInFilterRunner; +import ij.plugin.filter.GaussianBlur; +import ij.*; +import ij.process.*; +import com.jmatio.types.*; +import com.jmatio.io.*; + +public class Align_TranslationFilter2 implements PlugInFilter { + private final int flags = (DOES_ALL-DOES_RGB)|DOES_STACKS|NO_CHANGES|FINAL_PROCESSING; + private ImagePlus imp; + private ImagePlus registred; + private ImageStack translated; + private int nbslices = 0; + private int processed = 0; + + double[][] shifts; + + public void setShifts(double[][] shifts){ + this.shifts = shifts; + } + + public double[][] getShifts(){ + return this.shifts; + } + + + + /** + * This method is called by ImageJ for initialization. + * @param arg Unused here. For plugins in a .jar file this argument string can + * be specified in the plugins.config file of the .jar archive. + * @param imp The ImagePlus containing the image (or stack) to process. + * @return The method returns flags (i.e., a bit mask) specifying the + * capabilities (supported formats, etc.) and needs of the filter. + * See PlugInFilter.java and ExtendedPlugInFilter in the ImageJ + * sources for details. + */ + + public int setup(String arg, ImagePlus imp) { + nbslices = imp.getImageStackSize(); + registred = imp.createImagePlus(); + translated = new ImageStack(imp.getWidth(), imp.getHeight(), nbslices); + this.imp = imp; + + + if (shifts == null) return DONE; + //int ret = IJ.setupDialog(imp, flags); // ask whether to process all slices of stack (if a stack) + return flags; + } + + public ImagePlus getRegistred(){ + return registred; + } + + public ImageStack getTranslated(){ + return translated; + } + + /** Process a FloatProcessor (with the CONVERT_TO_FLOAT flag, ImageJ does the conversion to float). + * Called by ImageJ for each stack slice (when processing a full stack); for RGB also called once for each color. */ + public void run(ImageProcessor ip) { + + for (int slice =1; slice<= nbslices; slice++){ + if (Thread.currentThread().isInterrupted()) return; + + ImageProcessor nip = ip.duplicate().convertToFloat(); + nip.setInterpolationMethod(ImageProcessor.BICUBIC); + if (shifts.length != nbslices) { + nip.translate(shifts[1][3], shifts[1][2]); // translate all the frame by the + // same shifts + } else { + nip.translate(shifts[slice-1][3], shifts[slice-1][2]); + } + + String lbl = imp.getStack().getSliceLabel(slice); + if (lbl != null) { + translated.addSlice(lbl, nip, slice - 1); + } else { + translated.addSlice("" + slice, nip, slice - 1); + } + translated.deleteSlice(slice + 1); + + processed++; + IJ.showProgress(processed, nbslices); + } + registred.setStack("REG_" + imp.getTitle(), translated); + + } + +} \ No newline at end of file diff --git a/plugins/EnergyScan.form b/plugins/EnergyScan.form index c98bea0..759c47f 100755 --- a/plugins/EnergyScan.form +++ b/plugins/EnergyScan.form @@ -1,588 +1,588 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/MXSC-1.15.0.jar b/plugins/MXSC-1.15.0.jar new file mode 100644 index 0000000..50bdac0 Binary files /dev/null and b/plugins/MXSC-1.15.0.jar differ diff --git a/plugins/ManipulatorScan.form b/plugins/ManipulatorScan.form index 8a402ec..b2dde9b 100755 --- a/plugins/ManipulatorScan.form +++ b/plugins/ManipulatorScan.form @@ -510,6 +510,7 @@ + @@ -528,6 +529,8 @@ + + @@ -556,6 +559,14 @@ + + + + + + + + diff --git a/plugins/ManipulatorScan.java b/plugins/ManipulatorScan.java index ee918a9..7a648ad 100755 --- a/plugins/ManipulatorScan.java +++ b/plugins/ManipulatorScan.java @@ -1,15 +1,19 @@ /* * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. - */ + */ import ch.psi.pshell.device.Motor; import ch.psi.pshell.ui.Panel; +import ch.psi.pshell.ui.ScriptProcessor; import ch.psi.pshell.ui.Plugin; +import ch.psi.pshell.ui.QueueProcessor; import ch.psi.utils.State; import ch.psi.utils.swing.SwingUtils; import java.awt.Component; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JCheckBox; @@ -18,7 +22,7 @@ import javax.swing.SpinnerNumberModel; /** * */ -public class ManipulatorScan extends Panel { +public class ManipulatorScan extends ScriptProcessor { public ManipulatorScan() { initComponents(); @@ -64,8 +68,14 @@ public class ManipulatorScan extends Panel { void updateTable(){ } - - void startScan() throws Exception { + + @Override + public String getScript() { + return "ManipulatorScan"; + } + + @Override + public Map getArgs(){ HashMap args = new HashMap<>(); args.put("MOTOR", comboMotor.getSelectedItem().toString()); ArrayList sensors = new ArrayList(); @@ -89,45 +99,10 @@ public class ManipulatorScan extends Panel { } args.put("LATENCY", (Double) spinnerLatency.getValue()); args.put("RELATIVE", radioRelative.isSelected()); - - runAsync("ManipulatorScan", args); - - /* - getContext().setExecutingContext("manip_scan"); - String scan ="lscan(" + comboMotor.getSelectedItem().toString() + ", ( " ; - for (Component c : panelSensors.getComponents()) { - if ((c instanceof JCheckBox) && ((JCheckBox)c).isSelected()) - scan += c.getName() + ", "; - } - scan+="), "; - if (radioRelative.isSelected()){ - double halfRange = (Double)spinnerRange.getValue()/2; - scan+= (-halfRange) + ", " + (halfRange)+ ", "; - } else { - Double from = (Double)spinnerFrom.getValue(); - Double to = (Double)spinnerTo.getValue(); - - if (to <= from){ - throw new Exception ("Invalid range"); - } - scan+= from + ", " + to + ", "; - } - - scan+= (radioStepSize.isSelected()) ? "(" +((Double)spinnerStepSize.getValue())+",)" :((Integer)spinnerSteps.getValue()); - scan+=", " + (Double)spinnerLatency.getValue() + ", "; - if (radioRelative.isSelected()){ - scan+="True, "; //Relative - } - scan+="before_read=trig_scienta)"; //Relative - - if (checkImageIntegration.isSelected()){ - scan = "set_preference(Preference.PLOT_TYPES,{'integration':1}); " + scan; - } - - evalAsync(scan); - */ + return args; } + @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { @@ -173,6 +148,7 @@ public class ManipulatorScan extends Panel { buttonStart = new javax.swing.JButton(); buttonAbort = new javax.swing.JButton(); jButton1 = new javax.swing.JButton(); + buttonAddToQueue = new javax.swing.JButton(); panelPositioner.setBorder(javax.swing.BorderFactory.createTitledBorder("Positioner")); @@ -473,6 +449,13 @@ public class ManipulatorScan extends Panel { jButton1.setText("jButton1"); + buttonAddToQueue.setText("Add To Queue"); + buttonAddToQueue.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonAddToQueueActionPerformed(evt); + } + }); + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); jPanel3.setLayout(jPanel3Layout); jPanel3Layout.setHorizontalGroup( @@ -481,7 +464,8 @@ public class ManipulatorScan extends Panel { .addContainerGap() .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(buttonStart, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(buttonAbort, javax.swing.GroupLayout.DEFAULT_SIZE, 244, Short.MAX_VALUE)) + .addComponent(buttonAbort, javax.swing.GroupLayout.DEFAULT_SIZE, 244, Short.MAX_VALUE) + .addComponent(buttonAddToQueue, javax.swing.GroupLayout.DEFAULT_SIZE, 244, Short.MAX_VALUE)) .addContainerGap()) .addGroup(jPanel3Layout.createSequentialGroup() .addGap(21, 21, 21) @@ -496,6 +480,8 @@ public class ManipulatorScan extends Panel { .addGap(18, 18, 18) .addComponent(buttonAbort) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonAddToQueue) + .addGap(36, 36, 36) .addComponent(jButton1) .addGap(143, 143, 143)) ); @@ -538,7 +524,7 @@ public class ManipulatorScan extends Panel { private void buttonStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStartActionPerformed try { - startScan(); + execute(); } catch (Exception ex) { SwingUtils.showException(this, ex); } @@ -566,7 +552,7 @@ public class ManipulatorScan extends Panel { //spinnerFrom.setModel(new javax.swing.SpinnerNumberModel(3.0, 0.001, 100.0, 1.0)); //spinnerTo.setModel(new javax.swing.SpinnerNumberModel(2.0, 0.001, 100.0, 1.0)); } catch (Exception ex) { - SwingUtils.showException(this, ex); + showException(ex); } }//GEN-LAST:event_comboMotorActionPerformed @@ -574,8 +560,20 @@ public class ManipulatorScan extends Panel { setEnabled(isEnabled()); }//GEN-LAST:event_radioAbsoluteActionPerformed + private void buttonAddToQueueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAddToQueueActionPerformed + try { + List queues = getView().getQueues(); + QueueProcessor tq = (queues.size() == 0) ? getView().openProcessor(QueueProcessor.class, null) : queues.get(0); + getView().getDocumentsTab().setSelectedComponent(tq); + tq.addNewFile(getScript(), getArgs()); + } catch (Exception ex) { + showException( ex); + } + }//GEN-LAST:event_buttonAddToQueueActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton buttonAbort; + private javax.swing.JButton buttonAddToQueue; private javax.swing.ButtonGroup buttonGroup1; private javax.swing.ButtonGroup buttonGroup2; private javax.swing.JButton buttonScientaSetup; @@ -617,4 +615,5 @@ public class ManipulatorScan extends Panel { private javax.swing.JSpinner spinnerTo; private javax.swing.JLabel txtSize; // End of variables declaration//GEN-END:variables + } diff --git a/plugins/PanelPlugin.form b/plugins/PanelPlugin.form index 0fbdc12..c52670e 100755 --- a/plugins/PanelPlugin.form +++ b/plugins/PanelPlugin.form @@ -22,39 +22,51 @@ - + - - - - - - + + + + + + + + + + + + + + + + - - - + - - + + + + + + - - - - + - - + + + + + - + @@ -62,10 +74,7 @@ - - - - + @@ -73,17 +82,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + @@ -166,5 +195,19 @@ + + + + + + + + + + + + + + diff --git a/plugins/PanelPlugin.java b/plugins/PanelPlugin.java index b40099e..52e9fab 100755 --- a/plugins/PanelPlugin.java +++ b/plugins/PanelPlugin.java @@ -3,9 +3,14 @@ */ import ch.psi.pshell.core.Context; +import ch.psi.pshell.epics.ChannelDouble; +import ch.psi.pshell.epics.GenericChannel; +import ch.psi.pshell.plot.Plot; +import ch.psi.pshell.swing.DevicePanel; import ch.psi.pshell.ui.Panel; import ch.psi.utils.State; import java.awt.Component; +import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JButton; @@ -18,13 +23,29 @@ public class PanelPlugin extends Panel { public PanelPlugin() { initComponents(); this.setPersistedComponents(new Component[]{jRadioButton1, jRadioButton2}); + line.getAxis(Plot.AxisId.Y).setLabel("LinePlot"); + time.getAxis(Plot.AxisId.Y).setLabel("TimePlot"); + time.setTitle("Test"); + } //Overridables + @Override public void onInitialize(int runCount) { - + DevicePanel[] panels = new DevicePanel[]{panelSetp, panelRbck}; + for (DevicePanel p : panels){ + GenericChannel channel = new GenericChannel(p.getName(), p.getName(), 3); + channel.setMonitored(true); + try { + channel.initialize(); + p.setDevice(channel); + } catch (Exception ex) { + Logger.getLogger(PanelPlugin.class.getName()).log(Level.SEVERE, null, ex); + } + } } + @Override public void onStateChange(State state, State former) { @@ -56,6 +77,10 @@ public class PanelPlugin extends Panel { jRadioButton2 = new javax.swing.JRadioButton(); buttonExecShellCmd = new javax.swing.JButton(); jButton2 = new javax.swing.JButton(); + line = new ch.psi.pshell.plot.LinePlotJFree(); + time = new ch.psi.pshell.plot.TimePlotJFree(); + panelSetp = new ch.psi.pshell.swing.RegisterPanel(); + panelRbck = new ch.psi.pshell.swing.DeviceValuePanel(); motorPanel2.setDeviceName("m1"); @@ -90,6 +115,10 @@ public class PanelPlugin extends Panel { jButton2.setText("Exec Sync"); + panelSetp.setName("TESTIOC:TESTCALCOUT:Input"); // NOI18N + + panelRbck.setName("TESTIOC:TESTCALCOUT:Input"); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -100,52 +129,76 @@ public class PanelPlugin extends Panel { .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(scriptButton2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(motorPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jSpinner2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jSpinner3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(scriptButton1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(motorPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jSpinner2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(buttonExecShellCmd) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jRadioButton2) + .addComponent(jRadioButton1))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jSpinner3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))) .addGroup(layout.createSequentialGroup() - .addGap(36, 36, 36) + .addGap(86, 86, 86) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jRadioButton2) - .addComponent(jRadioButton1)))) - .addContainerGap(168, Short.MAX_VALUE)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(panelSetp, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelRbck, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(scriptButton1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jButton2) - .addComponent(buttonExecShellCmd)) - .addGap(225, 225, 225)) + .addComponent(line, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(time, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(scriptButton1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(motorPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(motorPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(scriptButton2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSpinner2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jSpinner3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGap(21, 21, 21) + .addComponent(jRadioButton1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jRadioButton2) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonExecShellCmd) + .addComponent(jButton2)))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panelSetp, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelRbck, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(44, 44, 44) + .addComponent(scriptButton1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(25, 25, 25)) + .addGroup(layout.createSequentialGroup() + .addComponent(line, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jSpinner3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(jRadioButton1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jRadioButton2) - .addGap(18, 18, 18) - .addComponent(buttonExecShellCmd) - .addGap(18, 18, 18) - .addComponent(jButton2) - .addContainerGap(35, Short.MAX_VALUE)) + .addComponent(time, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 12, Short.MAX_VALUE)) ); + + layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {panelRbck, panelSetp}); + }// //GEN-END:initComponents private void buttonExecShellCmdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonExecShellCmdActionPerformed @@ -178,8 +231,12 @@ public class PanelPlugin extends Panel { private javax.swing.JSpinner jSpinner1; private javax.swing.JSpinner jSpinner2; private javax.swing.JSpinner jSpinner3; + private ch.psi.pshell.plot.LinePlotJFree line; private ch.psi.pshell.swing.MotorPanel motorPanel2; + private ch.psi.pshell.swing.DeviceValuePanel panelRbck; + private ch.psi.pshell.swing.RegisterPanel panelSetp; private ch.psi.pshell.swing.ScriptButton scriptButton1; private ch.psi.pshell.swing.ScriptButton scriptButton2; + private ch.psi.pshell.plot.TimePlotJFree time; // End of variables declaration//GEN-END:variables } diff --git a/plugins/README b/plugins/README new file mode 100644 index 0000000..501c79a --- /dev/null +++ b/plugins/README @@ -0,0 +1,5 @@ +This plugin for the analysis of PEEM images requires the following additional +libraries: +JTransform, http://sites.google.com/site/piotrwendykier/software/jtransforms +Michael Thomas Flanagan's Java Scientific Library, http://www.ee.ucl.ac.uk/~mflanaga/java/ +JMatIO, http://www.mathworks.com/matlabcentral/fileexchange/10759 diff --git a/plugins/Regine.form b/plugins/Regine.form index 027950d..73438ee 100644 --- a/plugins/Regine.form +++ b/plugins/Regine.form @@ -297,6 +297,9 @@ + + + diff --git a/plugins/Regine.java b/plugins/Regine.java index dd86ad4..c759858 100644 --- a/plugins/Regine.java +++ b/plugins/Regine.java @@ -212,6 +212,8 @@ public class Regine extends ScriptProcessor { jLabel11.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); jLabel11.setText("Exposures(s):"); + checkZigZag.setSelected(true); + jLabel12.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); jLabel12.setText("ZigZag:"); diff --git a/plugins/SIStem.form b/plugins/SIStem.form new file mode 100644 index 0000000..18399ae --- /dev/null +++ b/plugins/SIStem.form @@ -0,0 +1,395 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
diff --git a/plugins/SIStem.java b/plugins/SIStem.java new file mode 100644 index 0000000..519c0f8 --- /dev/null +++ b/plugins/SIStem.java @@ -0,0 +1,813 @@ +import ch.psi.pshell.core.JsonSerializer; +import ch.psi.pshell.device.Positioner; +import ch.psi.pshell.ui.Panel; +import ch.psi.pshell.ui.PanelProcessor; +import ch.psi.pshell.ui.QueueProcessor; +import ch.psi.utils.Arr; +import ch.psi.utils.IO; +import ch.psi.utils.State; +import ch.psi.utils.swing.SwingUtils; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.DropMode; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JTable; +import javax.swing.TransferHandler; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.DefaultTableModel; + +/** + * + */ +public class SIStem extends PanelProcessor { + File currentFile; + final DefaultTableModel modelInactive; + final DefaultTableModel modelFixed; + final DefaultTableModel modelScanned; + + + public static final String FILE_EXTENSION = "json"; + + public SIStem() { + initComponents(); + modelInactive = (DefaultTableModel) tableInactive.getModel(); + modelFixed = (DefaultTableModel) tableFixed.getModel(); + modelScanned = (DefaultTableModel) tableScanned.getModel(); + clear(); + Standard st = new Standard(); st.run(); + + + abstract class PositinerTransferHandler extends TransferHandler{ + @Override + public int getSourceActions(JComponent c) { + return DnDConstants.ACTION_COPY_OR_MOVE; + } + @Override + public Transferable createTransferable(JComponent comp) { + try{ + JTable table = (JTable) comp; + return new StringSelection((String) table.getModel().getValueAt(table.getSelectedRow(),0)); + } catch(Exception ex){ + return null; + } + } + @Override + public boolean canImport(TransferHandler.TransferSupport support) { + return support.isDataFlavorSupported(DataFlavor.stringFlavor); + } + @Override + public boolean importData(TransferHandler.TransferSupport support) { + if (support.isDrop() && canImport(support)) { + try { + JTable.DropLocation dl = (JTable.DropLocation)support.getDropLocation(); + String name = (String) support.getTransferable().getTransferData(DataFlavor.stringFlavor); + Positioner pos = getContext().getDevicePool().getByName(name, Positioner.class); + DefaultTableModel model = ((DefaultTableModel)((JTable)support.getComponent()).getModel()); + addPositioner(pos, model, dl.getRow(), getRowData(pos)); + } catch (Exception ex) { + return false; + } + } + return true; + } + abstract Object[] getRowData(Positioner pos); + }; + + tableInactive.setDragEnabled(true); + tableInactive.setDropMode(DropMode.INSERT_ROWS); + tableInactive.setFillsViewportHeight(true); + tableInactive.setTransferHandler(new PositinerTransferHandler() { + @Override + Object[] getRowData(Positioner pos) { + return new Object[]{pos.getName()}; + } + }); + + tableFixed.setDragEnabled(true); + tableFixed.setDropMode(DropMode.INSERT_ROWS); + tableFixed.setFillsViewportHeight(true); + tableFixed.setTransferHandler(new PositinerTransferHandler() { + @Override + Object[] getRowData(Positioner pos) { + return new Object[]{pos.getName(), Double.NaN, pos.getUnit()}; + } + }); + + tableScanned.setDragEnabled(true); + tableScanned.setDropMode(DropMode.INSERT_ROWS); + tableScanned.setFillsViewportHeight(true); + tableScanned.setTransferHandler(new PositinerTransferHandler() { + @Override + Object[] getRowData(Positioner pos) { + return new Object[]{pos.getName(), Double.NaN, Double.NaN, 0, Double.NaN, pos.getUnit()}; + } + }); + } + + void addPositioner(Positioner pos, DefaultTableModel model, int row, Object[] data){ + if (row<0){ + row = model.getRowCount(); + } + model.insertRow(row, data); + removePositioner(pos, modelInactive, (model==modelInactive) ? row : -1); + removePositioner(pos, modelFixed, (model==modelFixed) ? row : -1); + removePositioner(pos, modelScanned, (model==modelScanned) ?row : -1); + } + + void removePositioner(Positioner pos, DefaultTableModel model, int except){ + for (int i=0; i< model.getRowCount(); i++){ + if ((except<0) || (i!=except)){ + if (model.getValueAt(i, 0).equals(pos.getName())){ + model.removeRow(i); + break; + } + } + } + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + + } + + + @Override + public void onStateChange(State state, State former) { + updateControls(); + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + + //Callback to perform update - in event thread + @Override + protected void doUpdate() { + } + + + @Override + public String getFileName(){ + return (currentFile==null) ? null : currentFile.toString(); + } + + @Override + public boolean isTabNameUpdated() { + return false; + } + + @Override + public String getType() { + return "SIStem"; + } + + @Override + public boolean createMenuNew() { + return true; + } + + @Override + public boolean createFilePanel() { + return true; + } + + @Override + public String getDescription() { + return "SIStem Scan definition file (*." + FILE_EXTENSION + ")"; + } + + @Override + public String[] getExtensions() { + return new String[]{FILE_EXTENSION}; + } + + @Override + public String getHomePath() { + return "{home}/scans"; + } + + @Override + public void saveAs(String fileName) throws IOException { + currentFile = new File(fileName); + Map preActions = new HashMap(); + for (int i=0; i< modelFixed.getRowCount(); i++){ + preActions.put(modelFixed.getValueAt(i, 0), modelFixed.getValueAt(i, 1)); + } + String[] positioners = new String[modelScanned.getRowCount()]; + Double[] start = new Double[modelScanned.getRowCount()]; + Double[] stop = new Double[modelScanned.getRowCount()]; + Integer[] steps = new Integer[modelScanned.getRowCount()]; + for (int i=0; i< modelScanned.getRowCount(); i++){ + positioners[i] = (String) modelScanned.getValueAt(i, 0); + start[i] = (Double) modelScanned.getValueAt(i, 1); + stop[i] = (Double) modelScanned.getValueAt(i, 2); + steps[i] = (Integer) modelScanned.getValueAt(i, 3) -1; + } + + Map config = new HashMap(); + config.put("PRE_ACTIONS", preActions); + config.put("POSITIONERS", positioners); + config.put("START", start); + config.put("STOP", stop); + config.put("STEPS", steps); + + //TODO: + config.put("SENSORS", Arr.toList(new String[]{"scienta.dataMatrix", "sin"})); + config.put("SETTLING_TIME", spinnerLatency.getValue() ); + config.put("PASSES", spinnerPasses.getValue()); + config.put("ZIGZAG", checkZigzag.isSelected()); + config.put("COMPRESSION", true); + + String json = JsonSerializer.encode(config, true); + Files.write(currentFile.toPath(), json.getBytes()); + updateControls(); + } + + @Override + public void open(String fileName) throws IOException { + clear(); + if (fileName!=null){ + Path path = Paths.get(fileName); + String json = new String(Files.readAllBytes(path)); + currentFile = path.toFile(); + Map config = (Map) JsonSerializer.decode(json, Map.class); + + Map preActions = (Map) config.get("PRE_ACTIONS"); + + List positioners = (List)config.get("POSITIONERS"); + List start = (List)config.get("START"); + List stop = (List)config.get("STOP"); + List steps = (List) config.get("STEPS"); + + for (String name:preActions.keySet()){ + Positioner pos = getContext().getDevicePool().getByName(name, Positioner.class); + if (pos!=null){ + addPositioner(pos, modelFixed, -1, new Object[]{name, preActions.get(name), pos.getUnit()}); + } + } + for (int i=0; i< positioners.size(); i++){ + String name = positioners.get(i); + Positioner pos = getContext().getDevicePool().getByName(name, Positioner.class); + if (pos!=null){ + addPositioner(pos, modelScanned, -1, new Object[]{name, start.get(i), stop.get(i), steps.get(i), 0, pos.getUnit()}); + } + } + spinnerLatency.setValue(config.get("SETTLING_TIME")); + spinnerPasses.setValue(config.get("PASSES")); + checkZigzag.setSelected((Boolean) config.get("ZIGZAG")); + } + updateControls(); + } + + public void clear(){ + currentFile = null; + modelInactive.setRowCount(0); + modelFixed.setRowCount(0); + modelScanned.setRowCount(0); + Positioner[] positioners = getContext().getDevicePool().getAllDevicesOrderedByName(Positioner.class); + for (Positioner pos: positioners){ + modelInactive.addRow(new Object[]{pos.getName()}); + } + updateControls(); + } + + @Override + public void execute() throws Exception { + checkValues(); + + HashMap args = new HashMap(); + if (currentFile == null) { + throw new Exception("TODO"); + } + args.put("NAME", getScanName()); + + this.runAsync("SIStem", args).handle((ret, ex) -> { + if (ex != null) { + } + try { + } catch (Exception e) { + Logger.getLogger(SIStem.class.getName()).log(Level.SEVERE, null, e); + } + return ret; + }); + + } + + String getScanName() { + if (currentFile != null) { + return IO.getPrefix(currentFile); + } + return null; + } + + void updateControls() { + State state = getState(); + try { + textFileId.setText(String.valueOf(getContext().getFileSequentialNumber())); + } catch (Exception ex) { + textFileId.setText(""); + } + + String fileName = getFileName(); + if (fileName == null){ + textFile.setText(""); + } else { + String home = getContext().getSetup().expandPath(getHomePath()); + if (IO.isSubPath(fileName, home)) { + fileName = IO.getRelativePath(fileName, home); + } + textFile.setText(fileName); + } + + buttonStart.setEnabled((state == State.Ready) && (currentFile != null)); + buttonAddToQueue.setEnabled((state == State.Ready) && (currentFile != null)); + buttonAbort.setEnabled(state.isProcessing()); + buttonScienta.setEnabled(state.isInitialized()); + + } + + void checkValues(){ + for (int i=0; i< modelFixed.getRowCount(); i++){ + if (Double.isNaN((Double)modelFixed.getValueAt(i, 1))){ + throw new IllegalArgumentException("Invalid value for " + modelFixed.getValueAt(i, 0)); + } + } + for (int i=0; i< modelScanned.getRowCount(); i++){ + if (Double.isNaN((Double)modelScanned.getValueAt(i, 1))){ + throw new IllegalArgumentException("Invalid start for " + modelFixed.getValueAt(i, 0)); + } + if (Double.isNaN((Double)modelScanned.getValueAt(i, 2))){ + throw new IllegalArgumentException("Invalid stop for " + modelFixed.getValueAt(i, 0)); + } + if (((Integer)modelScanned.getValueAt(i, 3)) < 1){ + throw new IllegalArgumentException("Invalid points for " + modelFixed.getValueAt(i, 0)); + } + } + } + + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + buttonScienta = new javax.swing.JButton(); + jLabel2 = new javax.swing.JLabel(); + textFileId = new javax.swing.JTextField(); + buttonResetId = new javax.swing.JButton(); + buttonStart = new javax.swing.JButton(); + buttonAbort = new javax.swing.JButton(); + jPanel2 = new javax.swing.JPanel(); + buttonOpen = new javax.swing.JButton(); + buttonSave = new javax.swing.JButton(); + jLabel3 = new javax.swing.JLabel(); + textFile = new javax.swing.JTextField(); + buttonClear = new javax.swing.JButton(); + jPanel1 = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + tableInactive = new javax.swing.JTable(); + jScrollPane2 = new javax.swing.JScrollPane(); + tableFixed = new javax.swing.JTable(); + jScrollPane3 = new javax.swing.JScrollPane(); + tableScanned = new javax.swing.JTable(); + jLabel1 = new javax.swing.JLabel(); + spinnerPasses = new javax.swing.JSpinner(); + checkZigzag = new javax.swing.JCheckBox(); + jLabel4 = new javax.swing.JLabel(); + spinnerLatency = new javax.swing.JSpinner(); + buttonAddToQueue = new javax.swing.JButton(); + + buttonScienta.setText("Scienta Panel"); + buttonScienta.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonScientaActionPerformed(evt); + } + }); + + jLabel2.setText("File ID:"); + + textFileId.setEditable(false); + textFileId.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + buttonResetId.setText("Reset"); + buttonResetId.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonResetIdActionPerformed(evt); + } + }); + + buttonStart.setText("Start"); + buttonStart.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonStartActionPerformed(evt); + } + }); + + buttonAbort.setText("Abort"); + buttonAbort.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonAbortActionPerformed(evt); + } + }); + + jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Parameters")); + + buttonOpen.setText("Open"); + buttonOpen.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonOpenActionPerformed(evt); + } + }); + + buttonSave.setText("Save"); + buttonSave.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonSaveActionPerformed(evt); + } + }); + + jLabel3.setText("File:"); + + textFile.setDisabledTextColor(javax.swing.UIManager.getDefaults().getColor("TextField.foreground")); + textFile.setEnabled(false); + + buttonClear.setText("Clear"); + buttonClear.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonClearActionPerformed(evt); + } + }); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Positioners")); + + jScrollPane1.setBorder(javax.swing.BorderFactory.createTitledBorder("Inactive")); + + tableInactive.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "Name" + } + ) { + Class[] types = new Class [] { + java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + tableInactive.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + jScrollPane1.setViewportView(tableInactive); + + jScrollPane2.setBorder(javax.swing.BorderFactory.createTitledBorder("Fixed")); + + tableFixed.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "Name", "Value", "Units" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.Double.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false, true, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + tableFixed.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + jScrollPane2.setViewportView(tableFixed); + + jScrollPane3.setBorder(javax.swing.BorderFactory.createTitledBorder("Scanned")); + + tableScanned.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "Name", "Start", "Stop", "Points", "Step", "Units" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.Double.class, java.lang.Double.class, java.lang.Integer.class, java.lang.Double.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false, true, true, true, false, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + tableScanned.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + jScrollPane3.setViewportView(tableScanned); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 183, Short.MAX_VALUE) + .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 183, Short.MAX_VALUE)) + .addGap(12, 12, 12)) + ); + + jLabel1.setText("Passes:"); + + spinnerPasses.setModel(new javax.swing.SpinnerNumberModel(1, 1, 1000, 1)); + + checkZigzag.setText("Zigzag"); + + jLabel4.setText("Settling Time:"); + + spinnerLatency.setModel(new javax.swing.SpinnerNumberModel(0.0d, 0.0d, 1000.0d, 1.0d)); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel2Layout.createSequentialGroup() + .addGap(17, 17, 17) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addGap(0, 98, Short.MAX_VALUE) + .addComponent(checkZigzag) + .addGap(18, 18, 18) + .addComponent(jLabel4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spinnerLatency, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spinnerPasses, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(textFile) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonOpen) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonSave) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonClear))))) + .addContainerGap()) + ); + + jPanel2Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonClear, buttonOpen, buttonSave}); + + jPanel2Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spinnerLatency, spinnerPasses}); + + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonOpen) + .addComponent(buttonSave) + .addComponent(jLabel3) + .addComponent(textFile, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonClear)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel4) + .addComponent(spinnerLatency, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(checkZigzag)) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(spinnerPasses, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(2, 2, 2) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(56, Short.MAX_VALUE)) + ); + + buttonAddToQueue.setText("Add to Queue"); + buttonAddToQueue.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonAddToQueueActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(buttonAddToQueue) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonStart) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonAbort) + .addContainerGap(137, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(buttonScienta) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(textFileId, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonResetId) + .addContainerGap()))) + ); + + layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonAbort, buttonAddToQueue, buttonStart}); + + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonScienta) + .addComponent(buttonResetId) + .addComponent(jLabel2) + .addComponent(textFileId, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonStart) + .addComponent(buttonAbort) + .addComponent(buttonAddToQueue)) + .addContainerGap()) + ); + }// //GEN-END:initComponents + + private void buttonScientaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonScientaActionPerformed + try { + this.showDevicePanel("scienta"); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonScientaActionPerformed + + private void buttonResetIdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonResetIdActionPerformed + try { + this.getContext().setFileSequentialNumber(0); + updateControls(); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonResetIdActionPerformed + + private void buttonStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStartActionPerformed + try { + execute(); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonStartActionPerformed + + private void buttonAbortActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAbortActionPerformed + try { + abort(); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonAbortActionPerformed + + private void buttonOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOpenActionPerformed + try { + open(); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonOpenActionPerformed + + private void buttonSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveActionPerformed + try { + JFileChooser chooser = new JFileChooser(getContext().getSetup().expandPath(getHomePath())); + FileNameExtensionFilter filter = new FileNameExtensionFilter(getDescription(), getExtensions()); + chooser.setFileFilter(filter); + try { + if (currentFile != null) { + chooser.setSelectedFile(currentFile); + } + } catch (Exception ex) { + this.showException(ex); + } + int rVal = chooser.showSaveDialog(this); + if (rVal == JFileChooser.APPROVE_OPTION) { + String fileName = chooser.getSelectedFile().getAbsolutePath(); + if (IO.getExtension(chooser.getSelectedFile().getAbsolutePath()).isEmpty()) { + fileName += "." + FILE_EXTENSION; + } + saveAs(fileName); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonSaveActionPerformed + + private void buttonAddToQueueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAddToQueueActionPerformed + try { + QueueProcessor tq = null; + List queues = getView().getQueues(); + if (queues.size()==0){ + tq = getView().openProcessor(QueueProcessor.class, null); + } else { + tq = queues.get(0); + } + getView().getDocumentsTab().setSelectedComponent(tq); + tq.addNewFile(currentFile.getPath()); + + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonAddToQueueActionPerformed + + private void buttonClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonClearActionPerformed + try { + clear(); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonClearActionPerformed + + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton buttonAbort; + private javax.swing.JButton buttonAddToQueue; + private javax.swing.JButton buttonClear; + private javax.swing.JButton buttonOpen; + private javax.swing.JButton buttonResetId; + private javax.swing.JButton buttonSave; + private javax.swing.JButton buttonScienta; + private javax.swing.JButton buttonStart; + private javax.swing.JCheckBox checkZigzag; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JSpinner spinnerLatency; + private javax.swing.JSpinner spinnerPasses; + private javax.swing.JTable tableFixed; + private javax.swing.JTable tableInactive; + private javax.swing.JTable tableScanned; + private javax.swing.JTextField textFile; + private javax.swing.JTextField textFileId; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/ScreenPanel.java b/plugins/ScreenPanel.java index 2413eee..0ca0bee 100644 --- a/plugins/ScreenPanel.java +++ b/plugins/ScreenPanel.java @@ -37,6 +37,7 @@ import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; +import javax.swing.SwingUtilities; /** * @@ -103,20 +104,30 @@ public class ScreenPanel extends Panel implements CamServerViewer.CamServerViewe if (App.hasArgument("instance_format")) { camServerViewer.setInstanceNameFormat(App.getArgumentValue("instance_format")); } + camServerViewer.setShowFit(true); + camServerViewer.setShowProfile(true); + camServerViewer.setShowReticle(true); } @Override public void onStart() { - super.onStart(); + super.onStart(); try { camServerViewer.setCameraServerUrl(App.getArgumentValue(ARG_CAMERA_SERVER)); camServerViewer.setPipelineServerUrl(App.getArgumentValue(ARG_PIPELINE_SERVER)); camServerViewer.setStartupStream(App.getArgumentValue(ARG_CAMERA)); - camServerViewer.initialize(CamServerViewer.SourceSelecionMode.Cameras); + SwingUtilities.invokeLater(()->{ + try { + camServerViewer.initialize(CamServerViewer.SourceSelecionMode.Cameras); + } catch (Exception ex) { + Logger.getLogger(ScreenPanel.class.getName()).log(Level.SEVERE, null, ex); + } + updateDialogTitle(); + }); + } catch (Exception ex) { logger.log(Level.SEVERE, null, ex); - } - updateDialogTitle(); + } } @Override @@ -195,7 +206,7 @@ public class ScreenPanel extends Panel implements CamServerViewer.CamServerViewe @Override public void onOpeningStream(String name) throws Exception { - System.out.println("Initializing stream " + name); + System.out.println("Initializing stream " + name); if ((devicesInitTask != null) && (devicesInitTask.isAlive())) { devicesInitTask.interrupt(); } @@ -207,6 +218,7 @@ public class ScreenPanel extends Panel implements CamServerViewer.CamServerViewe filter.close(); filter = null; } + updateDialogTitle(); } @@ -272,7 +284,7 @@ public class ScreenPanel extends Panel implements CamServerViewer.CamServerViewe devicesInitTask.start(); } } - + updateDialogTitle(); } public void onSavedSnapshot(String name, String instancee, String snapshotFile) throws Exception { diff --git a/plugins/ScreenPanel1.form b/plugins/ScreenPanel1.form new file mode 100755 index 0000000..3974d55 --- /dev/null +++ b/plugins/ScreenPanel1.form @@ -0,0 +1,960 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/ScreenPanel1.java b/plugins/ScreenPanel1.java new file mode 100755 index 0000000..7e1513c --- /dev/null +++ b/plugins/ScreenPanel1.java @@ -0,0 +1,3223 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.pshell.bs.CameraServer; +import ch.psi.pshell.core.Context; +import java.io.IOException; +import java.nio.file.Paths; +import javax.swing.DefaultComboBoxModel; +import ch.psi.pshell.ui.Panel; +import ch.psi.pshell.imaging.ImageListener; +import ch.psi.utils.State; +import ch.psi.utils.Chrono; +import ch.psi.utils.swing.SwingUtils; +import ch.psi.utils.swing.TextEditor; +import ch.psi.pshell.bs.PipelineServer; +import ch.psi.pshell.bs.StreamValue; +import ch.psi.pshell.core.JsonSerializer; +import ch.psi.pshell.data.DataManager; +import ch.psi.pshell.device.DescStatsDouble; +import ch.psi.pshell.device.Device; +import ch.psi.pshell.epics.ChannelInteger; +import ch.psi.pshell.epics.DiscretePositioner; +import ch.psi.pshell.epics.Epics; +import ch.psi.pshell.imaging.Calibration; +import ch.psi.pshell.imaging.Colormap; +import ch.psi.pshell.imaging.ColormapSource; +import ch.psi.pshell.imaging.ColormapSource.ColormapSourceConfig; +import ch.psi.pshell.ui.App; +import ch.psi.pshell.imaging.Data; +import ch.psi.pshell.imaging.DimensionDouble; +import ch.psi.pshell.imaging.Histogram; +import ch.psi.pshell.imaging.ImageBuffer; +import ch.psi.pshell.imaging.Overlay; +import ch.psi.pshell.imaging.Overlays; +import ch.psi.pshell.imaging.Overlays.Text; +import ch.psi.pshell.imaging.Pen; +import ch.psi.pshell.imaging.PointDouble; +import ch.psi.pshell.imaging.Renderer; +import ch.psi.pshell.imaging.RendererListener; +import ch.psi.pshell.imaging.RendererMode; +import ch.psi.pshell.imaging.Source; +import ch.psi.pshell.imaging.SourceBase; +import ch.psi.pshell.imaging.Utils; +import ch.psi.pshell.scripting.InterpreterResult; +import ch.psi.pshell.scripting.ScriptManager; +import ch.psi.pshell.swing.ValueSelection; +import ch.psi.pshell.swing.ValueSelection.ValueSelectionListener; +import ch.psi.utils.Arr; +import ch.psi.utils.ArrayProperties; +import ch.psi.utils.Convert; +import ch.psi.utils.swing.Editor.EditorDialog; +import ch.psi.utils.swing.MainFrame; +import ch.psi.utils.swing.StandardDialog; +import ch.psi.utils.swing.StandardDialog.StandardDialogListener; +import ch.psi.utils.swing.SwingUtils.OptionResult; +import ch.psi.utils.swing.SwingUtils.OptionType; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.io.FileInputStream; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.table.DefaultTableModel; +import org.apache.commons.math3.analysis.function.Gaussian; +import org.apache.commons.math3.fitting.GaussianCurveFitter; +import org.apache.commons.math3.fitting.WeightedObservedPoint; +import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; + +/** + * + */ +public class ScreenPanel1 extends Panel { + + final String CAMERA_DEVICE_NAME = "CurrentCamera"; + boolean useServerStats = true; + String userOverlaysConfigFile; + ColormapSource camera; + PipelineServer server; + String cameraName; + int polling = 1000; + Overlay marker = null; + JDialog histogramDialog; + DiscretePositioner screen; + DiscretePositioner filter; + boolean showFit; + boolean showProfile; + Overlay[] userOv; + Overlay[] fitOv; + Overlay[] profileOv; + Overlay errorOverlay; + boolean requestCameraListUpdate; + boolean goodRegion; + String serverUrl; + String instanceName; + + boolean averaging = false; + + Double getServerDouble(String name) { + return (Double) Convert.toDouble(server.getValue(name)); + } + + double[] getServerDoubleArray(String name) { + return (double[]) Convert.toDouble(server.getValue(name)); + } + + Double getServerDouble(String name, StreamValue cache) { + return (Double) Convert.toDouble(cache.__getitem__(name)); + } + + double[] getServerDoubleArray(String name, StreamValue cache) { + return (double[]) Convert.toDouble(cache.__getitem__(name)); + } + + class ImageData { + + ImageData() { + if (server != null) { + cache = server.getStream().take(); + String prefix = goodRegion ? "gr_" : ""; + x_fit_mean = getServerDouble(prefix + "x_fit_mean", cache); + y_fit_mean = getServerDouble(prefix + "y_fit_mean", cache); + x_fit_standard_deviation = getServerDouble(prefix + "x_fit_standard_deviation", cache); + y_fit_standard_deviation = getServerDouble(prefix + "y_fit_standard_deviation", cache); + x_fit_gauss_function = getServerDoubleArray(prefix + "x_fit_gauss_function", cache); + y_fit_gauss_function = getServerDoubleArray(prefix + "y_fit_gauss_function", cache); + x_profile = getServerDoubleArray("x_profile", cache); + y_profile = getServerDoubleArray("y_profile", cache); + x_center_of_mass = getServerDouble("x_center_of_mass", cache); + y_center_of_mass = getServerDouble("y_center_of_mass", cache); + x_rms = getServerDouble("x_rms", cache); + y_rms = getServerDouble("y_rms", cache); + if (goodRegion) { + double[] gX2 = new double[x_profile.length]; + Arrays.fill(gX2, Double.NaN); + try { + double x = getServerDoubleArray("gr_x_axis", cache)[0]; + System.arraycopy(x_fit_gauss_function, 0, gX2, (int) ((renderer.getCalibration() != null) ? renderer.getCalibration().convertToImageX(x) : x), x_fit_gauss_function.length); + } catch (Exception ex) { + } + x_fit_gauss_function = gX2; + double[] gY2 = new double[y_profile.length]; + Arrays.fill(gY2, Double.NaN); + try { + double y = getServerDoubleArray("gr_y_axis", cache)[0]; + System.arraycopy(y_fit_gauss_function, 0, gY2, (int) ((renderer.getCalibration() != null) ? renderer.getCalibration().convertToImageY(y) : y), y_fit_gauss_function.length); + } catch (Exception ex) { + } + y_fit_gauss_function = gY2; + } + } + } + public Double x_fit_mean; + public Double y_fit_mean; + public Double x_center_of_mass; + public Double x_rms; + public Double x_fit_standard_deviation; + public Double y_fit_standard_deviation; + public Double y_center_of_mass; + public Double y_rms; + public double[] x_profile; + public double[] x_fit_gauss_function; + public double[] y_profile; + public double[] y_fit_gauss_function; + public StreamValue cache; + + } + + class Frame extends ImageData { + + Frame(Data data) { + this.data = data; + } + Data data; + + } + + final ArrayList imageBuffer = new ArrayList(); + Frame currentFrame; + int imageBufferLenght = 1; + Text imageBufferOverlay; + + public ScreenPanel1() { + initComponents(); + spinnerThreshold.setVisible(false); + btFixColormapRange.setVisible(false); + spinnerGrThreshold.setVisible(false); + labelGrThreshold.setVisible(false); + spinnerGrScale.setVisible(false); + labelGrScale.setVisible(false); + //spinnerMin.setVisible(false); labelMin.setVisible(false); + //spinnerMax.setVisible(false); labelMax.setVisible(false); + renderer.setPersistenceFile(Paths.get(getContext().getSetup().getContextPath(), "Renderer_Cameras.bin")); + setPersistedComponents(new Component[]{buttonServer, buttonDirect}); + comboCameras.setEnabled(false); + SwingUtils.setEnumCombo(comboColormap, Colormap.class); + if (App.hasArgument("poll")) { + try { + polling = Integer.valueOf(App.getArgumentValue("poll")); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + if (App.hasArgument("zoom")) { + try { + renderer.setDefaultZoom(Double.valueOf(App.getArgumentValue("zoom"))); + renderer.resetZoom(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + if (App.hasArgument("buf")) { + try { + imageBufferLenght = Integer.valueOf(App.getArgumentValue("buf")); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + if (App.hasArgument("usr_ov")) { + try { + userOverlaysConfigFile = App.getArgumentValue("usr_ov"); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + if (App.hasArgument("srv_url")) { + serverUrl = App.getArgumentValue("srv_url"); + } + + if (App.hasArgument("calc")) { + useServerStats = false; + } + + renderer.setProfileNormalized(true); + renderer.setShowProfileLimits(false); + + JMenuItem menuCalibrate = new JMenuItem("Calibrate..."); + menuCalibrate.addActionListener((ActionEvent e) -> { + try { + calibrate(); + } catch (Exception ex) { + ex.printStackTrace(); + showException(ex); + } + }); + + JMenuItem menuShowStreamData = new JMenuItem("Show Stream Data"); + menuShowStreamData.addActionListener((ActionEvent e) -> { + try { + showStreamData(); + } catch (Exception ex) { + showException(ex); + } + }); + + JMenuItem menuSaveStack = new JMenuItem("Save Stack"); + menuSaveStack.addActionListener((ActionEvent e) -> { + try { + saveStack(); + } catch (Exception ex) { + showException(ex); + } + }); + menuSaveStack.setEnabled(imageBufferLenght > 0); + + JMenuItem menuSetROI = new JMenuItem("Set ROI..."); + menuSetROI.addActionListener((ActionEvent e) -> { + renderer.abortSelection(); + if (server != null) { + final Overlays.Rect selection = new Overlays.Rect(renderer.getPenMovingOverlay()); + renderer.addListener(new RendererListener() { + @Override + public void onSelectionFinished(Renderer renderer, Overlay overlay) { + try { + renderer.setShowReticle(false); + Rectangle roi = overlay.isFixed() ? renderer.toImageCoord(overlay.getBounds()) : overlay.getBounds(); + if (server.isRoiEnabled()) { + int[] cur = server.getRoi(); + server.setRoi(new int[]{roi.x + cur[0], roi.y + cur[1], roi.width, roi.height}); + } else { + server.setRoi(new int[]{roi.x, roi.y, roi.width, roi.height}); + } + } catch (Exception ex) { + } finally { + renderer.removeListener(this); + } + } + + @Override + public void onSelectionAborted(Renderer renderer, Overlay overlay) { + renderer.removeListener(this); + } + }); + selection.setFixed(true); + renderer.startSelection(selection); + } + }); + + JMenuItem menuResetROI = new JMenuItem("Reset ROI"); + menuResetROI.addActionListener((ActionEvent e) -> { + renderer.abortSelection(); + if (server != null) { + try { + renderer.setShowReticle(false); + server.resetRoi(); + } catch (IOException ex) { + showException(ex); + } + } + }); + + renderer.getPopupMenu().add(menuShowStreamData); + renderer.getPopupMenu().add(menuCalibrate); + renderer.getPopupMenu().add(menuSaveStack); + renderer.getPopupMenu().addSeparator(); + renderer.getPopupMenu().add(menuSetROI); + renderer.getPopupMenu().add(menuResetROI); + renderer.getPopupMenu().addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + menuResetROI.setEnabled(server != null); + menuSetROI.setEnabled(server != null); + menuShowStreamData.setVisible(server != null); + menuCalibrate.setVisible(server != null); + menuCalibrate.setEnabled((calibrationDialolg == null) || (!calibrationDialolg.isShowing())); + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + } + }); + renderer.getPopupMenu().setVisible(false); + + showFit = buttonFit.isSelected(); + showProfile = buttonProfile.isSelected(); + + pauseSelection.setVisible(false); + pauseSelection.setMinValue(1); + pauseSelection.addListener(new ValueSelectionListener() { + @Override + public void onValueChanged(ValueSelection origin, double value, boolean editing) { + if (editing && (value >= 1) && (value <= imageBuffer.size())) { + updatePause(); + } + } + }); + imageBufferOverlay = new Text(renderer.getPenErrorText(), "", new Font("Verdana", Font.PLAIN, 12), new Point(-100, 20)); + imageBufferOverlay.setFixed(true); + imageBufferOverlay.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_RIGHT); + if (MainFrame.isDark()) { + textState.setEnabled(true); + } + } + + @Override + public void onStart() { + super.onStart(); + if (App.hasArgument("ct")) { + boolean direct = App.getArgumentValue("ct").equals("0") || App.getArgumentValue("ct").equalsIgnoreCase("false"); + buttonServer.setSelected(!direct); + buttonDirect.setSelected(direct); + } + } + + @Override + public void onStop() { + try { + if (camera != null) { + camera.close(); + camera = null; + server = null; + } + } catch (Exception ex) { + ex.printStackTrace(); + } + super.onStop(); + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + comboCameras.setEnabled(false); + if (App.hasArgument("s")) { + renderer.setDevice((Source) getDevice("image")); + renderer.setAutoScroll(true); + ((Source) getDevice("image")).addListener(new ImageListener() { + @Override + public void onImage(Object o, BufferedImage bi, Data data) { + manageFit(bi, data); + manageUserOverlays(bi, data); + } + + @Override + public void onError(Object o, Exception ex) { + } + } + ); + + } else { + usingServer = buttonServer.isSelected(); + updateCameraList(); + comboCameras.setEnabled(true); + setComboCameraSelection(-1); + + if (comboCameras.getModel().getSize() > 0) { + try { + if (App.hasArgument("cam")) { + setComboCameraSelection(App.getArgumentValue("cam")); + comboCamerasActionPerformed(null); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + startTimer(1000); + } + + DefaultComboBoxModel getCameraList(boolean fromServer) throws Exception { + DefaultComboBoxModel model = new DefaultComboBoxModel(); + if (fromServer) { + try (PipelineServer srv = newServer()) { + srv.initialize(); + List cameras = srv.getCameras(); + Collections.sort(cameras); + for (String camera : cameras) { + model.addElement(camera); + } + } + + } else { + ArrayList cameras = (ArrayList) getContext().getClassByName("SfCamera").getMethod("getCameras", new Class[]{}).invoke(null); + for (String cam : cameras) { + model.addElement(cam); + } + } + return model; + } + + PipelineServer newServer() throws IOException { + if (serverUrl != null) { + System.out.println("Connecting to server: " + serverUrl); + server = new PipelineServer(CAMERA_DEVICE_NAME, serverUrl); + } else { + System.out.println("Connecting to server"); + server = new PipelineServer(CAMERA_DEVICE_NAME); + } + return server; + } + + boolean updatingCameraSelection; + + void setComboCameraSelection(Object selection) { + updatingCameraSelection = true; + try { + comboCameras.setSelectedItem(selection); + } finally { + updatingCameraSelection = false; + } + } + + boolean usingServer; + + void updateCameraList() { + try { + String selected = (String) comboCameras.getSelectedItem(); + DefaultComboBoxModel model = getCameraList(usingServer); + if (App.hasArgument("cam")) { + String cam = App.getArgumentValue("cam"); + if (model.getIndexOf(cam) < 0) { + model.addElement(cam); + } + } + comboCameras.setModel(model); + if (selected != null) { + setComboCameraSelection(selected); + } + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + updateStop(); + } + } + + final Object lockOverlays = new Object(); + + void manageFit(BufferedImage bi, Data data) { + Overlay[][] fo = ((bi == null) || ((!showFit && !showProfile))) ? null : getFitOverlays(data); + synchronized (lockOverlays) { + fo = (fo == null) ? new Overlay[][]{null, null} : fo; + renderer.updateOverlays(fo[0], profileOv); + profileOv = fo[0]; + renderer.updateOverlays(fo[1], fitOv); + fitOv = fo[1]; + } + } + + void manageUserOverlays(BufferedImage bi, Data data) { + Overlay[] fo = (bi == null) ? null : getUserOverlays(data); + synchronized (lockOverlays) { + renderer.updateOverlays(fo, userOv); + userOv = fo; + } + } + + @Override + public void onStateChange(State state, State former) { + + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + //Callback to perform update - in event thread + @Override + protected void doUpdate() { + } + + Thread devicesInitTask; + + class ImageAverager extends SourceBase { + final ArrayList images = new ArrayList(); + ImageAverager() { + super("Image Averager"); + + camera.addListener(new ImageListener() { + @Override + public void onImage(Object o, BufferedImage bi, Data data) { + images.add(bi); + if (images.size()>10){ + images.remove(0); + } + BufferedImage ret = null; + for (BufferedImage ib : images){ + if (ret == null){ + ret = Utils.copy(ib, null, null); + } else { + Utils.add(ret, ib, true); + + } + } + //ret =Utils.scale(ret, 1.0/images.size()); + ImageAverager.this.pushImage(ret); + } + + @Override + public void onError(Object origin, Exception ex) { + } + }); + + } + } + + void setCamera(String cameraName) throws IOException, InterruptedException { + System.out.println("Initializing"); + parseUserOverlays(); + errorOverlay = null; + + if (dataTableDialog != null) { + dataTableDialog.dispose(); + dataTableDialog = null; + } + dataTableModel = null; + + if (calibrationDialolg != null) { + calibrationDialolg.dispose(); + calibrationDialolg = null; + } + + boolean was_server = false; + if (camera != null) { + //camera.removeAllListeners(); + was_server = (server != null); + camera.close(); + camera = null; + server = null; + } + instanceName = null; + renderer.setDevice(null); + + renderer.setShowReticle(false); + renderer.removeOverlays(fitOv); + renderer.removeOverlays(profileOv); + renderer.removeOverlays(userOv); + renderer.clear(); + renderer.resetZoom(); + + boolean changed = !String.valueOf(cameraName).equals(this.cameraName); + this.cameraName = cameraName; + + if (changed || buttonDirect.isSelected()) { + spinnerThreshold.setVisible(false); + spinnerGrThreshold.setVisible(false); + labelGrThreshold.setVisible(false); + spinnerGrScale.setVisible(false); + labelGrScale.setVisible(false); + checkThreshold.setEnabled(false); + checkGoodRegion.setEnabled(false); + } + if (changed) { + checkBackground.setEnabled(false); + if ((devicesInitTask != null) && (devicesInitTask.isAlive())) { + devicesInitTask.interrupt(); + } + if (screen != null) { + screen.close(); + screen = null; + } + if (filter != null) { + filter.close(); + filter = null; + } + } + if (cameraName == null) { + return; + } + + System.out.println("Setting camera: " + cameraName + " [" + (buttonServer.isSelected() ? "server" : "direct") + "]"); + + synchronized (imageBuffer) { + currentFrame = null; + imageBuffer.clear(); + } + + try { + if (buttonServer.isSelected()) { + camera = newServer(); + camera.getConfig().flipHorizontally = false; + camera.getConfig().flipVertically = false; + camera.getConfig().rotation = 0.0; + camera.getConfig().roiX = 0; + camera.getConfig().roiY = 0; + camera.getConfig().roiWidth = -1; + camera.getConfig().roiHeight = -1; + } else { + //camera = new SfCamera(CAMERA_DEVICE_NAME, cameraName); + camera = (ColormapSource) getContext().getClassByName("SfCamera").getConstructor(new Class[]{String.class, String.class}).newInstance(new Object[]{CAMERA_DEVICE_NAME, cameraName}); + } + camera.initialize(); + camera.assertInitialized(); + System.out.println("Camera initialization OK"); + if (server != null) { + //server.start(cameraName, false); + String pipelineName = cameraName + "_sp"; + instanceName = cameraName + "_sp1"; + if (!server.getPipelines().contains(pipelineName)) { + System.out.println("Creating pipeline: " + pipelineName); + HashMap config = new HashMap<>(); + config.put("camera_name", cameraName); + //server.createFromConfig(config, pipelineName); + server.savePipelineConfig(pipelineName, config); + } + server.start(pipelineName, instanceName); + + updateServerControls(); + checkThreshold.setEnabled(true); + checkGoodRegion.setEnabled(true); + } else { + checkThreshold.setSelected(false); + checkGoodRegion.setSelected(false); + if (polling <= 0) { + camera.setMonitored(true); + } else { + camera.setPolling(polling); + } + camera.setBackgroundEnabled(checkBackground.isSelected()); + } + + buttonReticle.setEnabled(camera.getConfig().isCalibrated()); + camera.getConfig().save(); + if (averaging) { + SourceBase source = new ImageAverager(); + renderer.setDevice(source); + } else { + renderer.setDevice(camera); + } + renderer.setAutoScroll(true); + renderer.setMarker(marker); + imageSize = null; + + camera.addListener(new ImageListener() { + @Override + public void onImage(Object o, BufferedImage bi, Data data) { + if (bi != null) { + if ((imageSize == null) || imageSize.width != bi.getWidth() || imageSize.height != bi.getHeight()) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if ((renderer.getMode() == RendererMode.Zoom) || (renderer.getMode() == RendererMode.Fixed)) { + centralizeRenderer(); + } + checkReticle(); + } + }); + imageSize = new Dimension(bi.getWidth(), bi.getHeight()); + } + renderer.setProfileSize(Math.min(bi.getWidth(), bi.getHeight())); + } + //renderer.setCalibration(camera.getCalibration()); + if (!renderer.isPaused()) { + if (data != null) { + synchronized (imageBuffer) { + currentFrame = new Frame(data); + if (imageBufferLenght >= 1) { + imageBuffer.add(currentFrame); + if (imageBuffer.size() > imageBufferLenght) { + imageBuffer.remove(0); + } + } + } + } + manageFit(bi, data); + manageUserOverlays(bi, data); + } + //updateImageData(); + } + + @Override + public void onError(Object o, Exception ex) { + //System.err.println(ex); + } + }); + + } catch (Exception ex) { + ex.printStackTrace(); + showException(ex); + renderer.clearOverlays(); + updateServerControls(); + if (renderer.getDevice() == null) { + //renderer.setZoom(1.0); + //renderer.setMode(RendererMode.Zoom); + errorOverlay = new Text(renderer.getPenErrorText(), ex.toString(), new Font("Verdana", Font.PLAIN, 12), new Point(20, 20)); + errorOverlay.setFixed(true); + errorOverlay.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_LEFT); + renderer.addOverlay(errorOverlay); + } + } finally { + //checkReticle(); + onTimer(); + } + onChangeColormap(null); + checkBackground.setEnabled(true); + if (changed) { + comboScreen.setModel(new DefaultComboBoxModel()); comboScreen.setEnabled(false); + comboFilter.setModel(new DefaultComboBoxModel()); comboFilter.setEnabled(false); + if (getCameraType(cameraName).equals("ELECTRONS")){ + //Parallelizing initialization + devicesInitTask = new Thread(() -> { + try { + if (cameraName.contains("DSRM")) { + screen = new DiscretePositioner("CurrentScreen", cameraName + ":POSITION_SP", cameraName + ":POSITION"); + } else { + screen = new DiscretePositioner("CurrentScreen", cameraName + ":SET_SCREEN1_POS", cameraName + ":GET_SCREEN1_POS"); + } + screen.setMonitored(true); + screen.initialize(); + DefaultComboBoxModel model = new DefaultComboBoxModel(); + for (String pos : screen.getPositions()) { + model.addElement(pos); + } + comboScreen.setModel(model); + comboScreen.setSelectedItem(screen.read()); + + } catch (Exception ex) { + comboScreen.setModel(new DefaultComboBoxModel()); + System.err.println(ex.getMessage()); + screen = null; + } + comboScreen.setEnabled(screen != null); + valueScreen.setDevice(screen); + + try { + filter = new DiscretePositioner("CurrentFilter", cameraName + ":SET_FILTER", cameraName + ":GET_FILTER"); + filter.setMonitored(true); + filter.initialize(); + DefaultComboBoxModel model = new DefaultComboBoxModel(); + for (String pos : filter.getPositions()) { + model.addElement(pos); + } + comboFilter.setModel(model); + comboFilter.setSelectedItem(filter.read()); + } catch (Exception ex) { + System.err.println(ex.getMessage()); + filter = null; + } + comboFilter.setEnabled(filter != null); + valueFilter.setDevice(filter); + }); + devicesInitTask.start(); + } + } + + } + + volatile Dimension imageSize; + + void checkReticle() { + if ((renderer.getDevice() != null) && (camera != null) && (camera.getConfig().isCalibrated()) && buttonReticle.isSelected()) { + //renderer.setCalibration(camera.getCalibration()); + renderer.configureReticle(new Dimension(800, 800), 200); + renderer.setShowReticle(true); + } else { + //renderer.setCalibration(null); + renderer.setShowReticle(false); + } + renderer.refresh(); + } + + void checkMarker() { + if (camera != null) { + if (buttonMarker.isSelected()) { + Dimension d = renderer.getImageSize(); + Point p = (d == null) ? new Point(renderer.getWidth() / 2, renderer.getHeight() / 2) : new Point(d.width / 2, d.height / 2); + Overlay ov = null; + marker = new Overlays.Crosshairs(renderer.getPenMarker(), p, new Dimension(100, 100)); + marker.setMovable(true); + marker.setPassive(false); + } else { + marker = null; + } + renderer.setMarker(marker); + } + } + + void updateZoom() { + try { + buttonZoomStretch.setSelected(renderer.getMode() == RendererMode.Stretch); + buttonZoomFit.setSelected(renderer.getMode() == RendererMode.Fit); + if (renderer.getMode() == RendererMode.Fixed) { + buttonZoomNormal.setSelected(true); + } else if (renderer.getMode() == RendererMode.Zoom) { + if (renderer.getZoom() == 1) { + buttonZoomNormal.setSelected(true); + } else if (renderer.getZoom() == 0.5) { + buttonZoom05.setSelected(true); + } else if (renderer.getZoom() == 0.25) { + buttonZoom025.setSelected(true); + } else if (renderer.getZoom() == 2.0) { + buttonZoom2.setSelected(true); + } else { + buttonGroup1.clearSelection(); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + boolean updatingColormap; + + void updateColormap() { + updatingColormap = true; + try { + if ((camera != null) && (camera instanceof ColormapSource)) { + ColormapSourceConfig config = ((ColormapSource) camera).getConfig(); + comboColormap.setSelectedItem(config.colormap); + if (config.isDefaultColormap()) { + buttonFullRange.setSelected(true); + } else if (config.colormapAutomatic) { + buttonAutomatic.setSelected(true); + } else { + buttonManual.setSelected(true); + } + btFixColormapRange.setVisible(buttonAutomatic.isSelected()); + + //spinnerMin.setVisible(buttonManual.isSelected()); labelMin.setVisible(spinnerMin.isVisible()); + //spinnerMax.setVisible(buttonManual.isSelected()); labelMax.setVisible(spinnerMax.isVisible()); + spinnerMin.setEnabled(buttonManual.isSelected()); + spinnerMax.setEnabled(buttonManual.isSelected()); + //spinnerMin.setValue(Double.isNaN(config.colormapMin) ? 0 : Math.min(Math.max((int) config.colormapMin, 0), 65535)); + //spinnerMax.setValue(Double.isNaN(config.colormapMax) ? 0 : Math.min(Math.max((int) config.colormapMax, 0), 65535)); + if (!Double.isNaN(config.colormapMin)) { + spinnerMin.setValue(Math.min(Math.max((int) config.colormapMin, 0), 65535)); + } + if (!Double.isNaN(config.colormapMax)) { + spinnerMax.setValue(Math.min(Math.max((int) config.colormapMax, 0), 65535)); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + updatingColormap = false; + } + + boolean updatingServerControls; + + void updateServerControls() { + if (server != null) { + updatingServerControls = true; + try { + checkBackground.setSelected(server.getBackgroundSubtraction()); + Double threshold = (server.getThreshold()); + checkThreshold.setSelected(threshold != null); + spinnerThreshold.setValue((threshold == null) ? 0 : threshold); + Map gr = (server.getGoodRegion()); + checkGoodRegion.setSelected(gr != null); + if (gr != null) { + spinnerGrThreshold.setValue(((Number) gr.get("threshold")).doubleValue()); + spinnerGrScale.setValue(((Number) gr.get("gfscale")).doubleValue()); + } + } catch (Exception ex) { + } + goodRegion = checkGoodRegion.isSelected(); + spinnerThreshold.setVisible(checkThreshold.isSelected()); + spinnerGrThreshold.setVisible(goodRegion); + labelGrThreshold.setVisible(spinnerGrThreshold.isVisible()); + spinnerGrScale.setVisible(goodRegion); + labelGrScale.setVisible(spinnerGrScale.isVisible()); + updatingServerControls = false; + } + } + + boolean isCameraStopped() { + if (server != null) { + if (!server.isStarted()) { + return true; + } + } + return ((camera == null) || (camera.isClosed()) || !buttonStop.isEnabled()); + } + + void updateStop() { + buttonStop.setEnabled(comboCameras.getSelectedItem() != null); + buttonStop.setText(isCameraStopped() ? "Start" : "Stop"); + + } + + @Override + protected void onTimer() { + for (Device dev : new Device[]{screen, filter}) { + if (dev != null) { + dev.request(); + } + } + + textState.setText((camera == null) ? "" : camera.getState().toString()); + buttonArgs.setEnabled(camera != null); + if (App.hasArgument("s")) { + try { + ((Source) getDevice("image")).initialize(); + } catch (IOException ex) { + Logger.getLogger(ScreenPanel1.class.getName()).log(Level.SEVERE, null, ex); + } catch (InterruptedException ex) { + Logger.getLogger(ScreenPanel1.class.getName()).log(Level.SEVERE, null, ex); + } + } + if (renderer.isPaused() != buttonPause.isSelected()) { + buttonPause.setSelected(renderer.isPaused()); + buttonPauseActionPerformed(null); + } + if (renderer.getShowReticle() != buttonReticle.isSelected()) { + //buttonReticle.setSelected(renderer.getShowReticle()); + } + if ((renderer.getMarker() == null) && buttonMarker.isSelected()) { + buttonMarker.setSelected(false); + } + if (!renderer.isPaused() && (dataTableDialog != null) && (dataTableDialog.isShowing())) { + updateStreamData(); + } + updateZoom(); + updateColormap(); + updateStop(); + buttonSave.setSelected(renderer.isSnapshotDialogVisible()); + checkHistogram.setSelected((histogramDialog != null) && (histogramDialog.isShowing())); + } + + Pen penFit = new Pen(new Color(192, 105, 0), 0); + Pen penCross = new Pen(new Color(192, 105, 0), 0); + + public Frame getCurrentFrame() { + if ((imageBufferLenght > 1) && (renderer.isPaused())) { + int index = ((int) pauseSelection.getValue()) - 1; + synchronized (imageBuffer) { + return (index < imageBuffer.size()) ? imageBuffer.get(index) : null; + } + } + return currentFrame; + } + + Frame getFrame(Data data) { + synchronized (imageBuffer) { + for (Frame f : imageBuffer) { + if (f.data == data) { + return f; + } + } + } + return null; + } + + Overlay[][] getFitOverlays(Data data) { + Overlays.Polyline hgaussian = null; + Overlays.Polyline vgaussian = null; + Overlays.Polyline hprofile = null; + Overlays.Polyline vprofile = null; + Double xMean = null, xSigma = null, xNorm = null, xCom = null, xRms = null; + Double yMean = null, ySigma = null, yNorm = null, yCom = null, yRms = null; + double[] pX = null, pY = null, gX = null, gY = null; + int height = data.getHeight(); + int width = data.getWidth(); + //Double xCom=null, yCom=null; + if (data != null) { + int profileSize = renderer.getProfileSize(); + if ((useServerStats) && (server != null)) { + try { + + ImageData id = getFrame(data); + if (id == null) { + return null; + } + xMean = id.x_fit_mean; + xSigma = id.x_fit_standard_deviation; + yMean = id.y_fit_mean; + ySigma = id.y_fit_standard_deviation; + gX = id.x_fit_gauss_function; + gY = id.y_fit_gauss_function; + pX = id.x_profile; + pY = id.y_profile; + xCom = id.x_center_of_mass; + xRms = id.x_rms; + yCom = id.y_center_of_mass; + yRms = id.y_rms; + + profileSize /= 4; + if (pX != null) { + int[] x = Arr.indexesInt(pX.length); + int[] y = new int[pX.length]; + int[] p = new int[pX.length]; + List l = Arrays.asList((Double[]) Convert.toWrapperArray(pX)); + Double min = Collections.min(l); + Double max = Collections.max(l); + double minPlot = min; + double rangePlot = max - min; + + for (int i = 0; i < x.length; i++) { + if (gX != null) { + y[i] = (int) (height - 1 - (((gX[i] - minPlot) / rangePlot) * profileSize)); + } + p[i] = (int) (height - 1 - (((pX[i] - minPlot) / rangePlot) * profileSize)); + } + + if (goodRegion) { + for (int i = 0; i < x.length; i++) { + y[i] = (Double.isNaN(gX[i])) ? 100000 : y[i]; + } + } + + vgaussian = new Overlays.Polyline(penFit, x, y); + vprofile = new Overlays.Polyline(renderer.getPenProfile(), x, p); + } + + if (pY != null) { + int[] y = Arr.indexesInt(pY.length); + int[] x = new int[pY.length]; + int[] p = new int[pY.length]; + + List l = Arrays.asList((Double[]) Convert.toWrapperArray(pY)); + Double min = Collections.min(l); + Double max = Collections.max(l); + double minPlot = min; + double rangePlot = max - min; + + for (int i = 0; i < x.length; i++) { + if (gY != null) { + x[i] = (int) (((gY[i] - minPlot) / rangePlot) * profileSize); + } + p[i] = (int) (((pY[i] - minPlot) / rangePlot) * profileSize); + } + + if (goodRegion) { + for (int i = 0; i < x.length; i++) { + x[i] = (Double.isNaN(gY[i])) ? -1 : x[i]; + } + } + hgaussian = new Overlays.Polyline(penFit, x, y); + hprofile = new Overlays.Polyline(renderer.getPenProfile(), p, y); + } + } catch (Exception ex) { + System.err.println(ex.getMessage()); + return null; + } + } else { + ArrayProperties properties = data.getProperties(); + double maxPlot = properties.max; + double minPlot = properties.min; + double rangePlot = maxPlot - minPlot; + + if (rangePlot <= 0) { + return null; + } + if (renderer.getCalibration() != null) { + try { + double[] sum = data.integrateVertically(true); + double[] saux = new double[sum.length]; + int[] p = new int[sum.length]; + double[] x_egu = renderer.getCalibration().getAxisX(sum.length); + double[] comRms = getComRms(sum, x_egu); + xCom = comRms[0]; + xRms = comRms[1]; + int[] x = Arr.indexesInt(sum.length); + DescriptiveStatistics stats = new DescriptiveStatistics(sum); + double min = stats.getMin(); + for (int i = 0; i < sum.length; i++) { + saux[i] = sum[i] - min; + } + if (showFit) { + double[] gaussian = fitGaussian(saux, x); + if (gaussian != null) { + if ((gaussian[2] < sum.length * 0.45) + && (gaussian[2] > 2) + && (gaussian[0] > min * 0.03)) { + xNorm = gaussian[0]; + xMean = gaussian[1]; + xSigma = gaussian[2]; + double[] fit = getFitFunction(gaussian, x); + int[] y = new int[x.length]; + for (int i = 0; i < x.length; i++) { + y[i] = (int) (height - 1 - ((((fit[i] + min) / height - minPlot) / rangePlot) * profileSize)); + } + vgaussian = new Overlays.Polyline(penFit, x, y); + } + } + } + if (showProfile) { + for (int i = 0; i < x.length; i++) { + p[i] = (int) (height - 1 - (((sum[i] / height - minPlot) / rangePlot) * profileSize)); + } + vprofile = new Overlays.Polyline(renderer.getPenProfile(), x, p); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + + try { + double[] sum = data.integrateHorizontally(true); + double[] saux = new double[sum.length]; + int[] p = new int[sum.length]; + double[] y_egu = renderer.getCalibration().getAxisY(sum.length); + double[] comRms = getComRms(sum, y_egu); + yCom = comRms[0]; + yRms = comRms[1]; + int[] x = Arr.indexesInt(sum.length); + DescriptiveStatistics stats = new DescriptiveStatistics(sum); + double min = stats.getMin(); + for (int i = 0; i < sum.length; i++) { + saux[i] = sum[i] - min; + } + + if (showFit) { + double[] gaussian = fitGaussian(saux, x); + if (gaussian != null) { + //Only aknowledge beam fully inside the image and peak over 3% of min + if ((gaussian[2] < sum.length * 0.45) + && (gaussian[2] > 2) + && (gaussian[0] > min * 0.03)) { + yNorm = gaussian[0]; + yMean = gaussian[1]; + ySigma = gaussian[2]; + double[] fit = getFitFunction(gaussian, x); + + int[] y = new int[x.length]; + for (int i = 0; i < x.length; i++) { + y[i] = (int) ((((fit[i] + min) / width - minPlot) / rangePlot) * profileSize); + } + hgaussian = new Overlays.Polyline(penFit, y, x); + } + } + } + if (showProfile) { + for (int i = 0; i < x.length; i++) { + p[i] = (int) (((sum[i] / width - minPlot) / rangePlot) * profileSize); + } + hprofile = new Overlays.Polyline(renderer.getPenProfile(), p, x); + } + + } catch (Exception ex) { + ex.printStackTrace(); + } + if (xSigma != null) { + xSigma *= renderer.getCalibration().getScaleX(); + } + if (ySigma != null) { + ySigma *= renderer.getCalibration().getScaleY(); + } + if (xMean != null) { + xMean = data.getX((int) Math.round(xMean)); + } + if (yMean != null) { + yMean = data.getY((int) Math.round(yMean)); + } + } + } + final String units = (renderer.getCalibration() != null) ? "\u00B5m" : "px"; + final String fmt = "%7.1f" + units; + Overlays.Text textCom = null; + Overlay[] pOv = null, fOv = null; + Point textPosition = new Point(12, 20); + if (showProfile) { + if ((xCom != null) && (yCom != null)) { + String text = String.format("com x: m=" + fmt + " \u03C3=" + fmt + "\ncom y: m=" + fmt + " \u03C3=" + fmt, xCom, xRms, yCom, yRms); + textCom = new Overlays.Text(renderer.getPenProfile(), text, new Font(Font.MONOSPACED, 0, 14), textPosition); + textCom.setFixed(true); + textCom.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_LEFT); + } + pOv = new Overlay[]{hprofile, vprofile, textCom}; + } + if (showFit) { + Overlays.Crosshairs cross = null; + Overlays.Text textFit = null; + if ((xMean != null) && (yMean != null)) { + String text = String.format("fit x: m=" + fmt + " \u03C3=" + fmt + "\nfit y: m=" + fmt + " \u03C3=" + fmt, xMean, xSigma, yMean, ySigma); + textFit = new Overlays.Text(penFit, text, new Font(Font.MONOSPACED, 0, 14), showProfile ? new Point(12, 54) : textPosition); + textFit.setFixed(true); + textFit.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_LEFT); + Point center = new Point(xMean.intValue(), yMean.intValue()); + if (renderer.getCalibration() != null) { + center = renderer.getCalibration().convertToImagePosition(new PointDouble(xMean, yMean)); + xSigma /= renderer.getCalibration().getScaleX(); + ySigma /= renderer.getCalibration().getScaleY(); + } + cross = new Overlays.Crosshairs(penCross, center, new Dimension(Math.abs(2 * xSigma.intValue()), 2 * Math.abs(ySigma.intValue()))); + } + fOv = new Overlay[]{hgaussian, vgaussian, cross, textFit}; + + if (goodRegion) { + try { + double[] x = getServerDoubleArray("gr_x_axis"); + double[] y = getServerDoubleArray("gr_y_axis"); + double x1 = x[0]; + double x2 = x[x.length - 1]; + double y1 = y[0]; + double y2 = y[y.length - 1]; + Overlays.Rect goodRegionOv = new Overlays.Rect(new Pen(penFit.getColor(), 0, Pen.LineStyle.dotted)); + goodRegionOv.setCalibration(renderer.getCalibration()); + goodRegionOv.setAbsolutePosition(new PointDouble(x1, y1)); + goodRegionOv.setAbsoluteSize(new DimensionDouble(x2 - x1, y2 - y1)); + fOv = Arr.append(fOv, goodRegionOv); + } catch (Exception ex) { + } + } + + } + return new Overlay[][]{pOv, fOv}; + } + return null; + } + + class UserOverlay { + + String name; + Overlay obj; + String[] channels; + } + ArrayList userOverlayConfig; + + void parseUserOverlays() { + Properties userOverlays = new Properties(); + userOverlayConfig = new ArrayList<>(); + if (userOverlaysConfigFile != null) { + try { + try (FileInputStream in = new FileInputStream(getContext().getSetup().expandPath(userOverlaysConfigFile))) { + userOverlays.load(in); + + for (String name : userOverlays.stringPropertyNames()) { + String val = userOverlays.getProperty(name); + try { + UserOverlay uo = new UserOverlay(); + uo.name = name; + String type = val.substring(0, val.indexOf("(")).trim(); + String pars = val.substring(val.indexOf("(") + 1, val.lastIndexOf(")")).trim(); + String[] tokens = pars.split(","); + for (int i = 0; i < tokens.length; i++) { + tokens[i] = tokens[i].trim(); + } + Color color = Color.GRAY; + try { + color = (Color) Color.class.getField(tokens[tokens.length - 1].toUpperCase()).get(null); + } catch (Exception ex) { + } + Pen pen = new Pen(color); + try { + String[] penTokens = tokens[tokens.length - 1].split(":"); + color = (Color) Color.class.getField(penTokens[0].toUpperCase()).get(null); + int width = Integer.valueOf(penTokens[1]); + Pen.LineStyle style = Pen.LineStyle.valueOf(penTokens[2]); + pen = new Pen(color, width, style); + } catch (Exception ex) { + } + switch (type) { + case "Point": + uo.obj = new Overlays.Crosshairs(); + uo.obj.setSize(new Dimension(Integer.valueOf(tokens[2]), Integer.valueOf(tokens[3]))); + break; + case "Line": + uo.obj = new Overlays.Line(); + break; + case "Arrow": + uo.obj = new Overlays.Arrow(); + break; + case "Rect": + uo.obj = new Overlays.Rect(); + break; + case "Ellipse": + uo.obj = new Overlays.Ellipse(); + break; + case "Polyline": + uo.obj = new Overlays.Polyline(); + break; + } + if (type.equals("Polyline") || type.equals("Point")) { + uo.channels = new String[]{tokens[0], tokens[1]}; + } else { + uo.channels = new String[]{tokens[0], tokens[1], tokens[2], tokens[3]}; + } + uo.obj.setPen(pen); + userOverlayConfig.add(uo); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + Overlay[] getUserOverlays(Data data) { + ArrayList ret = new ArrayList<>(); + if (server != null) { + for (UserOverlay uo : userOverlayConfig) { + try { + Overlay ov = uo.obj; + //Overlay ov = (Overlay)uo.cls.newInstance(); + ov.setCalibration(renderer.getCalibration()); + boolean valid = false; + if (ov instanceof Overlays.Polyline) { + double[] x = (uo.channels[0].equals("null")) ? null : getServerDoubleArray(uo.channels[0]); + double[] y = (uo.channels[1].equals("null")) ? null : getServerDoubleArray(uo.channels[1]); + if ((x != null) || (y != null)) { + if (x == null) { + x = (renderer.getCalibration() == null) ? Arr.indexesDouble(y.length) : renderer.getCalibration().getAxisX(y.length); + } + if (y == null) { + y = (renderer.getCalibration() == null) ? Arr.indexesDouble(x.length) : renderer.getCalibration().getAxisY(x.length); + } + ((Overlays.Polyline) ov).updateAbsolute(x, y); + valid = true; + } + } else { + Double x = getServerDouble(uo.channels[0]); + Double y = getServerDouble(uo.channels[1]); + if ((x != null) && (y != null)) { + PointDouble position = new PointDouble(x, y); + ov.setAbsolutePosition(position); + if (!(ov instanceof Overlays.Crosshairs)) { + Double x2 = getServerDouble(uo.channels[2]); + Double y2 = getServerDouble(uo.channels[3]); + if ((x != null) && (y != null)) { + DimensionDouble size = new DimensionDouble(x2 - position.x, y2 - position.y); + ov.setAbsoluteSize(size); + valid = true; + } + } else { + valid = true; + } + } + } + if (valid) { + ret.add(ov); + } + } catch (Exception ex) { + //ex.printStackTrace(); + } + } + } + return ret.toArray(new Overlay[0]); + } + + double[] getComRms(double[] arr, double[] x) { + if (arr != null) { + double xmd = 0; + double xmd2 = 0; + double total = 0; + for (int i = 0; i < arr.length; i++) { + double v = (arr[i] * x[i]); + xmd += v; + xmd2 += (v * x[i]); + total += arr[i]; + } + if (total > 0) { + double com = xmd / total; + double com2 = xmd2 / total; + double rms = Math.sqrt(Math.abs(com2 - com * com)); + return new double[]{com, rms}; + } + } + return new double[]{Double.NaN, Double.NaN}; + } + + double[] fitGaussianScript(int[] y, int[] x) { + ScriptManager sm = Context.getInstance().getScriptManager(); + ArrayProperties pY = ArrayProperties.get(y); + sm.setVar("y", y); + sm.setVar("x", x); + InterpreterResult r = sm.eval("r = fit_gaussians(y, x, [" + pY.maxIndex + ",])"); + if (r.exception != null) { + r.exception.printStackTrace(); + } else { + List ret = (List) sm.getVar("r"); + if ((ret != null) && (ret.size() == 1) && (ret.get(0) instanceof List) && (((List) (ret.get(0))).size() == 3)) { + double norm = (Double) ((List) ret.get(0)).get(0); + double mean = (Double) ((List) ret.get(0)).get(1); + double sigma = (Double) ((List) ret.get(0)).get(2); + return new double[]{norm, mean, sigma}; + } + } + return null; + } + + double[] fitGaussian(double[] y, int[] x) { + try { + ArrayProperties pY = ArrayProperties.get(y); + GaussianCurveFitter fitter = GaussianCurveFitter.create().withStartPoint(new double[]{(pY.max - pY.min) / 2, x[pY.maxIndex], 1.0}).withMaxIterations(1000); + ArrayList values = new ArrayList<>(); + for (int i = 0; i < y.length; i++) { + values.add(new WeightedObservedPoint(1.0, x[i], y[i])); + } + return fitter.fit(values); + } catch (Exception ex) { + return null; + } + + } + + double[] getFitFunction(double[] pars, int[] x) { + double[] fit = new double[x.length]; + Gaussian g = new Gaussian(pars[0], pars[1], pars[2]); + for (int i = 0; i < x.length; i++) { + fit[i] = g.value(x[i]); + } + return fit; + } + + void setHistogramVisible(boolean value) { + if (value) { + if ((histogramDialog == null) || (!histogramDialog.isShowing())) { + Histogram histogram = new Histogram(true); + histogram.setRenderer(renderer); + histogramDialog = SwingUtils.showDialog(SwingUtils.getWindow(renderer), "Histogram", null, histogram); + renderer.refresh(); + } + } else { + if (histogramDialog != null) { + histogramDialog.setVisible(false); + histogramDialog = null; + } + } + } + + void setLaserState(boolean value) throws Exception { + System.out.println("Setting laser state: " + value); + Epics.putq("SIN-TIMAST-TMA:Beam-Las-Delay-Sel", value ? 0 : 1); + Epics.putq("SIN-TIMAST-TMA:Beam-Apply-Cmd.PROC", 1); + Thread.sleep(3000); + } + + boolean getLaserState() throws Exception { + return (Epics.get("SIN-TIMAST-TMA:Beam-Las-Delay-Sel", Integer.class) == 0); + } + + void elog(String logbook, String title, String message, String[] attachments) throws Exception { + String domain = ""; + String category = "Info"; + String entry = ""; + StringBuffer cmd = new StringBuffer(); + + cmd.append("G_CS_ELOG_add -l \"").append(logbook).append("\" "); + cmd.append("-a \"Author=ScreenPanel\" "); + cmd.append("-a \"Type=pshell\" "); + cmd.append("-a \"Entry=").append(entry).append("\" "); + cmd.append("-a \"Title=").append(title).append("\" "); + cmd.append("-a \"Category=").append(category).append("\" "); + cmd.append("-a \"Domain=").append(domain).append("\" "); + for (String attachment : attachments) { + cmd.append("-f \"").append(attachment).append("\" "); + } + cmd.append("-n 1 "); + cmd.append("\"").append(message).append("\" "); + System.out.println(cmd.toString()); + + final Process process = Runtime.getRuntime().exec(new String[]{"bash", "-c", cmd.toString()}); + new Thread(() -> { + try { + process.waitFor(); + int bytes = process.getInputStream().available(); + byte[] arr = new byte[bytes]; + process.getInputStream().read(arr, 0, bytes); + System.out.println(new String(arr)); + bytes = process.getErrorStream().available(); + arr = new byte[bytes]; + process.getErrorStream().read(arr, 0, bytes); + System.err.println(new String(arr)); + } catch (Exception ex) { + System.err.println(ex); + } + }).start(); + } + + void centralizeRenderer() { + Point center = null; + Dimension size = renderer.getImageSize(); + double zoom = (renderer.getMode() == RendererMode.Fixed) ? 1.0 : renderer.getZoom(); + if (renderer.getCalibration() != null) { + center = renderer.getCalibration().getCenter(); + } else if (size != null) { + center = new Point(size.width / 2, size.height / 2); + } + if (center != null) { + Point topleft = new Point(Math.max((int) (center.x - renderer.getWidth() / 2 / zoom), 0), + Math.max((int) (center.y - renderer.getHeight() / 2 / zoom), 0)); + renderer.setViewPosition(topleft); + } + } + + void updatePause() { + int index = ((int) pauseSelection.getValue()) - 1; + synchronized (imageBuffer) { + if (index < imageBuffer.size()) { + Data data = imageBuffer.get(index).data; + BufferedImage image = camera.generateImage(data); + renderer.setImage(renderer.getOrigin(), image, data); + imageBufferOverlay.update(Chrono.getTimeStr(data.getTimestamp(), "HH:mm:ss.SSS")); + manageFit(image, data); + manageUserOverlays(image, data); + } + } + } + + /* + void writeFrameMetadata(String path, Frame frame) throws Exception { + getContext().getDataManager().setAttribute("/", "Camera", String.valueOf(cameraName)); + getContext().getDataManager().setAttribute("/", "Screen", String.valueOf(valueScreen.getLabel().getText())); + getContext().getDataManager().setAttribute("/", "Filter", String.valueOf(valueFilter.getLabel().getText())); + Calibration cal = renderer.getCalibration(); + getContext().getDataManager().setAttribute("/", "Calibration", cal == null ? new double[]{1, 1, 0, 0} + : new double[]{cal.getScaleX(), cal.getScaleY(), cal.getOffsetX(), cal.getOffsetY()}); + getContext().getDataManager().setAttribute(path, "Timestamp", Chrono.getTimeStr(frame.data.getTimestamp(), "HH:mm:ss.SSS")); + if (server != null) { + try { + getContext().getDataManager().setAttribute("/", "ROI", server.getRoi()); + } catch (Exception ex) { + getContext().getDataManager().setAttribute("/", "ROI", new int[]{0, 0, -1, -1}); + } + if (frame != null) { + for (Field f : ImageData.class.getFields()) { + Object value = f.get(frame); + getContext().getDataManager().setAttribute(path, f.getName(), (value == null) ? Double.NaN : value); + } + } + for (String name : new String[]{"x_axis", "y_axis", "gr_x_axis", "gr_y_axis"}) { + double[] val = getServerDoubleArray(name); + getContext().getDataManager().setAttribute("/", "GoodRegion", goodRegion); + if (val != null) { + getContext().getDataManager().setAttribute("/", name, val); + } + } + } + } + */ + + void saveSnapshot() throws Exception { + /* + getContext().setExecutionPars("snapshot"); + String path = "/data"; + String snapshotFile = null; + synchronized (imageBuffer) { + Frame id = getCurrentFrame(); + if (id == null) { + throw new Exception("No current image"); + } + Object data = id.data.getMatrix(); + getContext().getDataManager().setDataset(path, data, id.data.isUnsigned()); + writeFrameMetadata(path, id); + getContext().getDataManager().closeOutput(); + //Enforce the same timestamp to data & image files. + //snapshotFile = getContext().getSetup().expandPath("{images}/{date}_{time}_snapshot.png", getContext().getExecutionPars().getStart()); + snapshotFile = getContext().getExecutionPars().getPath() + ".png"; + //renderer.saveSnapshot(snapshotFile, "png", true); + ImageBuffer.saveImage(SwingUtils.createImage(renderer), snapshotFile, "png"); + } + */ + String snapshotFile = null; + synchronized (imageBuffer) { + Frame frame = getCurrentFrame(); + if (frame == null) { + throw new Exception("No current image"); + } + ArrayList frames = new ArrayList<>(); + frames.add(frame); + this.saveFrames("camera_snapshot", frames); + + //Enforce the same timestamp to data & image files. + //snapshotFile = getContext().getSetup().expandPath("{images}/{date}_{time}_snapshot.png", getContext().getExecutionPars().getStart()); + snapshotFile = getContext().getExecutionPars().getPath() + ".png"; + //renderer.saveSnapshot(snapshotFile, "png", true); + ImageBuffer.saveImage(SwingUtils.createImage(renderer), snapshotFile, "png"); + } + + JPanel panel = new JPanel(); + GridBagLayout layout = new GridBagLayout(); + layout.columnWidths = new int[]{0, 180}; //Minimum width + layout.rowHeights = new int[]{30, 30, 30}; //Minimum height + panel.setLayout(layout); + JComboBox comboLogbook = new JComboBox(new String[]{"SwissFEL commissioning data", "SwissFEL commissioning"}); + JTextField textComment = new JTextField(); + GridBagConstraints c = new GridBagConstraints(); + c.gridx = 0; + c.gridy = 0; + panel.add(new JLabel("Data file:"), c); + c.gridy = 1; + panel.add(new JLabel("Logbook:"), c); + c.gridy = 2; + panel.add(new JLabel("Comment:"), c); + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + panel.add(textComment, c); + c.gridy = 1; + panel.add(comboLogbook, c); + c.gridy = 0; + panel.add(new JLabel(getContext().getExecutionPars().getPath()), c); + + if (SwingUtils.showOption(getTopLevel(), "Success", panel, OptionType.OkCancel) == OptionResult.Yes) { + StringBuilder message = new StringBuilder(); + message.append("Camera: ").append(cameraName).append(" ("). + append((server != null) ? "server" : "direct").append(")").append("\n"); + message.append("Screen: ").append(String.valueOf(valueScreen.getLabel().getText())).append("\n"); + message.append("Filter: ").append(String.valueOf(valueFilter.getLabel().getText())).append("\n"); + message.append("Data file: ").append(getContext().getExecutionPars().getPath()).append("\n"); + message.append("Comment: ").append(textComment.getText()).append("\n"); + if ((fitOv != null) && (fitOv.length > 5)) { + Overlays.Text text = (Overlays.Text) fitOv[5]; + message.append(text.getText()).append("\n"); + } + elog((String) comboLogbook.getSelectedItem(), "ScreenPanel Snapshot", message.toString(), new String[]{snapshotFile}); + } + //SwingUtils.showMessage(getTopLevel(), "Success", "Generated data file:\n" + getContext().getExecutionPars().getPath(), 5000); + //elog("SwissFEL commissioning data", "ScreenPanel Snapshot", message.toString(), new String[]{snapshotFile}); + } + + + + public static String getCameraType(String name){ + for (String s : new String[]{"LCAM"}){ + if (name.contains(s)){ + return "LCAM"; + } + } + for (String s : new String[]{"DSCR", "DSRM", "DLAC"}){ + if (name.contains(s)){ + return "ELECTRONS"; + } + } + for (String s : new String[]{"PROF", "PPRM", "PSSS", "PSCR", "PSRD"}){ + if (name.contains(s)){ + return "PHOTONICS"; + } + } + return "UNKNOWN"; + } + + public Map getProcessingParameters(StreamValue value) throws IOException { + return (Map) JsonSerializer.decode(value.getValue("processing_parameters").toString(), Map.class); + } + + void saveFrames(String name, ArrayList frames) throws IOException{ + ArrayList values = new ArrayList<>(); + for (Frame frame : frames){ + values.add(frame.cache); + } + saveImages(name, values); + } + + void saveImages(String name, ArrayList images) throws IOException{ + int depth = images.size(); + if (depth == 0){ + return; + } + StreamValue first = images.get(0); + String pathRoot = "/camera1/"; + String pathImage = pathRoot + "image"; + String pathPid = pathRoot + "pulse_id"; + String pathTimestampStr = pathRoot + "timestamp_str"; + Map processingPars = getProcessingParameters(first); + System.out.println(processingPars); + String camera = (String) processingPars.get("camera_name"); + String type = getCameraType(camera); + + int width = ((Number)first.getValue("width")).intValue(); + int height = ((Number)first.getValue("height")).intValue(); + Class dataType = first.getValue("image").getClass().getComponentType(); + + getContext().setExecutionPars(name); + DataManager dm = getContext().getDataManager(); + + //Create tables + dm.createDataset(pathImage, dataType, new int[]{depth, height, width}); + dm.createDataset(pathPid, Long.class, new int[]{depth}); + dm.createDataset(pathTimestampStr, String.class, new int[]{depth}); + for (String id : first.getIdentifiers()){ + Object val = first.getValue(id); + if (id.equals("image")){ + } else if (id.equals("processing_parameters")){ + Map pars = getProcessingParameters(first); + for (String key : pars.keySet()){ + if ((pars.get(key) != null) && (pars.get(key) instanceof Map)){ + for (Object k : ((Map)pars.get(key)).keySet()){ + Object v = ((Map)pars.get(key)).get(k); + dm.setAttribute(pathImage, key + " " + k, (v == null)? "" : v); + } + } else { + dm.setAttribute(pathImage, key, (pars.get(key) == null)? "" : pars.get(key)); + } + } + } else if (val.getClass().isArray()) { + dm.createDataset(pathRoot + id, Double.class, new int[]{depth, Array.getLength(val)}); + } else { + dm.createDataset(pathRoot + id, val.getClass(), new int[]{depth}); + } + } + + //Add metadata + dm.setAttribute(pathRoot,"Camera", camera); + dm.setAttribute(pathRoot,"Images", depth); + dm.setAttribute(pathRoot,"Interval", -1); + dm.setAttribute(pathRoot,"Type", type); + if (type.equals("ELECTRONS")){ + dm.setAttribute(pathRoot,"Screen", String.valueOf(valueScreen.getLabel().getText())); + dm.setAttribute(pathRoot,"Filter", String.valueOf(valueFilter.getLabel().getText())); + } + + //Save data + for (int index=0; index x = new ArrayList<>(); + ArrayList y = new ArrayList<>(); + synchronized (imageBuffer) { + for (int i = 0; i < imageBuffer.size(); i++) { + Frame frame = imageBuffer.get(i); + String path = "/data_" + i; + getContext().getDataManager().setDataset(path, frame.data.getMatrix(), frame.data.isUnsigned()); + writeFrameMetadata(path, frame); + x.add(frame.x_fit_mean); + y.add(frame.y_fit_mean); + } + } + DescStatsDouble xs = new DescStatsDouble(x.toArray(new Double[0]), -1); + DescStatsDouble ys = new DescStatsDouble(y.toArray(new Double[0]), -1); + + getContext().getDataManager().closeOutput(); + ) + */ + synchronized (imageBuffer) { + saveFrames("camera_stack", imageBuffer); + } + SwingUtils.showMessage(getTopLevel(), "Success", "Generated data file:\n" + getContext().getExecutionPars().getPath(), 5000); + } + + StandardDialog calibrationDialolg; + + void calibrate() throws Exception { + if (server != null) { + server.resetRoi(); + calibrationDialolg = (StandardDialog) getContext().getClassByName("CameraCalibrationDialog").getConstructors()[0].newInstance(new Object[]{getTopLevel(), server.getCurrentCamera(), renderer}); + SwingUtils.centerComponent(getTopLevel(), calibrationDialolg); + calibrationDialolg.setVisible(true); + calibrationDialolg.setListener(new StandardDialogListener() { + @Override + public void onWindowOpened(StandardDialog dlg) { + } + + @Override + public void onWindowClosed(StandardDialog dlg, boolean accepted) { + if (accepted) { + //comboCamerasActionPerformed(null); + } + } + }); + } + } + + StandardDialog dataTableDialog; + DefaultTableModel dataTableModel; + + void showStreamData() { + dataTableModel = null; + if (server != null) { + + if ((dataTableDialog != null) && (dataTableDialog.isShowing())) { + SwingUtils.centerComponent(getTopLevel(), dataTableDialog); + dataTableDialog.requestFocus(); + return; + } + //String msg = String.join("\n", ids); + //SwingUtils.showMessage(getTopLevel(), "Image Data", msg); + dataTableModel = new DefaultTableModel(new Object[0][2], new String[]{"Name", "Value"}) { + public Class getColumnClass(int columnIndex) { + return String.class; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } + }; + updateStreamData(); + StreamValue val = server.getStream().take(); + JTable dataTable = new JTable(dataTableModel); + dataTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + dataTable.setCellSelectionEnabled(true); + dataTable.getTableHeader().setReorderingAllowed(false); + dataTable.getTableHeader().setResizingAllowed(true); + dataTableDialog = new StandardDialog(getTopLevel(), "Image Data", false); + dataTableDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + JScrollPane scrollPane = new JScrollPane(); + scrollPane.setViewportView(dataTable); + scrollPane.setPreferredSize(new Dimension(300, 400)); + dataTableDialog.setContentPane(scrollPane); + dataTableDialog.pack(); + SwingUtils.centerComponent(getTopLevel(), dataTableDialog); + dataTableDialog.setVisible(true); + dataTableDialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + dataTableModel = null; + } + }); + } + } + + void updateStreamData() { + if ((dataTableModel != null) && (server != null)) { + StreamValue value = server.getValue(); + + List ids = (value == null) ? new ArrayList<>() : new ArrayList(value.getIdentifiers()); + if (ids.size() + 2 != dataTableModel.getRowCount()) { + dataTableModel.setNumRows(0); + try { + dataTableModel.addRow(new Object[]{"Locator", server.getUrl() + "/" + ((value == null) ? instanceName : server.getCurrentInstance())}); + } catch (Exception ex) { + dataTableModel.addRow(new Object[]{"Locator", ex.getMessage()}); + } + try { + dataTableModel.addRow(new Object[]{"Stream", server.getStreamAddress()}); + } catch (Exception ex) { + dataTableModel.addRow(new Object[]{"Stream", ex.getMessage()}); + } + Collections.sort(ids); + for (String id : ids) { + dataTableModel.addRow(new Object[]{id, ""}); + } + } + for (int i = 2; i < dataTableModel.getRowCount(); i++) { + String id = String.valueOf(dataTableModel.getValueAt(i, 0)); + Object obj = server.getValue(id); + if (obj != null) { + if (obj.getClass().isArray()) { + obj = obj.getClass().getComponentType().getSimpleName() + "[" + Array.getLength(obj) + "]"; + } else if (obj instanceof Double) { + obj = Convert.roundDouble((Double) obj, 1); + } else if (obj instanceof Float) { + obj = Convert.roundDouble((Float) obj, 1); + } + } + dataTableModel.setValueAt(String.valueOf(obj), i, 1); + } + } + } + + //////// + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + buttonGroup1 = new javax.swing.ButtonGroup(); + buttonGroup2 = new javax.swing.ButtonGroup(); + buttonGroup3 = new javax.swing.ButtonGroup(); + buttonGroup4 = new javax.swing.ButtonGroup(); + jProgressBar1 = new javax.swing.JProgressBar(); + jPanel1 = new javax.swing.JPanel(); + jPanel7 = new javax.swing.JPanel(); + buttonMarker = new javax.swing.JToggleButton(); + buttonGrabBackground = new javax.swing.JButton(); + buttonSave = new javax.swing.JToggleButton(); + buttonFit = new javax.swing.JToggleButton(); + buttonReticle = new javax.swing.JToggleButton(); + buttonPause = new javax.swing.JToggleButton(); + buttonProfile = new javax.swing.JToggleButton(); + jPanel6 = new javax.swing.JPanel(); + textState = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + comboCameras = new javax.swing.JComboBox(); + buttonConfig = new javax.swing.JButton(); + jLabel1 = new javax.swing.JLabel(); + buttonArgs = new javax.swing.JButton(); + buttonStop = new javax.swing.JButton(); + renderer = new ch.psi.pshell.imaging.Renderer(); + jPanel4 = new javax.swing.JPanel(); + jPanel3 = new javax.swing.JPanel(); + buttonZoomFit = new javax.swing.JRadioButton(); + buttonZoomStretch = new javax.swing.JRadioButton(); + buttonZoomNormal = new javax.swing.JRadioButton(); + buttonZoom025 = new javax.swing.JRadioButton(); + buttonZoom05 = new javax.swing.JRadioButton(); + buttonZoom2 = new javax.swing.JRadioButton(); + jPanel2 = new javax.swing.JPanel(); + checkHistogram = new javax.swing.JCheckBox(); + comboColormap = new javax.swing.JComboBox(); + jLabel3 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + buttonFullRange = new javax.swing.JRadioButton(); + buttonManual = new javax.swing.JRadioButton(); + buttonAutomatic = new javax.swing.JRadioButton(); + labelMin = new javax.swing.JLabel(); + spinnerMin = new javax.swing.JSpinner(); + spinnerMax = new javax.swing.JSpinner(); + labelMax = new javax.swing.JLabel(); + btFixColormapRange = new javax.swing.JButton(); + jPanel5 = new javax.swing.JPanel(); + buttonServer = new javax.swing.JRadioButton(); + buttonDirect = new javax.swing.JRadioButton(); + panelScreen = new javax.swing.JPanel(); + valueScreen = new ch.psi.pshell.swing.DeviceValuePanel(); + comboScreen = new javax.swing.JComboBox(); + panelScreen1 = new javax.swing.JPanel(); + valueFilter = new ch.psi.pshell.swing.DeviceValuePanel(); + comboFilter = new javax.swing.JComboBox(); + pauseSelection = new ch.psi.pshell.swing.ValueSelection(); + panelScreen2 = new javax.swing.JPanel(); + checkThreshold = new javax.swing.JCheckBox(); + spinnerThreshold = new javax.swing.JSpinner(); + checkBackground = new javax.swing.JCheckBox(); + checkGoodRegion = new javax.swing.JCheckBox(); + spinnerGrScale = new javax.swing.JSpinner(); + spinnerGrThreshold = new javax.swing.JSpinner(); + labelGrThreshold = new javax.swing.JLabel(); + labelGrScale = new javax.swing.JLabel(); + + setPreferredSize(new java.awt.Dimension(873, 600)); + + buttonMarker.setText("Marker"); + buttonMarker.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMarkerActionPerformed(evt); + } + }); + + buttonGrabBackground.setText("Grab Background"); + buttonGrabBackground.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonGrabBackgroundActionPerformed(evt); + } + }); + + buttonSave.setText("Save Snapshot"); + buttonSave.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonSaveActionPerformed(evt); + } + }); + + buttonFit.setSelected(true); + buttonFit.setText("Fit"); + buttonFit.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonFitActionPerformed(evt); + } + }); + + buttonReticle.setSelected(true); + buttonReticle.setText("Reticle"); + buttonReticle.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonReticleActionPerformed(evt); + } + }); + + buttonPause.setText("Pause"); + buttonPause.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPauseActionPerformed(evt); + } + }); + + buttonProfile.setSelected(true); + buttonProfile.setText("Profile"); + buttonProfile.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonProfileActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7); + jPanel7.setLayout(jPanel7Layout); + jPanel7Layout.setHorizontalGroup( + jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel7Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(buttonPause) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonMarker) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonProfile) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonFit) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonReticle) + .addGap(18, 18, Short.MAX_VALUE) + .addComponent(buttonGrabBackground) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonSave) + .addGap(0, 0, 0)) + ); + + jPanel7Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonFit, buttonMarker, buttonPause, buttonProfile, buttonReticle}); + + jPanel7Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonGrabBackground, buttonSave}); + + jPanel7Layout.setVerticalGroup( + jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel7Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonPause) + .addComponent(buttonFit) + .addComponent(buttonMarker) + .addComponent(buttonSave) + .addComponent(buttonReticle) + .addComponent(buttonGrabBackground) + .addComponent(buttonProfile)) + .addGap(0, 0, 0)) + ); + + textState.setEditable(false); + textState.setHorizontalAlignment(javax.swing.JTextField.CENTER); + textState.setDisabledTextColor(new java.awt.Color(0, 0, 0)); + textState.setEnabled(false); + + jLabel2.setText("State:"); + + comboCameras.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N + comboCameras.setMaximumRowCount(30); + comboCameras.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + comboCamerasActionPerformed(evt); + } + }); + + buttonConfig.setText("Config"); + buttonConfig.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonConfigActionPerformed(evt); + } + }); + + jLabel1.setText("Camera:"); + + buttonArgs.setText("Setup"); + buttonArgs.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonArgsActionPerformed(evt); + } + }); + + buttonStop.setText("Stop"); + buttonStop.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonStopActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6); + jPanel6.setLayout(jPanel6Layout); + jPanel6Layout.setHorizontalGroup( + jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel6Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(comboCameras, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonArgs) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonConfig) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonStop) + .addGap(18, 18, 18) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(textState, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0)) + ); + + jPanel6Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonArgs, buttonConfig, buttonStop}); + + jPanel6Layout.setVerticalGroup( + jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel6Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(comboCameras, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel2) + .addComponent(textState, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonArgs) + .addComponent(buttonConfig) + .addComponent(buttonStop)) + .addGap(0, 0, 0)) + ); + + jPanel6Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {comboCameras, textState}); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(renderer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(renderer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Zoom")); + + buttonGroup1.add(buttonZoomFit); + buttonZoomFit.setText("Fit"); + buttonZoomFit.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoomFitActionPerformed(evt); + } + }); + + buttonGroup1.add(buttonZoomStretch); + buttonZoomStretch.setText("Stretch"); + buttonZoomStretch.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoomStretchActionPerformed(evt); + } + }); + + buttonGroup1.add(buttonZoomNormal); + buttonZoomNormal.setText("Normal"); + buttonZoomNormal.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoomNormalActionPerformed(evt); + } + }); + + buttonGroup1.add(buttonZoom025); + buttonZoom025.setText("1/4"); + buttonZoom025.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoom025ActionPerformed(evt); + } + }); + + buttonGroup1.add(buttonZoom05); + buttonZoom05.setText("1/2"); + buttonZoom05.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoom05ActionPerformed(evt); + } + }); + + buttonGroup1.add(buttonZoom2); + buttonZoom2.setText("2"); + buttonZoom2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoom2ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonZoomFit) + .addComponent(buttonZoomNormal) + .addComponent(buttonZoomStretch)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonZoom025) + .addComponent(buttonZoom05) + .addComponent(buttonZoom2)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonZoomNormal) + .addComponent(buttonZoom025)) + .addGap(0, 0, 0) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonZoomFit) + .addComponent(buttonZoom05)) + .addGap(0, 0, 0) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonZoomStretch) + .addComponent(buttonZoom2)) + .addContainerGap()) + ); + + jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Colormap")); + + checkHistogram.setText("Histogram"); + checkHistogram.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkHistogramActionPerformed(evt); + } + }); + + comboColormap.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + onChangeColormap(evt); + } + }); + + jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel3.setText("Type:"); + + jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel4.setText("Range:"); + + buttonGroup3.add(buttonFullRange); + buttonFullRange.setText("Full"); + buttonFullRange.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + onChangeColormap(evt); + } + }); + + buttonGroup3.add(buttonManual); + buttonManual.setText("Manual"); + buttonManual.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + onChangeColormap(evt); + } + }); + + buttonGroup3.add(buttonAutomatic); + buttonAutomatic.setText("Automatic"); + buttonAutomatic.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + onChangeColormap(evt); + } + }); + + labelMin.setText("Min:"); + + spinnerMin.setModel(new javax.swing.SpinnerNumberModel(0, 0, 65535, 1)); + spinnerMin.setEnabled(false); + spinnerMin.setPreferredSize(new java.awt.Dimension(77, 20)); + spinnerMin.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + onChangeColormapRange(evt); + } + }); + + spinnerMax.setModel(new javax.swing.SpinnerNumberModel(255, 0, 65535, 1)); + spinnerMax.setEnabled(false); + spinnerMax.setPreferredSize(new java.awt.Dimension(77, 20)); + spinnerMax.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + onChangeColormapRange(evt); + } + }); + + labelMax.setText("Max:"); + + btFixColormapRange.setText("Fix"); + btFixColormapRange.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btFixColormapRangeActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel3) + .addComponent(jLabel4)) + .addGap(4, 4, 4) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonAutomatic) + .addComponent(buttonFullRange) + .addComponent(buttonManual) + .addComponent(comboColormap, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 12, Short.MAX_VALUE) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() + .addComponent(labelMax) + .addGap(2, 2, 2) + .addComponent(spinnerMax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(checkHistogram, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() + .addComponent(labelMin) + .addGap(2, 2, 2) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btFixColormapRange, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(spinnerMin, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + .addContainerGap()) + ); + + jPanel2Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {btFixColormapRange, spinnerMax, spinnerMin}); + + jPanel2Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel3, jLabel4}); + + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(comboColormap, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel3) + .addComponent(checkHistogram)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonAutomatic) + .addComponent(jLabel4) + .addComponent(btFixColormapRange, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 0, 0) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(labelMin) + .addComponent(spinnerMin, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonFullRange)) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonManual) + .addComponent(labelMax) + .addComponent(spinnerMax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder("Source")); + + buttonGroup4.add(buttonServer); + buttonServer.setSelected(true); + buttonServer.setText("Server"); + buttonServer.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonServerActionPerformed(evt); + } + }); + + buttonGroup4.add(buttonDirect); + buttonDirect.setText("Direct"); + buttonDirect.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonDirectActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); + jPanel5.setLayout(jPanel5Layout); + jPanel5Layout.setHorizontalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addContainerGap() + .addComponent(buttonServer) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonDirect) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel5Layout.setVerticalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonServer) + .addComponent(buttonDirect)) + .addContainerGap()) + ); + + panelScreen.setBorder(javax.swing.BorderFactory.createTitledBorder("Screen")); + + comboScreen.setEnabled(false); + comboScreen.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + comboScreenActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelScreenLayout = new javax.swing.GroupLayout(panelScreen); + panelScreen.setLayout(panelScreenLayout); + panelScreenLayout.setHorizontalGroup( + panelScreenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelScreenLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelScreenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(valueScreen, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(comboScreen, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + panelScreenLayout.setVerticalGroup( + panelScreenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelScreenLayout.createSequentialGroup() + .addGap(4, 4, 4) + .addComponent(comboScreen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(valueScreen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + panelScreen1.setBorder(javax.swing.BorderFactory.createTitledBorder("Filter")); + + comboFilter.setEnabled(false); + comboFilter.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + comboFilterActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelScreen1Layout = new javax.swing.GroupLayout(panelScreen1); + panelScreen1.setLayout(panelScreen1Layout); + panelScreen1Layout.setHorizontalGroup( + panelScreen1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelScreen1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(panelScreen1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(valueFilter, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(comboFilter, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + panelScreen1Layout.setVerticalGroup( + panelScreen1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelScreen1Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addComponent(comboFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(valueFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + pauseSelection.setDecimals(0); + + panelScreen2.setBorder(javax.swing.BorderFactory.createTitledBorder("Image")); + + checkThreshold.setText("Threshold"); + checkThreshold.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkThresholdActionPerformed(evt); + } + }); + + spinnerThreshold.setModel(new javax.swing.SpinnerNumberModel(0.0d, 0.0d, 99999.0d, 1.0d)); + spinnerThreshold.setPreferredSize(new java.awt.Dimension(77, 20)); + spinnerThreshold.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerThresholdonChange(evt); + } + }); + + checkBackground.setText("Subtract Background"); + checkBackground.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkBackgroundActionPerformed(evt); + } + }); + + checkGoodRegion.setText("Good Region"); + checkGoodRegion.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkGoodRegionActionPerformed(evt); + } + }); + + spinnerGrScale.setModel(new javax.swing.SpinnerNumberModel(3.0d, 0.01d, 100.0d, 1.0d)); + spinnerGrScale.setPreferredSize(new java.awt.Dimension(77, 20)); + spinnerGrScale.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerGrThresholdonChange(evt); + } + }); + + spinnerGrThreshold.setModel(new javax.swing.SpinnerNumberModel(0.5d, 0.04d, 1.0d, 0.1d)); + spinnerGrThreshold.setPreferredSize(new java.awt.Dimension(77, 20)); + spinnerGrThreshold.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerGrThresholdonChange(evt); + } + }); + + labelGrThreshold.setText("Threshold:"); + + labelGrScale.setText("Scale:"); + + javax.swing.GroupLayout panelScreen2Layout = new javax.swing.GroupLayout(panelScreen2); + panelScreen2.setLayout(panelScreen2Layout); + panelScreen2Layout.setHorizontalGroup( + panelScreen2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelScreen2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(panelScreen2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelScreen2Layout.createSequentialGroup() + .addComponent(checkGoodRegion) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(labelGrScale) + .addGap(2, 2, 2) + .addComponent(spinnerGrScale, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelScreen2Layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(labelGrThreshold) + .addGap(2, 2, 2) + .addComponent(spinnerGrThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(panelScreen2Layout.createSequentialGroup() + .addComponent(checkBackground) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(panelScreen2Layout.createSequentialGroup() + .addComponent(checkThreshold) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(spinnerThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap()) + ); + + panelScreen2Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spinnerGrScale, spinnerGrThreshold, spinnerThreshold}); + + panelScreen2Layout.setVerticalGroup( + panelScreen2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelScreen2Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addComponent(checkBackground) + .addGap(2, 2, 2) + .addGroup(panelScreen2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(checkThreshold) + .addComponent(spinnerThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(panelScreen2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(checkGoodRegion) + .addComponent(spinnerGrScale, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelGrScale)) + .addGap(2, 2, 2) + .addGroup(panelScreen2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerGrThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelGrThreshold)) + .addContainerGap()) + ); + + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelScreen, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelScreen1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pauseSelection, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(panelScreen2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel4Layout.setVerticalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelScreen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelScreen1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelScreen2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pauseSelection, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + ); + }// //GEN-END:initComponents + + private void comboCamerasActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboCamerasActionPerformed + try { + if (!updatingCameraSelection) { + if (!comboCameras.isEnabled()) { + throw new Exception("Invalid state"); + } + comboCameras.setEnabled(false); + buttonServer.setEnabled(false); + buttonDirect.setEnabled(false); + final String cameraName = (String) comboCameras.getSelectedItem(); + new Thread(new Runnable() { + @Override + public void run() { + if (requestCameraListUpdate) { + requestCameraListUpdate = false; + try { + updateCameraList(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + try { + setCamera(cameraName); + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + updateStop(); + comboCameras.setEnabled(true); + buttonServer.setEnabled(true); + buttonDirect.setEnabled(true); + } + } + }).start(); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_comboCamerasActionPerformed + + private void buttonArgsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonArgsActionPerformed + try { + if (camera != null) { + String cameraConfigJson = null; + if (usingServer) { + String cameraServerUrl = server.getUrl().substring(0, server.getUrl().length() - 1) + "8"; + try (CameraServer srv = new CameraServer("CamServer", cameraServerUrl)) { + srv.initialize(); + //TODO: replace into encodeMultiline + cameraConfigJson = JsonSerializer.encode(srv.getConfig(cameraName), true); + } + + } else { + String configFolder = (String) getContext().getClassByName("SfCamera").getMethod("getConfigFolder", new Class[]{}).invoke(null); + Path configFile = Paths.get(configFolder, cameraName + ".json"); + cameraConfigJson = configFile.toFile().exists() ? new String(Files.readAllBytes(configFile)) : null; + } + TextEditor editor = new TextEditor(); + editor.setText(cameraConfigJson); + editor.setReadOnly(true); + editor.setTitle(cameraName); + EditorDialog dlg = editor.getDialog(getTopLevel(), false); + dlg.setSize(480, 640); + dlg.setVisible(true); + SwingUtils.centerComponent(getTopLevel(), dlg); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonArgsActionPerformed + + private void buttonConfigActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonConfigActionPerformed + try { + if (camera != null) { + this.showDeviceConfigDialog(camera, false); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonConfigActionPerformed + + private void buttonPauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPauseActionPerformed + try { + renderer.removeOverlay(imageBufferOverlay); + if (camera != null) { + synchronized (imageBuffer) { + if (buttonPause.isSelected()) { + renderer.pause(); + } else { + imageBuffer.clear(); + renderer.resume(); + } + pauseSelection.setVisible(buttonPause.isSelected() && (imageBuffer.size() > 1)); + if (pauseSelection.isVisible()) { + renderer.addOverlay(imageBufferOverlay); + pauseSelection.setMaxValue(imageBuffer.size()); + pauseSelection.setValue(imageBuffer.size());; + } + } + updateStreamData(); + } + } catch (Exception ex) { + ex.printStackTrace(); + showException(ex); + } + }//GEN-LAST:event_buttonPauseActionPerformed + + private void buttonMarkerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMarkerActionPerformed + try { + checkMarker(); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonMarkerActionPerformed + + private void buttonFitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonFitActionPerformed + try { + showFit = buttonFit.isSelected(); + if (showFit) { + renderer.setProfile(Renderer.Profile.None); + } else { + renderer.removeOverlays(fitOv); + fitOv = null; + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonFitActionPerformed + + private void buttonReticleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonReticleActionPerformed + try { + checkReticle(); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonReticleActionPerformed + + private void buttonSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveActionPerformed + try { + saveSnapshot(); + } catch (Exception ex) { + ex.printStackTrace(); + showException(ex); + } + }//GEN-LAST:event_buttonSaveActionPerformed + + private void buttonGrabBackgroundActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonGrabBackgroundActionPerformed + try { + if (camera != null) { + if (SwingUtils.showOption(getTopLevel(), "Background", "Do you want to capture background now?", OptionType.YesNo) == OptionResult.Yes) { + boolean laserOn = getLaserState(); + if (laserOn) { + setLaserState(false); + } + try { + System.out.println("Grabbing background for: " + cameraName); + if (server != null) { + server.captureBackground(5); + } else { + camera.captureBackground(5, 0); + } + } finally { + if (laserOn) { + setLaserState(true); + } + } + SwingUtils.showMessage(getTopLevel(), "Success", "Success capturing background", 5000); + } + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonGrabBackgroundActionPerformed + + private void buttonZoomFitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoomFitActionPerformed + try { + renderer.setMode(RendererMode.Fit); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonZoomFitActionPerformed + + private void buttonZoomStretchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoomStretchActionPerformed + try { + renderer.setMode(RendererMode.Stretch); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonZoomStretchActionPerformed + + private void buttonZoomNormalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoomNormalActionPerformed + try { + renderer.setMode(RendererMode.Fixed); + centralizeRenderer(); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonZoomNormalActionPerformed + + private void onChangeColormap(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onChangeColormap + try { + if ((camera != null) && (camera instanceof ColormapSource) && !updatingColormap) { + ColormapSource source = (ColormapSource) camera; + Color colorReticule = new Color(16, 16, 16); + Color colorMarker = new Color(128, 128, 128); + source.getConfig().colormap = (Colormap) comboColormap.getSelectedItem(); + switch (source.getConfig().colormap) { + case Grayscale: + case Inverted: + colorReticule = new Color(0, 192, 0); + colorMarker = new Color(64, 255, 64); + break; + case Flame: + colorReticule = new Color(0, 192, 0); + colorMarker = new Color(64, 255, 64); + break; + } + + renderer.setPenReticle(new Pen(colorReticule)); + renderer.setPenProfile(new Pen(colorReticule, 0)); + renderer.setPenMarker(new Pen(colorMarker, 2)); + renderer.setShowReticle(false); + checkReticle(); + source.getConfig().colormapAutomatic = buttonAutomatic.isSelected(); + source.getConfig().colormapMin = buttonFullRange.isSelected() ? Double.NaN : (Integer) spinnerMin.getValue(); + source.getConfig().colormapMax = buttonFullRange.isSelected() ? Double.NaN : (Integer) spinnerMax.getValue(); + try { + source.getConfig().save(); + } catch (Exception ex) { + Logger.getLogger(ScreenPanel1.class.getName()).log(Level.WARNING, null, ex); + } + source.refresh(); + if (buttonPause.isSelected()) { + updatePause(); + } + updateColormap(); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_onChangeColormap + + private void onChangeColormapRange(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_onChangeColormapRange + onChangeColormap(null); + }//GEN-LAST:event_onChangeColormapRange + + private void buttonZoom025ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoom025ActionPerformed + renderer.setZoom(0.25); + renderer.setMode(RendererMode.Zoom); + centralizeRenderer(); + }//GEN-LAST:event_buttonZoom025ActionPerformed + + private void buttonZoom05ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoom05ActionPerformed + renderer.setZoom(0.5); + renderer.setMode(RendererMode.Zoom); + centralizeRenderer(); + }//GEN-LAST:event_buttonZoom05ActionPerformed + + private void buttonServerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonServerActionPerformed + if (!usingServer) { + usingServer = true; + requestCameraListUpdate = true; + } + comboCamerasActionPerformed(null); + }//GEN-LAST:event_buttonServerActionPerformed + + private void buttonDirectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDirectActionPerformed + if (usingServer) { + usingServer = false; + requestCameraListUpdate = true; + } + comboCamerasActionPerformed(null); + }//GEN-LAST:event_buttonDirectActionPerformed + + private void comboScreenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboScreenActionPerformed + + comboScreen.setEnabled(false); + new Thread(new Runnable() { + @Override + public void run() { + ChannelInteger setpoint = null; + try { + int index = comboScreen.getSelectedIndex(); + if (cameraName.contains("DSRM")) { + setpoint = new ChannelInteger(null, cameraName + ":POSITION_SP"); + } else { + setpoint = new ChannelInteger(null, cameraName + ":SET_SCREEN1_POS"); + } + setpoint.initialize(); + if (setpoint.read() != index) { + setpoint.write(index); + //Must be threaded to control the laser because of sleep in setLaserState + /* + boolean laserOn = getLaserState(); + if (laserOn) { + setLaserState(false); + } + try { + setpoint.write(index); + } finally { + if (laserOn) { + setLaserState(true); + } + } + */ + } + screen.read(); + } catch (Exception ex) { + showException(ex); + } finally { + comboScreen.setEnabled(true); + if (setpoint != null) { + setpoint.close(); + } + } + } + }).start(); + }//GEN-LAST:event_comboScreenActionPerformed + + private void comboFilterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboFilterActionPerformed + try { + String setpoint = (String) comboFilter.getSelectedItem(); + if (!setpoint.equals(filter.read())) { + filter.write(setpoint); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_comboFilterActionPerformed + + private void checkHistogramActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkHistogramActionPerformed + try { + setHistogramVisible(checkHistogram.isSelected()); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_checkHistogramActionPerformed + + private void buttonZoom2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoom2ActionPerformed + renderer.setZoom(2.0); + renderer.setMode(RendererMode.Zoom); + centralizeRenderer(); + }//GEN-LAST:event_buttonZoom2ActionPerformed + + private void spinnerThresholdonChange(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerThresholdonChange + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + server.setThreshold((Double) spinnerThreshold.getValue()); + } + } catch (Exception ex) { + showException(ex); + updateServerControls(); + } + } + }//GEN-LAST:event_spinnerThresholdonChange + + private void checkBackgroundActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkBackgroundActionPerformed + if (server != null) { + if (!updatingServerControls) { + try { + if (server.isStarted()) { + server.setBackgroundSubtraction(checkBackground.isSelected()); + } + } catch (Exception ex) { + showException(ex); + updateServerControls(); + updatingServerControls = true; + checkBackground.setSelected(false); + updatingServerControls = false; + + } + } + } else { + camera.setBackgroundEnabled(checkBackground.isSelected()); + } + }//GEN-LAST:event_checkBackgroundActionPerformed + + private void checkThresholdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkThresholdActionPerformed + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + spinnerThreshold.setVisible(checkThreshold.isSelected()); + server.setThreshold(checkThreshold.isSelected() ? (Double) spinnerThreshold.getValue() : null); + } + } catch (Exception ex) { + showException(ex); + updateServerControls(); + } + } + }//GEN-LAST:event_checkThresholdActionPerformed + + private void buttonStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStopActionPerformed + try { + if (buttonStop.getText().equals("Stop")) { + if ((camera != null) && !camera.isClosed()) { + camera.close(); + } + } else { + if (isCameraStopped()) { + comboCamerasActionPerformed(null); + } + } + } catch (Exception ex) { + showException(ex); + } finally { + updateStop(); + } + }//GEN-LAST:event_buttonStopActionPerformed + + private void buttonProfileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonProfileActionPerformed + try { + showProfile = buttonProfile.isSelected(); + if (showProfile) { + renderer.setProfile(Renderer.Profile.None); + } else { + renderer.removeOverlays(profileOv); + profileOv = null; + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonProfileActionPerformed + + private void checkGoodRegionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkGoodRegionActionPerformed + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + spinnerGrScale.setVisible(checkGoodRegion.isSelected()); + labelGrScale.setVisible(spinnerGrScale.isVisible()); + spinnerGrThreshold.setVisible(checkGoodRegion.isSelected()); + labelGrThreshold.setVisible(spinnerGrThreshold.isVisible()); + if (checkGoodRegion.isSelected()) { + server.setGoodRegion(((Number) spinnerGrThreshold.getValue()).doubleValue(), ((Number) spinnerGrScale.getValue()).doubleValue()); + } else { + server.setGoodRegion(null); + } + goodRegion = checkGoodRegion.isSelected(); + } + } catch (Exception ex) { + showException(ex); + ex.printStackTrace(); + updateServerControls(); + } + } + }//GEN-LAST:event_checkGoodRegionActionPerformed + + private void spinnerGrThresholdonChange(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerGrThresholdonChange + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + server.setGoodRegion((Double) spinnerGrThreshold.getValue(), (Double) spinnerGrScale.getValue()); + } + } catch (Exception ex) { + showException(ex); + updateServerControls(); + } + } + }//GEN-LAST:event_spinnerGrThresholdonChange + + private void btFixColormapRangeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btFixColormapRangeActionPerformed + try { + updatingColormap = true; + ArrayProperties properties = currentFrame.data.getProperties(); + spinnerMax.setValue(properties.max.intValue()); + spinnerMin.setValue(properties.min.intValue()); + buttonManual.setSelected(true); + } catch (Exception ex) { + showException(ex); + } finally { + updatingColormap = false; + onChangeColormap(null); + } + }//GEN-LAST:event_btFixColormapRangeActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btFixColormapRange; + private javax.swing.JButton buttonArgs; + private javax.swing.JRadioButton buttonAutomatic; + private javax.swing.JButton buttonConfig; + private javax.swing.JRadioButton buttonDirect; + private javax.swing.JToggleButton buttonFit; + private javax.swing.JRadioButton buttonFullRange; + private javax.swing.JButton buttonGrabBackground; + private javax.swing.ButtonGroup buttonGroup1; + private javax.swing.ButtonGroup buttonGroup2; + private javax.swing.ButtonGroup buttonGroup3; + private javax.swing.ButtonGroup buttonGroup4; + private javax.swing.JRadioButton buttonManual; + private javax.swing.JToggleButton buttonMarker; + private javax.swing.JToggleButton buttonPause; + private javax.swing.JToggleButton buttonProfile; + private javax.swing.JToggleButton buttonReticle; + private javax.swing.JToggleButton buttonSave; + private javax.swing.JRadioButton buttonServer; + private javax.swing.JButton buttonStop; + private javax.swing.JRadioButton buttonZoom025; + private javax.swing.JRadioButton buttonZoom05; + private javax.swing.JRadioButton buttonZoom2; + private javax.swing.JRadioButton buttonZoomFit; + private javax.swing.JRadioButton buttonZoomNormal; + private javax.swing.JRadioButton buttonZoomStretch; + private javax.swing.JCheckBox checkBackground; + private javax.swing.JCheckBox checkGoodRegion; + private javax.swing.JCheckBox checkHistogram; + private javax.swing.JCheckBox checkThreshold; + private javax.swing.JComboBox comboCameras; + private javax.swing.JComboBox comboColormap; + private javax.swing.JComboBox comboFilter; + private javax.swing.JComboBox comboScreen; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel4; + private javax.swing.JPanel jPanel5; + private javax.swing.JPanel jPanel6; + private javax.swing.JPanel jPanel7; + private javax.swing.JProgressBar jProgressBar1; + private javax.swing.JLabel labelGrScale; + private javax.swing.JLabel labelGrThreshold; + private javax.swing.JLabel labelMax; + private javax.swing.JLabel labelMin; + private javax.swing.JPanel panelScreen; + private javax.swing.JPanel panelScreen1; + private javax.swing.JPanel panelScreen2; + private ch.psi.pshell.swing.ValueSelection pauseSelection; + private ch.psi.pshell.imaging.Renderer renderer; + private javax.swing.JSpinner spinnerGrScale; + private javax.swing.JSpinner spinnerGrThreshold; + private javax.swing.JSpinner spinnerMax; + private javax.swing.JSpinner spinnerMin; + private javax.swing.JSpinner spinnerThreshold; + private javax.swing.JTextField textState; + private ch.psi.pshell.swing.DeviceValuePanel valueFilter; + private ch.psi.pshell.swing.DeviceValuePanel valueScreen; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/ScreenPanel11.form b/plugins/ScreenPanel11.form new file mode 100644 index 0000000..c169e3f --- /dev/null +++ b/plugins/ScreenPanel11.form @@ -0,0 +1,1347 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/ScreenPanel11.java b/plugins/ScreenPanel11.java new file mode 100644 index 0000000..f6878b6 --- /dev/null +++ b/plugins/ScreenPanel11.java @@ -0,0 +1,4495 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.pshell.bs.CameraServer; +import ch.psi.pshell.core.Context; +import java.io.IOException; +import java.nio.file.Paths; +import javax.swing.DefaultComboBoxModel; +import ch.psi.pshell.ui.Panel; +import ch.psi.pshell.imaging.ImageListener; +import ch.psi.utils.State; +import ch.psi.utils.Chrono; +import ch.psi.utils.swing.SwingUtils; +import ch.psi.utils.swing.TextEditor; +import ch.psi.pshell.bs.PipelineServer; +import ch.psi.pshell.bs.StreamValue; +import ch.psi.pshell.core.JsonSerializer; +import ch.psi.pshell.data.DataManager; +import ch.psi.pshell.device.Device; +import ch.psi.pshell.epics.ChannelInteger; +import ch.psi.pshell.epics.DiscretePositioner; +import ch.psi.pshell.epics.Epics; +import ch.psi.pshell.imaging.Colormap; +import ch.psi.pshell.imaging.ColormapSource; +import ch.psi.pshell.imaging.ColormapSource.ColormapSourceConfig; +import ch.psi.pshell.ui.App; +import ch.psi.pshell.imaging.Data; +import ch.psi.pshell.imaging.DimensionDouble; +import ch.psi.pshell.imaging.Histogram; +import ch.psi.pshell.imaging.ImageBuffer; +import ch.psi.pshell.imaging.Overlay; +import ch.psi.pshell.imaging.Overlays; +import ch.psi.pshell.imaging.Overlays.Text; +import ch.psi.pshell.imaging.Pen; +import ch.psi.pshell.imaging.PointDouble; +import ch.psi.pshell.imaging.Renderer; +import ch.psi.pshell.imaging.RendererListener; +import ch.psi.pshell.imaging.RendererMode; +import ch.psi.pshell.imaging.Source; +import ch.psi.pshell.scripting.InterpreterResult; +import ch.psi.pshell.scripting.ScriptManager; +import ch.psi.pshell.swing.DevicePanel; +import ch.psi.pshell.swing.ValueSelection; +import ch.psi.pshell.swing.ValueSelection.ValueSelectionListener; +import ch.psi.pshell.ui.Console; +import ch.psi.utils.Arr; +import ch.psi.utils.ArrayProperties; +import ch.psi.utils.Config; +import ch.psi.utils.Convert; +import ch.psi.utils.Str; +import ch.psi.utils.swing.Editor.EditorDialog; +import ch.psi.utils.swing.MainFrame; +import ch.psi.utils.swing.StandardDialog; +import ch.psi.utils.swing.StandardDialog.StandardDialogListener; +import ch.psi.utils.swing.SwingUtils.OptionResult; +import ch.psi.utils.swing.SwingUtils.OptionType; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileInputStream; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.JTextField; +import javax.swing.SpinnerNumberModel; +import javax.swing.SwingUtilities; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import org.apache.commons.math3.analysis.function.Gaussian; +import org.apache.commons.math3.fitting.GaussianCurveFitter; +import org.apache.commons.math3.fitting.PolynomialCurveFitter; +import org.apache.commons.math3.fitting.WeightedObservedPoint; +import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; + +/** + * + */ +public class ScreenPanel11 extends Panel { + + public static final String ARG_TYPE = "cam_type"; + public static final String ARG_LIST = "cam_list"; + public static final String ARG_ALIAS = "alias"; + + public static final String LASER_TYPE = "Laser"; + public static final String ELECTRONS_TYPE = "Electrons"; + public static final String PHOTONICS_TYPE = "Photonics"; + public static final String TWO_PULSES_TYPE = "2Pulses"; + + public static final int STACK_RETRIES = 10; + + final String CAMERA_DEVICE_NAME = "CurrentCamera"; + boolean useServerStats = true; + String userOverlaysConfigFile; + ColormapSource camera; + PipelineServer server; + String cameraName; + String cameraAlias; + int polling = 1000; + Overlay marker = null; + JDialog histogramDialog; + DiscretePositioner screen; + DiscretePositioner filter; + boolean showFit; + boolean showProfile; + Overlay[] userOv; + Overlay[] fitOv; + Overlay[] profileOv; + Overlay errorOverlay; + boolean requestCameraListUpdate; + boolean goodRegion; + boolean slicing; + String serverUrl; + String camServerUrl; + String instanceName; + Overlay titleOv = null; + Overlay backgOv = null; + boolean persistCameraState; + Map> groups; + Map aliases; + final Logger logger; + List types; + boolean isUrl; + boolean isPipeline; + DevicePanel streamPanel; + + public class CameraState extends Config { + + public boolean valid; + public boolean showSidePanel; + public boolean showProfile; + public boolean showFit; + public boolean showReticle; + public boolean showScale; + public boolean showTitle; + public double zoom; + public RendererMode mode; + public boolean colormapAutomatic; + public double colormapMin; + public double colormapMax; + public Colormap colormap; + public boolean colormapLogarithmic; + + String getFile() { + if (camera == null) { + return null; + } + return getContext().getSetup().expandPath("{context}/screen_panel/" + cameraName + ".properties"); + } + } + + void loadCameraState() { + if (persistCameraState) { + try { + CameraState state = new CameraState(); + state.load(state.getFile()); + if (state.valid) { + buttonSidePanel.setSelected(state.showSidePanel); + buttonSidePanelActionPerformed(null); + buttonProfile.setSelected(state.showProfile); + buttonProfileActionPerformed(null); + buttonFit.setSelected(state.showFit); + buttonFitActionPerformed(null); + buttonReticle.setSelected(state.showReticle); + buttonReticleActionPerformed(null); + buttonScale.setSelected(state.showScale); + buttonScaleActionPerformed(null); + buttonTitle.setSelected(state.showTitle); + buttonTitleActionPerformed(null); + renderer.setMode(state.mode); + renderer.setZoom(state.zoom); + if (camera instanceof ColormapSource) { + camera.getConfig().colormap = state.colormap; + camera.getConfig().colormapAutomatic = state.colormapAutomatic; + camera.getConfig().colormapLogarithmic = state.colormapLogarithmic; + camera.getConfig().colormapMax = state.colormapMax; + camera.getConfig().colormapMin = state.colormapMin; + updateColormap(); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + void saveCameraState() { + if (persistCameraState) { + try { + CameraState state = new CameraState(); + state.valid = true; + if (camera instanceof ColormapSource) { + state.colormap = camera.getConfig().colormap; + state.colormapAutomatic = camera.getConfig().colormapAutomatic; + state.colormapLogarithmic = camera.getConfig().colormapLogarithmic; + state.colormapMax = camera.getConfig().colormapMax; + state.colormapMin = camera.getConfig().colormapMin; + } + state.mode = renderer.getMode(); + state.zoom = renderer.getZoom(); + + state.showSidePanel = buttonSidePanel.isSelected(); + state.showProfile = buttonProfile.isSelected(); + state.showFit = buttonFit.isSelected(); + state.showReticle = buttonReticle.isSelected(); + state.showScale = buttonScale.isSelected(); + state.showTitle = buttonTitle.isSelected(); + + state.save(state.getFile()); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + String pipelineSuffix = "_sp"; + + Double getServerDouble(String name) { + return (Double) Convert.toDouble(server.getValue(name)); + } + + double[] getServerDoubleArray(String name) { + return (double[]) Convert.toDouble(server.getValue(name)); + } + + class ImageData { + + ImageData() { + if (server != null) { + cache = server.getStream().take(); + String prefix = goodRegion ? "gr_" : ""; + x_fit_mean = getDouble(prefix + "x_fit_mean"); + y_fit_mean = getDouble(prefix + "y_fit_mean"); + x_fit_standard_deviation = getDouble(prefix + "x_fit_standard_deviation"); + y_fit_standard_deviation = getDouble(prefix + "y_fit_standard_deviation"); + x_fit_gauss_function = getDoubleArray(prefix + "x_fit_gauss_function"); + y_fit_gauss_function = getDoubleArray(prefix + "y_fit_gauss_function"); + x_profile = getDoubleArray("x_profile"); + y_profile = getDoubleArray("y_profile"); + x_center_of_mass = getDouble("x_center_of_mass"); + y_center_of_mass = getDouble("y_center_of_mass"); + x_rms = getDouble("x_rms"); + y_rms = getDouble("y_rms"); + if (goodRegion) { + double[] gX2 = new double[x_profile.length]; + Arrays.fill(gX2, Double.NaN); + try { + double[] axis = getDoubleArray("x_axis"); + gr_x_axis = getDoubleArray("gr_x_axis"); + double x = gr_x_axis[0]; + gr_size_x = x_fit_gauss_function.length; + //If gr axis values are not identical, calculate the index... + gr_pos_x = (int) ((renderer.getCalibration() != null) ? renderer.getCalibration().convertToImageX(x) : x); + //But prefer checking the value to avoid raounding errors + for (int i=0;i imageBuffer = new ArrayList(); + Frame currentFrame; + int imageBufferLenght = 1; + Text imagePauseOverlay; + final Console console; + + public ScreenPanel11() { + logger = Logger.getLogger(getClass().getName()); + try { + initComponents(); + panelPulse.setVisible(false); + panelScreen.setVisible(false); + panelFilter.setVisible(false); + spinnerBackground.setVisible(false); + spinnerThreshold.setVisible(false); + btFixColormapRange.setVisible(false); + setGoodRegionOptionsVisible(false); + setSlicingOptionsVisible(false); + setRotationOptionsVisible(false); + setAveragingOptionsVisible(false); + JComponent editor = spinnerSlOrientation.getEditor(); + if (editor instanceof JSpinner.DefaultEditor) { + ((JSpinner.DefaultEditor) editor).getTextField().setHorizontalAlignment(JTextField.RIGHT); + } + renderer.setPersistenceFile(Paths.get(getContext().getSetup().getContextPath(), "Renderer_Cameras.bin")); + //setPersistedComponents(new Component[]{buttonServer, buttonDirect}); + setPersistedComponents(new Component[]{buttonTitle}); + comboCameras.setEnabled(false); + comboType.setEnabled(false); + if (App.hasArgument(ARG_LIST)){ + comboType.setVisible(false); + labelType.setVisible(false); + } + if (App.hasArgument(ARG_TYPE)){ + types = new ArrayList<>(); + for (String token : App.getArgumentValue(ARG_TYPE).split(",")){ + if (!token.isBlank()){ + types.add(token.trim()); + } + } + } + + SwingUtils.setEnumCombo(comboColormap, Colormap.class); + if (App.hasArgument("poll")) { + try { + polling = Integer.valueOf(App.getArgumentValue("poll")); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + if (App.hasArgument("zoom")) { + try { + renderer.setDefaultZoom(Double.valueOf(App.getArgumentValue("zoom"))); + renderer.resetZoom(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + if (App.hasArgument("buf")) { + try { + imageBufferLenght = Integer.valueOf(App.getArgumentValue("buf")); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + if (App.hasArgument("usr_ov")) { + try { + userOverlaysConfigFile = App.getArgumentValue("usr_ov"); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + if (App.hasArgument("srv_url")) { + serverUrl = App.getArgumentValue("srv_url"); + } + + if (App.hasArgument("cam_srv_url")) { + camServerUrl = App.getArgumentValue("cam_srv_url"); + } + + if (App.hasArgument("calc")) { + useServerStats = false; + } + + if (App.hasArgument("persist")) { + persistCameraState = true; + } + + if (App.hasArgument("suffix")) { + pipelineSuffix = App.getArgumentValue("suffix"); + } + + renderer.setProfileNormalized(true); + renderer.setShowProfileLimits(false); + + JMenuItem menuCalibrate = new JMenuItem("Calibrate..."); + menuCalibrate.addActionListener((ActionEvent e) -> { + try { + calibrate(); + } catch (Exception ex) { + showException(ex); + } + }); + + JMenuItem menuRendererConfig = new JMenuItem("Renderer Parameters"); + menuRendererConfig.addActionListener((ActionEvent e) -> { + try { + if (camera != null) { + this.showDeviceConfigDialog(camera, false); + } + } catch (Exception ex) { + showException(ex); + } + }); + + JMenuItem menuCameraConfig = new JMenuItem("Camera Configurarion"); + menuCameraConfig.addActionListener((ActionEvent e) -> { + try { + if (camera != null) { + String cameraConfigJson = null; + String cameraServerUrl = (camServerUrl == null) ? server.getUrl().substring(0, server.getUrl().length() - 1) + "8" : camServerUrl; + try (CameraServer srv = newCameraServer()) { + //TODO: replace into encodeMultiline + cameraConfigJson = JsonSerializer.encode(srv.getConfig(cameraName), true); + } + + TextEditor configEditor = new TextEditor(); + configEditor.setText(cameraConfigJson); + configEditor.setReadOnly(true); + configEditor.setTitle(cameraName); + EditorDialog dlg = configEditor.getDialog(getTopLevel(), false); + dlg.setSize(480, 640); + dlg.setVisible(true); + SwingUtils.centerComponent(getTopLevel(), dlg); + } + } catch (Exception ex) { + showException(ex); + } + }); + + JMenuItem menuSetImageBufferSize = new JMenuItem("Set Stack Size..."); + menuSetImageBufferSize.addActionListener((ActionEvent e) -> { + try { + String ret = SwingUtils.getString(getTopLevel(), "Enter size of image buffer: ", String.valueOf(imageBufferLenght)); + if (ret != null) { + this.setImageBufferSize(Integer.valueOf(ret)); + } + } catch (Exception ex) { + showException(ex); + } + }); + + JMenuItem menuSaveStack = new JMenuItem("Save Stack"); + menuSaveStack.addActionListener((ActionEvent e) -> { + try { + boolean completeOnly = true; + boolean badFormat = false; + boolean incomplete = false; + + while ((incomplete=((imageBuffer.size() < imageBufferLenght) && completeOnly)) || (badFormat = !hasSameFormat(imageBuffer))){ + if (incomplete){ + OptionResult ret = SwingUtils.showOption(getTopLevel(), "Save Stack", String.format("Stack is not complete (%d/%d images). Wait for completion?", imageBuffer.size(), imageBufferLenght), OptionType.YesNoCancel); + if (ret == OptionResult.Cancel){ + return; + } + if (ret == OptionResult.Yes){ + for (int i=0; i { + renderer.abortSelection(); + if (server != null) { + final Overlays.Rect selection = new Overlays.Rect(renderer.getPenMovingOverlay()); + renderer.addListener(new RendererListener() { + @Override + public void onSelectionFinished(Renderer renderer, Overlay overlay) { + try { + renderer.setShowReticle(false); + Rectangle roi = overlay.isFixed() ? renderer.toImageCoord(overlay.getBounds()) : overlay.getBounds(); + if (server.isRoiEnabled()) { + int[] cur = server.getRoi(); + server.setRoi(new int[]{roi.x + cur[0], roi.y + cur[1], roi.width, roi.height}); + } else { + server.setRoi(new int[]{roi.x, roi.y, roi.width, roi.height}); + } + } catch (Exception ex) { + } finally { + renderer.removeListener(this); + } + } + + @Override + public void onSelectionAborted(Renderer renderer, Overlay overlay) { + renderer.removeListener(this); + } + }); + selection.setFixed(true); + renderer.startSelection(selection); + } + }); + + JMenuItem menuResetROI = new JMenuItem("Reset ROI"); + menuResetROI.addActionListener((ActionEvent e) -> { + renderer.abortSelection(); + if (server != null) { + try { + renderer.setShowReticle(false); + server.resetRoi(); + } catch (IOException ex) { + showException(ex); + } + } + }); + + renderer.getPopupMenu().addSeparator(); + renderer.getPopupMenu().add(menuRendererConfig); + renderer.getPopupMenu().add(menuCameraConfig); + renderer.getPopupMenu().add(menuSetImageBufferSize); + renderer.getPopupMenu().add(menuSaveStack); + renderer.getPopupMenu().addSeparator(); + renderer.getPopupMenu().add(menuCalibrate); + renderer.getPopupMenu().addSeparator(); + renderer.getPopupMenu().add(menuSetROI); + renderer.getPopupMenu().add(menuResetROI); + renderer.getPopupMenu().addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + menuResetROI.setEnabled(server != null); + menuSetROI.setEnabled(server != null); + menuCalibrate.setVisible(server != null); + menuCalibrate.setEnabled((calibrationDialolg == null) || (!calibrationDialolg.isShowing())); + menuSaveStack.setEnabled(imageBufferLenght > 0); + menuSetImageBufferSize.setEnabled(!renderer.isPaused()); + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + } + }); + renderer.getPopupMenu().setVisible(false); + buttonScale.setSelected(renderer.getShowColormapScale()); + clearMarker(); + + showFit = buttonFit.isSelected(); + showProfile = buttonProfile.isSelected(); + + pauseSelection.setVisible(false); + pauseSelection.setMinValue(1); + pauseSelection.addListener(new ValueSelectionListener() { + @Override + public void onValueChanged(ValueSelection origin, double value, boolean editing) { + if (editing && (value >= 1) && (value <= imageBuffer.size())) { + updatePause(); + } + } + }); + renderer.addListener(new RendererListener() { + @Override + public void onMoveFinished(Renderer renderer, Overlay overlay) { + if (overlay == marker) { + try { + onMarkerChanged(); + } catch (IOException ex) { + logger.log(Level.WARNING, null, ex); + } + } + } + }); + if (MainFrame.isDark()) { + //textState.setDisabledTextColor(textState.getForeground()); + } + + } catch (Exception ex) { + ex.printStackTrace(); + } + + console = (!App.hasArgument("console")) ? null : new Console() { + + @Override + protected void onConsoleCommand(String command) { + String[] tokens = command.split(" "); + if (tokens.length > 0){ + try { + if (tokens[0].equals("cam")) { + if (!tokens[1].equals(comboCameras.getSelectedItem())) { + setComboTypeSelection("All"); + updateCameraList(); + comboCameras.setSelectedItem(tokens[1]); + if (!tokens[1].equals(comboCameras.getSelectedItem())) { + comboCameras.setSelectedItem(""); + throw new Exception("Invalid camera name : " + tokens[1]); + } + System.out.println("Console set camera: " + tokens[1]); + } + } else if (tokens[0].equals("pip")) { + initPipeline(tokens[1]); + } else if (tokens[0].equals("str")) { + initStream(tokens[1]); + } else if (tokens[0].equals("stop")) { + initCamera(""); + } else { + System.err.println("Invalid command: " + command); + } + } catch (Exception ex) { + System.err.println(ex); + } + } + } + }; + } + + @Override + public void onStart() { + super.onStart(); + updateDialogTitle(); + if (App.hasArgument("console")) { + console.start(); + } + } + + @Override + public void onStop() { + try { + if (camera != null) { + saveCameraState(); + camera.close(); + camera = null; + server = null; + updateButtons(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + try { + if (console != null) { + console.stop(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + super.onStop(); + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + comboCameras.setEnabled(false); + comboType.setEnabled(false); + + String[] types = new String[]{"All"}; + try (CameraServer srv = newCameraServer()) { + groups = srv.getCameraGroups(); + types = Arr.insert(Arr.sort(groups.keySet().toArray(new String[0])), "All", 0); + aliases = srv.getCameraAliases(); + } catch (Exception ex){ + groups = null; + aliases = null; + } + if (this.types!=null){ + types = this.types.toArray(new String[0]); + } + comboType.setModel(new javax.swing.DefaultComboBoxModel(types)); + + comboCameras.setEnabled(true); + comboType.setEnabled(true); + setComboCameraSelection(null); + if (Arr.containsEqual(types, "All")){ + setComboTypeSelection("All"); + } + updateCameraList(); + + try{ + if (App.hasArgument("s")) { + initSimulation(); + } else if (App.hasArgument("str")) { + initStream(App.getArgumentValue("str")); + } else if (App.hasArgument("pip")) { + initPipeline(App.getArgumentValue("pip")); + } else { + if (comboCameras.getModel().getSize() > 0) { + if (App.hasArgument("cam")) { + initCamera(App.getArgumentValue("cam")); + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + updateButtons(); + startTimer(1000); + } + + public void initCamera(String camera) throws IOException, InterruptedException{ + setComboCameraSelection(camera); + comboCamerasActionPerformed(null); + } + + public void initStream(String url) throws IOException, InterruptedException{ + if (!url.contains("\\")){ + url="tcp://" + url; + } + setCamera(url); + } + + public void initPipeline(String url) throws IOException, InterruptedException{ + if (!url.contains("\\")){ + url="cs://" + url; + } + setCamera(url); + } + + public void initSimulation() throws IOException, InterruptedException{ + renderer.setDevice((Source) getDevice("image")); + renderer.setAutoScroll(true); + ((Source) getDevice("image")).addListener(new ImageListener() { + @Override + public void onImage(Object o, BufferedImage bi, Data data) { + manageFit(bi, data); + manageUserOverlays(bi, data); + } + + @Override + public void onError(Object o, Exception ex) { + } + } + ); + } + + boolean isVisible(String camera) { + return ((comboType.getSelectedItem().toString().toLowerCase().equals("all")) || (getCameraTypes(camera).contains(comboType.getSelectedItem()))); + } + + DefaultComboBoxModel getCameraList() throws Exception { + DefaultComboBoxModel model = new DefaultComboBoxModel(); + if (App.hasArgument(ARG_LIST)){ + List lists = App.getArgumentValues(ARG_LIST); + for (String list: lists){ + String[] tokens = list.split(","); + for (String token : tokens){ + if (!token.isBlank()){ + model.addElement(token.trim()); + } + } + } + } else { + try (CameraServer srv = newCameraServer()) { + List cameras = srv.getCameras(); + Collections.sort(cameras); + if (App.hasArgument(ARG_ALIAS) && (aliases!=null)){ + if ("only".equals(App.getArgumentValue(ARG_ALIAS))){ + cameras = new ArrayList(); + } + cameras.addAll(0, aliases.keySet()); + } + for (String camera : cameras) { + if (isVisible(camera)) { + model.addElement(camera); + } + } + } + } + if (App.hasArgument("cam")) { + String camera = App.getArgumentValue("cam"); + if (model.getIndexOf(camera) < 0) { + if (isVisible(camera)) { + model.addElement(camera); + } + } + } + model.addElement(""); + + return model; + } + + PipelineServer newServer() throws IOException { + if (serverUrl != null) { + System.out.println("Connecting to server: " + serverUrl); + server = new PipelineServer(CAMERA_DEVICE_NAME, serverUrl); + } else { + System.out.println("Connecting to server"); + server = new PipelineServer(CAMERA_DEVICE_NAME); + } + updateButtons(); + return server; + } + + CameraServer newCameraServer() throws IOException, InterruptedException { + String cameraServerUrl = (camServerUrl == null) ? server.getUrl().substring(0, server.getUrl().length() - 1) + "8" : camServerUrl; + CameraServer srv = new CameraServer("CamServer", cameraServerUrl); + srv.initialize(); + return srv; + } + + boolean updatingCameraSelection; + + void setComboCameraSelection(Object selection) { + updatingCameraSelection = true; + try { + comboCameras.setSelectedItem(selection); + } finally { + updatingCameraSelection = false; + } + } + + void setComboTypeSelection(Object selection) { + updatingCameraSelection = true; + try { + comboType.setSelectedItem(selection); + } finally { + updatingCameraSelection = false; + } + } + + void updateCameraList() { + try { + String selected = (String) comboCameras.getSelectedItem(); + comboCameras.setModel(getCameraList()); + if ((selected != null) && (((DefaultComboBoxModel) comboCameras.getModel()).getIndexOf(selected) > 0)){ + setComboCameraSelection(selected); + } else{ + setComboCameraSelection(""); + } + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + updateButtons(); + } + } + + final Object lockOverlays = new Object(); + + void manageFit(BufferedImage bi, Data data) { + Overlay[][] fo = null; + if ((showFit || showProfile)) { + try { + fo = getFitOverlays(data); + } catch (Exception ex) { + System.err.println(ex); + } + } + synchronized (lockOverlays) { + fo = (fo == null) ? new Overlay[][]{null, null} : fo; + renderer.updateOverlays(fo[0], profileOv); + profileOv = fo[0]; + renderer.updateOverlays(fo[1], fitOv); + fitOv = fo[1]; + } + } + + void manageUserOverlays(BufferedImage bi, Data data) { + Overlay[] fo = (bi == null) ? null : getUserOverlays(data); + synchronized (lockOverlays) { + renderer.updateOverlays(fo, userOv); + userOv = fo; + } + } + + void updateDialogTitle() { + if (App.isDetached()) { + getTopLevel().setTitle(cameraName == null ? "ScreenPanel" : cameraName); + } + } + + void manageTitleOverlay() { + Overlay to = null; + String text = cameraAlias; + if ((buttonTitle.isSelected()) && (text != null)) { + Font font = new Font("Arial", Font.PLAIN, 28); + to = new Text(renderer.getPenErrorText(), text, font, new Point(-SwingUtils.getTextSize(text, renderer.getGraphics().getFontMetrics(font)).width - 14, 26)); + to.setFixed(true); + to.setAnchor(Overlay.ANCHOR_VIEWPORT_OR_IMAGE_TOP_RIGHT); + } + + synchronized (lockOverlays) { + renderer.updateOverlays(to, titleOv); + titleOv = to; + } + } + + + void manageOverlayErrorOverlay(boolean error) { + if ((error) != (backgOv != null)){ + + Overlay bo = null; + if (error){ + String text = "Invalid image background"; + Font font = new Font("Arial", Font.PLAIN, 14); + bo = new Text(renderer.getPenErrorText(), text, font, new Point(-SwingUtils.getTextSize(text, renderer.getGraphics().getFontMetrics(font)).width - 14, 46)); + bo.setFixed(true); + bo.setAnchor(Overlay.ANCHOR_VIEWPORT_OR_IMAGE_TOP_RIGHT); + } + synchronized (lockOverlays) { + renderer.updateOverlays(bo,backgOv); + backgOv = bo; + } + } + } + + + @Override + public void onStateChange(State state, State former) { + + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + //Callback to perform update - in event thread + @Override + protected void doUpdate() { + } + + Thread devicesInitTask; + + void setCamera(String cameraName) throws IOException, InterruptedException { + System.out.println("Initializing: " + cameraName); + isUrl = (cameraName!=null) && cameraName.startsWith("tcp://"); + isPipeline = (cameraName!=null) && cameraName.startsWith("cs://"); + if (isPipeline) { + cameraName = cameraName.substring(cameraName.lastIndexOf("/") + 1); + } + panelPipeline.setVisible(!isUrl); + panelCameraSelection.setVisible(!isUrl); + parseUserOverlays(); + errorOverlay = null; + lastMarkerPos = null; + lastFrame = null; + lastPipelinePars = null; + + if (streamPanel!=null){ + streamPanel.hideDevicePanel(server.getStream()); + } + + if (calibrationDialolg != null) { + calibrationDialolg.dispose(); + calibrationDialolg = null; + } + + if (camera != null) { + saveCameraState(); + camera.close(); + camera = null; + server = null; + } + updateButtons(); + instanceName = null; + renderer.setDevice(null); + renderer.setShowReticle(false); + renderer.removeOverlays(fitOv); + renderer.removeOverlays(profileOv); + renderer.removeOverlays(userOv); + renderer.clear(); + renderer.resetZoom(); + + cameraAlias = cameraName; + if ((aliases!=null) && (cameraName!=null) && (aliases.containsKey(cameraName))){ + cameraName = aliases.get(cameraName); + System.out.println("Camera name is alias to: " + cameraName); + } + + boolean changed = !String.valueOf(cameraName).equals(this.cameraName); + this.cameraName = cameraName; + + if (changed) { + spinnerBackground.setVisible(false); + spinnerThreshold.setVisible(false); + checkThreshold.setEnabled(false); + checkRotation.setEnabled(false); + checkAveraging.setEnabled(false); + checkGoodRegion.setEnabled(false); + setGoodRegionOptionsVisible(false); + setSlicingOptionsVisible(false); + setRotationOptionsVisible(false); + setAveragingOptionsVisible(false); + } + synchronized (imageBuffer) { + currentFrame = null; + imageBuffer.clear(); + } + if (changed) { + checkBackground.setEnabled(false); + if ((devicesInitTask != null) && (devicesInitTask.isAlive())) { + devicesInitTask.interrupt(); + } + if (screen != null) { + screen.close(); + screen = null; + } + if (filter != null) { + filter.close(); + filter = null; + } + if (renderer.isPaused()) { + renderer.resume(); + removePauseOverlay(); + pauseSelection.setVisible(false); + panelCameraSelection.setVisible(true); + } + } + manageTitleOverlay(); + updateDialogTitle(); + + if (cameraName == null) { + return; + } + try { + + camera = newServer(); + camera.getConfig().flipHorizontally = false; + camera.getConfig().flipVertically = false; + camera.getConfig().rotation = 0.0; + camera.getConfig().roiX = 0; + camera.getConfig().roiY = 0; + camera.getConfig().roiWidth = -1; + camera.getConfig().roiHeight = -1; + + camera.initialize(); + camera.assertInitialized(); + System.out.println("Camera initialization OK"); + loadCameraState(); + if (server != null) { + //server.start(cameraName, false); + if (isUrl){ + System.out.println("Setting url: " + cameraName ); + instanceName = cameraName; + server.setStreamSocket(instanceName); + server.startReceiver(); + cameraName = null; + } else if (isPipeline){ + System.out.println("Setting pipeline: " + cameraName ); + instanceName = cameraName; + server.start(instanceName, true); + try{ + cameraName = server.getCameraName(); + //setComboCameraSelection(cameraName); + } catch (Exception ex){ + cameraName = null; + } + System.out.println("Camera Name: " + cameraName ); + } else { + System.out.println("Setting camera: " + cameraName ); + String pipelineName = cameraName + pipelineSuffix; + instanceName = cameraName + pipelineSuffix + "1"; + if (!server.getPipelines().contains(pipelineName)) { + System.out.println("Creating pipeline: " + pipelineName); + HashMap config = new HashMap<>(); + config.put("camera_name", cameraName); + //server.createFromConfig(config, pipelineName); + server.savePipelineConfig(pipelineName, config); + } + server.start(pipelineName, instanceName); + } + this.cameraName = cameraName; + updatePipelineControls(); + checkThreshold.setEnabled(true); + checkRotation.setEnabled(true); + checkAveraging.setEnabled(true); + checkGoodRegion.setEnabled(true); + } else { + checkThreshold.setSelected(false); + checkRotation.setSelected(false); + checkAveraging.setSelected(false); + checkGoodRegion.setSelected(false); + if (polling <= 0) { + camera.setMonitored(true); + } else { + camera.setPolling(polling); + } + camera.setBackgroundEnabled(checkBackground.isSelected()); + } + updateButtons(); + camera.getConfig().save(); + + renderer.setDevice(camera); + + renderer.setAutoScroll(true); + //renderer.setMarker(marker); + clearMarker(); + imageSize = null; + + camera.addListener(new ImageListener() { + @Override + public void onImage(Object o, BufferedImage bi, Data data) { + if (bi != null) { + if ((imageSize == null) || imageSize.width != bi.getWidth() || imageSize.height != bi.getHeight()) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if ((renderer.getMode() == RendererMode.Zoom) || (renderer.getMode() == RendererMode.Fixed)) { + centralizeRenderer(); + } + checkReticle(); + } + }); + imageSize = new Dimension(bi.getWidth(), bi.getHeight()); + } + renderer.setProfileSize(Math.min(bi.getWidth(), bi.getHeight())); + } + //renderer.setCalibration(camera.getCalibration()); + if (!renderer.isPaused()) { + if (data != null) { + synchronized (imageBuffer) { + currentFrame = new Frame(data); + if (imageBufferLenght >= 1) { + imageBuffer.add(currentFrame); + if (imageBuffer.size() > imageBufferLenght) { + imageBuffer.remove(0); + setBufferFull(true); + } else { + setBufferFull(false); + } + } else { + setBufferFull(true); + } + updateMarker(); + } + } + manageFit(bi, data); + manageUserOverlays(bi, data); + } + //updateImageData(); + } + + @Override + public void onError(Object o, Exception ex) { + //System.err.println(ex); + } + }); + + } catch (Exception ex) { + showException(ex); + renderer.clearOverlays(); + updatePipelineControls(); + if (renderer.getDevice() == null) { + //renderer.setZoom(1.0); + //renderer.setMode(RendererMode.Zoom); + errorOverlay = new Text(renderer.getPenErrorText(), ex.toString(), new Font("Verdana", Font.PLAIN, 12), new Point(20, 20)); + errorOverlay.setFixed(true); + errorOverlay.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_LEFT); + renderer.addOverlay(errorOverlay); + } + } finally { + //checkReticle(); + onTimer(); + } + onChangeColormap(null); + checkBackground.setEnabled(true); + if (changed) { + if (cameraName==null){ + + } + boolean electrons = (this.cameraName!=null) && getCameraTypes(this.cameraName).contains(ELECTRONS_TYPE); + boolean twoPulses = (this.cameraName!=null) && getCameraTypes(this.cameraName).contains(TWO_PULSES_TYPE); + comboScreen.setModel(new DefaultComboBoxModel()); + comboScreen.setEnabled(false); + comboFilter.setModel(new DefaultComboBoxModel()); + comboFilter.setEnabled(false); + panelFilter.setVisible(electrons); + panelScreen.setVisible(electrons); + panelPulse.setVisible(twoPulses); + textPulse.setText(""); + if (this.cameraName!=null){ + if (electrons) { + //Parallelizing initialization + devicesInitTask = new Thread(() -> { + try { + if (this.cameraName.contains("DSRM")) { + screen = new DiscretePositioner("CurrentScreen", this.cameraName + ":POSITION_SP", this.cameraName + ":POSITION"); + } else { + screen = new DiscretePositioner("CurrentScreen", this.cameraName + ":SET_SCREEN1_POS", this.cameraName + ":GET_SCREEN1_POS"); + } + screen.setMonitored(true); + screen.initialize(); + DefaultComboBoxModel model = new DefaultComboBoxModel(); + for (String pos : screen.getPositions()) { + model.addElement(pos); + } + comboScreen.setModel(model); + comboScreen.setSelectedItem(screen.read()); + + } catch (Exception ex) { + comboScreen.setModel(new DefaultComboBoxModel()); + System.err.println(ex.getMessage()); + screen = null; + } + comboScreen.setEnabled(screen != null); + valueScreen.setDevice(screen); + + try { + filter = new DiscretePositioner("CurrentFilter", this.cameraName + ":SET_FILTER", this.cameraName + ":GET_FILTER"); + filter.setMonitored(true); + filter.initialize(); + DefaultComboBoxModel model = new DefaultComboBoxModel(); + for (String pos : filter.getPositions()) { + model.addElement(pos); + } + comboFilter.setModel(model); + comboFilter.setSelectedItem(filter.read()); + } catch (Exception ex) { + System.err.println(ex.getMessage()); + filter = null; + } + comboFilter.setEnabled(filter != null); + valueFilter.setDevice(filter); + }); + devicesInitTask.start(); + } + } + } + } + + boolean bufferFull = true; + + void setBufferFull(boolean value) { + if (value != bufferFull) { + SwingUtilities.invokeLater(() -> { + buttonPause.setBackground(value ? buttonSave.getBackground() : buttonSave.getBackground().brighter()); + }); + bufferFull = value; + } + } + + volatile Dimension imageSize; + + void checkReticle() { + if ((renderer.getDevice() != null) && (camera != null) && (camera.getConfig().isCalibrated()) && buttonReticle.isSelected()) { + //renderer.setCalibration(camera.getCalibration()); + renderer.configureReticle(new Dimension(800, 800), 200); + renderer.setShowReticle(true); + } else { + //renderer.setCalibration(null); + renderer.setShowReticle(false); + } + renderer.refresh(); + } + + void checkMarker(Point p) throws IOException { + if (camera != null) { + if (buttonMarker.isSelected()) { + Dimension d = renderer.getImageSize(); + if (p == null) { + p = (d == null) ? new Point(renderer.getWidth() / 2, renderer.getHeight() / 2) : new Point(d.width / 2, d.height / 2); + } + Overlay ov = null; + marker = new Overlays.Crosshairs(renderer.getPenMarker(), p, new Dimension(100, 100)); + marker.setMovable(true); + marker.setPassive(false); + } else { + marker = null; + } + renderer.setMarker(marker); + onMarkerChanged(); + } + } + + Point lastMarkerPos; + + void onMarkerChanged() throws IOException { + lastMarkerPos = getStreamMarkerPos(); + if (marker == null) { + setInstanceConfigValue("Marker", null); + } else { + setInstanceConfigValue("Marker", new int[]{marker.getPosition().x, marker.getPosition().y}); + } + } + + void updateMarker() { + try { + if ((server != null) && (!isUrl)) { + Point p = getStreamMarkerPos(); + if (p != null) { + //To prevent a local change being overriden by a message having the old settings. + //TODO: This is not bullet-proof, as one can have 2 changes between 2 frames... + if (!p.equals(lastMarkerPos)) { + if (p.x == Integer.MIN_VALUE) { + if (buttonMarker.isSelected()) { + buttonMarker.setSelected(false); + checkMarker(null); + } + } else { + if (!buttonMarker.isSelected()) { + buttonMarker.setSelected(true); + checkMarker(p); + } else { + if (!p.equals(marker.getPosition())) { + marker.setPosition(p); + } + } + } + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + Point getStreamMarkerPos() throws IOException { + //System.out.println(server.getInstanceConfig().get("Marker")); + Map pars = server.getProcessingParameters(); + if (pars != null) { + List markerPosition = (List) pars.get("Marker"); + if (markerPosition != null) { + return new Point((Integer) markerPosition.get(0), (Integer) markerPosition.get(1)); + } + return new Point(Integer.MIN_VALUE, Integer.MIN_VALUE); + } + return null; + } + + void clearMarker() { + marker = null; + renderer.setMarker(marker); + } + + void setInstanceConfigValue(String name, Object value) throws IOException { + if (server != null) { + Map map = server.getInstanceConfig(); + map.put(name, value); + server.setInstanceConfig(map); + } + } + + void updateZoom() { + try { + buttonZoomStretch.setSelected(renderer.getMode() == RendererMode.Stretch); + buttonZoomFit.setSelected(renderer.getMode() == RendererMode.Fit); + if (renderer.getMode() == RendererMode.Fixed) { + buttonZoomNormal.setSelected(true); + } else if (renderer.getMode() == RendererMode.Zoom) { + if (renderer.getZoom() == 1) { + buttonZoomNormal.setSelected(true); + } else if (renderer.getZoom() == 0.5) { + buttonZoom05.setSelected(true); + } else if (renderer.getZoom() == 0.25) { + buttonZoom025.setSelected(true); + } else if (renderer.getZoom() == 2.0) { + buttonZoom2.setSelected(true); + } else { + buttonGroup1.clearSelection(); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + boolean updatingColormap; + + void updateColormap() { + updatingColormap = true; + try { + if ((camera != null) && (camera instanceof ColormapSource)) { + ColormapSourceConfig config = ((ColormapSource) camera).getConfig(); + comboColormap.setSelectedItem(config.colormap); + if (config.isDefaultColormap()) { + buttonFullRange.setSelected(true); + } else if (config.colormapAutomatic) { + buttonAutomatic.setSelected(true); + } else { + buttonManual.setSelected(true); + } + btFixColormapRange.setVisible(buttonAutomatic.isSelected()); + spinnerMin.setEnabled(buttonManual.isSelected()); + spinnerMax.setEnabled(buttonManual.isSelected()); + + boolean signed = spinnerBackground.isVisible() && "signed".equals(spinnerBackground.getValue()); + Integer min = signed ? -65535: 0; + if (!min.equals(((SpinnerNumberModel)spinnerMin.getModel()).getMinimum())){ + spinnerMin.setModel(new SpinnerNumberModel(0, min.intValue(), 65535, 1)); + spinnerMax.setModel(new SpinnerNumberModel(255, min.intValue(), 65535, 1)); + if ((Integer)((SpinnerNumberModel)spinnerMin.getModel()).getValue() < min){ + spinnerMin.setValue(min); + } + if ((Integer)((SpinnerNumberModel)spinnerMax.getModel()).getValue() < min){ + spinnerMax.setValue(min); + } + } + + if (!Double.isNaN(config.colormapMin)) { + Integer value = Math.min(Math.max((int) config.colormapMin, min), 65535); + if (spinnerMin.getModel().getValue()!= value){ + spinnerMin.setValue(value); + } + } + if (!Double.isNaN(config.colormapMax)) { + Integer value = Math.min(Math.max((int) config.colormapMax, min), 65535); + if (spinnerMax.getModel().getValue()!= value){ + spinnerMax.setValue(value); + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + updatingColormap = false; + } + + void updatePipelineProperties() { + goodRegion = checkGoodRegion.isSelected(); + spinnerBackground.setVisible(checkBackground.isSelected()); + spinnerThreshold.setVisible(checkThreshold.isSelected()); + setGoodRegionOptionsVisible(goodRegion); + slicing = goodRegion && checkSlicing.isSelected(); + setSlicingOptionsVisible(slicing); + updatingServerControls = false; + boolean rotation = checkRotation.isSelected(); + setRotationOptionsVisible(rotation); + boolean averaging = checkAveraging.isSelected(); + setAveragingOptionsVisible(averaging); + } + + boolean updatingServerControls; + + void updatePipelineControls() { + if (server != null) { + updatingServerControls = true; + if (server.isStarted()) { + try { + checkBackground.setSelected(server.isBackgroundSubtractionEnabled()); + setBackgoundControl(server.getBackgroundSubtraction()); + Object bg = server.getBackgroundSubtraction(); + if (bg.equals("signed") || bg.equals("passive")){ + spinnerBackground.setValue(bg); + } else { + spinnerBackground.setValue("normal"); + } + Double threshold = (server.getThreshold()); + checkThreshold.setSelected(threshold != null); + spinnerThreshold.setValue((threshold == null) ? 0 : threshold); + Map gr = (server.getGoodRegion()); + checkGoodRegion.setSelected(gr != null); + if (gr != null) { + spinnerGrThreshold.setValue(((Number) gr.get("threshold")).doubleValue()); + spinnerGrScale.setValue(((Number) gr.get("gfscale")).doubleValue()); + } + Map rotation = server.getRotation(); + checkRotation.setSelected(rotation != null); + if (rotation!=null){ + spinnerRotationAngle.setValue(((Number) rotation.get("angle")).doubleValue()); + spinnerRotationOrder.setValue(((Number) rotation.get("order")).intValue()); + String mode = (String) rotation.get("mode"); + try{ + spinnerRotationConstant.setValue(Double.valueOf(mode)); + spinnerRotationMode.setValue("constant"); + } catch (Exception ex){ + spinnerRotationConstant.setValue(0); + spinnerRotationMode.setValue(mode); + } + } + + Number averaging = (Number) server.getAveraging(); + checkAveraging.setSelected(averaging != null); + if (averaging!=null){ + spinnerAvFrames.setValue(Math.abs(averaging.intValue())); + spinnerAvMode.setValue(averaging.intValue()<0 ? "window" : "single"); + } + + Map slicing = (server.getSlicing()); + checkSlicing.setSelected(slicing != null); + if (slicing != null) { + spinnerSlNumber.setValue(((Number) slicing.get("number_of_slices")).intValue()); + spinnerSlScale.setValue(((Number) slicing.get("scale")).doubleValue()); + spinnerSlOrientation.setValue((String) slicing.get("orientation")); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + updatePipelineProperties(); + } + } + + boolean changedPipelinePars(Map pars1, Map pars2) { + String[] keys = new String[]{"image_background_enable", "image_threshold", "image_good_region", + "threshold", "gfscale", "image_slices", "number_of_slices", "scale", "orientation", "image_background_ok"}; + for (String key : keys) { + Object o1 = pars1.get(key); + Object o2 = pars2.get(key); + if (o1 == null) { + if (o2 != null) { + return true; + } + } else if (!o1.equals(o2)) { + return true; + } + } + return false; + } + + void setBackgoundControl(Object background){ + spinnerBackground.setValue((background.equals("signed") || background.equals("passive")) ? background : "normal"); + } + + void updatePipelineControls(Map pars) { + if (pars != null) { + updatingServerControls = true; + try { + Object background = pars.get("image_background_enable"); + checkBackground.setSelected(!background.equals("") && !background.equals(false) && !background.equals("false")); + setBackgoundControl(background); + + manageOverlayErrorOverlay(Boolean.FALSE.equals(pars.get("image_background_ok"))); + + Double threshold = (Double) (pars.get("image_threshold")); + checkThreshold.setSelected(threshold != null); + spinnerThreshold.setValue((threshold == null) ? 0 : threshold); + Map gr = (Map) pars.get("image_good_region"); + checkGoodRegion.setSelected(gr != null); + if (gr != null) { + Double value = ((Number) gr.get("threshold")).doubleValue(); + spinnerGrThreshold.setValue(value); + Double scale = ((Number) gr.get("gfscale")).doubleValue(); + spinnerGrScale.setValue(scale); + } + Map slicing = (Map) (pars.get("image_slices")); + checkSlicing.setSelected(slicing != null); + if (slicing != null) { + int slices = ((Number) slicing.get("number_of_slices")).intValue(); + spinnerSlNumber.setValue(slices); + double scale = ((Number) slicing.get("scale")).doubleValue(); + spinnerSlScale.setValue(scale); + String orientation = (String) slicing.get("orientation"); + spinnerSlOrientation.setValue(orientation); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + updatePipelineProperties(); + } + } + + void setGoodRegionOptionsVisible(boolean visible) { + spinnerGrThreshold.setVisible(visible); + labelGrThreshold.setVisible(visible); + spinnerGrScale.setVisible(visible); + labelGrScale.setVisible(visible); + panelSlicing.setVisible(visible); + } + + void setSlicingOptionsVisible(boolean visible) { + spinnerSlNumber.setVisible(visible); + labelSlNumber.setVisible(visible); + spinnerSlScale.setVisible(visible); + labelSlScale.setVisible(visible); + spinnerSlOrientation.setVisible(visible); + labelSlOrientation.setVisible(visible); + } + + void setAveragingOptionsVisible(boolean visible) { + labelAvMode.setVisible(visible); + labelAvFrames.setVisible(visible); + spinnerAvMode.setVisible(visible); + spinnerAvFrames.setVisible(visible); + } + + void setRotationOptionsVisible(boolean visible) { + labelAngle.setVisible(visible); + labelOrder.setVisible(visible); + labelMode.setVisible(visible); + labelConstant.setVisible(visible); + spinnerRotationAngle.setVisible(visible); + spinnerRotationOrder.setVisible(visible); + spinnerRotationMode.setVisible(visible); + spinnerRotationConstant.setVisible(visible); + } + + boolean isCameraStopped() { + if (server != null) { + if (!isUrl) { + if (!server.isStarted()) + return true; + } + } + return ((camera == null) || camera.isClosed()); + } + + boolean updatingButtons; + + void updateButtons() { + updatingButtons = true; + try { + boolean active = !isCameraStopped();//(camera != null); + buttonSave.setEnabled(active); + buttonGrabBackground.setEnabled(active); + buttonMarker.setEnabled(active); + buttonProfile.setEnabled(active); + buttonFit.setEnabled(active); + buttonReticle.setEnabled(active && camera.getConfig().isCalibrated()); + buttonStreamData.setEnabled(active && (server != null)); + buttonPause.setEnabled(active); + + if (renderer.isPaused() != buttonPause.isSelected()) { + buttonPause.setSelected(renderer.isPaused()); + buttonPauseActionPerformed(null); + } + if (renderer.getShowReticle() != buttonReticle.isSelected()) { + //buttonReticle.setSelected(renderer.getShowReticle()); + } + if ((renderer.getMarker() == null) && buttonMarker.isSelected()) { + buttonMarker.setSelected(false); + } + buttonSave.setSelected(renderer.isSnapshotDialogVisible()); + + } finally { + updatingButtons = false; + } + } + + Frame lastFrame = null; + Map lastPipelinePars = null; + + State state; + void checkAppState(){ + if (App.isDetached()){ + State state = App.getInstance().getState(); + if (state.isInitialized()){ + state = (camera == null) ? state : camera.getState(); + } + if (state!=this.state){ + App.getInstance().getPropertyChangeSupport().firePropertyChange("appstate", this.state, state); + this.state = state; + } + } + } + + + @Override + protected void onTimer() { + for (Device dev : new Device[]{screen, filter}) { + if (dev != null) { + dev.request(); + } + } + + //textState.setText((camera == null) ? "" : camera.getState().toString());\ + checkAppState(); + + if (App.hasArgument("s")) { + try { + ((Source) getDevice("image")).initialize(); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + updateZoom(); + updateColormap(); + updateButtons(); + checkHistogram.setSelected((histogramDialog != null) && (histogramDialog.isShowing())); + buttonScale.setSelected(renderer.getShowColormapScale()); + try { + Frame frame = getCurrentFrame(); + if (frame != lastFrame) { + lastFrame = frame; + if (frame != null) { + Map pars = getProcessingParameters(frame.cache); + if ((lastPipelinePars == null) || changedPipelinePars(pars, lastPipelinePars)) { + //System.out.println("Update pipeline: " + pars); + lastPipelinePars = pars; + updatePipelineControls(pars); + } + if (panelPulse.isVisible()){ + Object pulse = null; + try{ + pulse = frame.cache.getValue("pulse"); + } catch (Exception ex) { + } + textPulse.setText((pulse==null) ? "" : Str.toString(pulse)); + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + Pen penFit = new Pen(new Color(192, 105, 0), 0); + Pen penCross = new Pen(new Color(192, 105, 0), 0); + Pen penSlices = new Pen(Color.CYAN.darker(), 1); + + Frame getCurrentFrame() { + if ((imageBufferLenght > 1) && (renderer.isPaused())) { + int index = ((int) pauseSelection.getValue()) - 1; + synchronized (imageBuffer) { + return ((index>=0) && (index < imageBuffer.size())) ? imageBuffer.get(index) : null; + } + } + return currentFrame; + } + + Frame getFrame(Data data) { + synchronized (imageBuffer) { + for (Frame f : imageBuffer) { + if (f.data == data) { + return f; + } + } + } + return null; + } + + void setImageBufferSize(int size) { + if (renderer.isPaused()) { + throw new RuntimeException("Cannot change buffer size whn paused"); + } + synchronized (imageBuffer) { + imageBufferLenght = size; + imageBuffer.clear(); + } + + } + + Overlay[][] getFitOverlays(Data data) { + Overlays.Polyline hgaussian = null; + Overlays.Polyline vgaussian = null; + Overlays.Polyline hprofile = null; + Overlays.Polyline vprofile = null; + Double xMean = null, xSigma = null, xNorm = null, xCom = null, xRms = null; + Double yMean = null, ySigma = null, yNorm = null, yCom = null, yRms = null; + double[] pX = null, pY = null, gX = null, gY = null; + PointDouble[] sliceCenters = null; + if (data != null) { + int height = data.getHeight(); + int width = data.getWidth(); + int profileSize = renderer.getProfileSize(); + ImageData id = null; + if ((useServerStats) && (server != null)) { + try { + id = getFrame(data); + if (id == null) { + return null; + } + xMean = id.x_fit_mean; + xSigma = id.x_fit_standard_deviation; + yMean = id.y_fit_mean; + ySigma = id.y_fit_standard_deviation; + gX = id.x_fit_gauss_function; + gY = id.y_fit_gauss_function; + pX = id.x_profile; + pY = id.y_profile; + xCom = id.x_center_of_mass; + xRms = id.x_rms; + yCom = id.y_center_of_mass; + yRms = id.y_rms; + sliceCenters = id.sliceCenters; + + profileSize /= 4; + if (pX != null) { + int[] xp = Arr.indexesInt(pX.length); + int[] xg = xp; + int[] yp = new int[pX.length]; + int[] yg = new int[pX.length]; + + List l = Arrays.asList((Double[]) Convert.toWrapperArray(pX)); + double minProfile = Collections.min(l); + double maxProfile = Collections.max(l); + double rangeProfile = maxProfile - minProfile; + double minGauss = minProfile; + double rangeGauss = rangeProfile; + //If not good region, range of profile and fit are similar so save this calcultion + if (goodRegion && id.gr_size_x > 0) { + l = Arrays.asList((Double[]) Convert.toWrapperArray(Arrays.copyOfRange(gX, id.gr_pos_x, id.gr_pos_x + id.gr_size_x))); + minGauss = Collections.min(l); + rangeGauss = Collections.max(l) - minGauss; + } + + for (int i = 0; i < xp.length; i++) { + if (gX != null) { + yg[i] = (int) (height - 1 - (((gX[i] - minGauss) / rangeGauss) * profileSize)); + } + yp[i] = (int) (height - 1 - (((pX[i] - minProfile) / rangeProfile) * profileSize)); + } + + if (goodRegion && id.gr_size_x > 0) { + xg = Arrays.copyOfRange(xg, id.gr_pos_x, id.gr_pos_x + id.gr_size_x); + yg = Arrays.copyOfRange(yg, id.gr_pos_x, id.gr_pos_x + id.gr_size_x); + } + + vgaussian = new Overlays.Polyline(penFit, xg, yg); + vprofile = new Overlays.Polyline(renderer.getPenProfile(), xp, yp); + } + + if (pY != null) { + int[] xp = new int[pY.length]; + int[] xg = new int[pY.length]; + int[] yp = Arr.indexesInt(pY.length); + int[] yg = yp; + + List l = Arrays.asList((Double[]) Convert.toWrapperArray(pY)); + double minProfile = Collections.min(l); + double maxProfile = Collections.max(l); + double rangeProfile = maxProfile - minProfile; + double minGauss = minProfile; + double rangeGauss = rangeProfile; + //If not good region, range of profile and fit are similar so save this calcultion + if (goodRegion && id.gr_size_y > 0) { + l = Arrays.asList((Double[]) Convert.toWrapperArray(Arrays.copyOfRange(gY, id.gr_pos_y, id.gr_pos_y + id.gr_size_y))); + minGauss = Collections.min(l); + rangeGauss = Collections.max(l) - minGauss; + } + + for (int i = 0; i < xp.length; i++) { + if (gY != null) { + xg[i] = (int) (((gY[i] - minGauss) / rangeGauss) * profileSize); + } + xp[i] = (int) (((pY[i] - minProfile) / rangeProfile) * profileSize); + } + + if (goodRegion && id.gr_size_y > 0) { + xg = Arrays.copyOfRange(xg, id.gr_pos_y, id.gr_pos_y + id.gr_size_y); + yg = Arrays.copyOfRange(yg, id.gr_pos_y, id.gr_pos_y + id.gr_size_y); + } + hgaussian = new Overlays.Polyline(penFit, xg, yg); + hprofile = new Overlays.Polyline(renderer.getPenProfile(), xp, yp); + } + } catch (Exception ex) { + System.err.println(ex.getMessage()); + return null; + } + } else { + ArrayProperties properties = data.getProperties(); + double maxPlot = properties.max; + double minPlot = properties.min; + double rangePlot = maxPlot - minPlot; + + if (rangePlot <= 0) { + return null; + } + if (renderer.getCalibration() != null) { + try { + double[] sum = data.integrateVertically(true); + double[] saux = new double[sum.length]; + int[] p = new int[sum.length]; + double[] x_egu = renderer.getCalibration().getAxisX(sum.length); + double[] comRms = getComRms(sum, x_egu); + xCom = comRms[0]; + xRms = comRms[1]; + int[] x = Arr.indexesInt(sum.length); + DescriptiveStatistics stats = new DescriptiveStatistics(sum); + double min = stats.getMin(); + for (int i = 0; i < sum.length; i++) { + saux[i] = sum[i] - min; + } + if (showFit) { + double[] gaussian = fitGaussian(saux, x); + if (gaussian != null) { + if ((gaussian[2] < sum.length * 0.45) + && (gaussian[2] > 2) + && (gaussian[0] > min * 0.03)) { + xNorm = gaussian[0]; + xMean = gaussian[1]; + xSigma = gaussian[2]; + double[] fit = getFitFunction(gaussian, x); + int[] y = new int[x.length]; + for (int i = 0; i < x.length; i++) { + y[i] = (int) (height - 1 - ((((fit[i] + min) / height - minPlot) / rangePlot) * profileSize)); + } + vgaussian = new Overlays.Polyline(penFit, x, y); + } + } + } + if (showProfile) { + for (int i = 0; i < x.length; i++) { + p[i] = (int) (height - 1 - (((sum[i] / height - minPlot) / rangePlot) * profileSize)); + } + vprofile = new Overlays.Polyline(renderer.getPenProfile(), x, p); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + + try { + double[] sum = data.integrateHorizontally(true); + double[] saux = new double[sum.length]; + int[] p = new int[sum.length]; + double[] y_egu = renderer.getCalibration().getAxisY(sum.length); + double[] comRms = getComRms(sum, y_egu); + yCom = comRms[0]; + yRms = comRms[1]; + int[] x = Arr.indexesInt(sum.length); + DescriptiveStatistics stats = new DescriptiveStatistics(sum); + double min = stats.getMin(); + for (int i = 0; i < sum.length; i++) { + saux[i] = sum[i] - min; + } + + if (showFit) { + double[] gaussian = fitGaussian(saux, x); + if (gaussian != null) { + //Only aknowledge beam fully inside the image and peak over 3% of min + if ((gaussian[2] < sum.length * 0.45) + && (gaussian[2] > 2) + && (gaussian[0] > min * 0.03)) { + yNorm = gaussian[0]; + yMean = gaussian[1]; + ySigma = gaussian[2]; + double[] fit = getFitFunction(gaussian, x); + + int[] y = new int[x.length]; + for (int i = 0; i < x.length; i++) { + y[i] = (int) ((((fit[i] + min) / width - minPlot) / rangePlot) * profileSize); + } + hgaussian = new Overlays.Polyline(penFit, y, x); + } + } + } + if (showProfile) { + for (int i = 0; i < x.length; i++) { + p[i] = (int) (((sum[i] / width - minPlot) / rangePlot) * profileSize); + } + hprofile = new Overlays.Polyline(renderer.getPenProfile(), p, x); + } + + } catch (Exception ex) { + ex.printStackTrace(); + } + if (xSigma != null) { + xSigma *= renderer.getCalibration().getScaleX(); + } + if (ySigma != null) { + ySigma *= renderer.getCalibration().getScaleY(); + } + if (xMean != null) { + xMean = data.getX((int) Math.round(xMean)); + } + if (yMean != null) { + yMean = data.getY((int) Math.round(yMean)); + } + } + } + final String units = (renderer.getCalibration() != null) ? "\u00B5m" : "px"; + final String fmt = "%7.1f" + units; + Overlays.Text textCom = null; + Overlay[] pOv = null, fOv = null; + Font fontInfoText = new Font(Font.MONOSPACED, 0, 14); + Point textPosition = new Point(12, 20); + if (showProfile) { + if ((xCom != null) && (yCom != null)) { + String text = String.format("com x: m=" + fmt + " \u03C3=" + fmt + "\ncom y: m=" + fmt + " \u03C3=" + fmt, xCom, xRms, yCom, yRms); + textCom = new Overlays.Text(renderer.getPenProfile(), text, fontInfoText, textPosition); + textCom.setFixed(true); + textCom.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_LEFT); + } + pOv = new Overlay[]{hprofile, vprofile, textCom}; + textPosition = new Point(textPosition.x, textPosition.y + 34); + } + if (showFit) { + Overlays.Crosshairs cross = null; + Overlays.Text textFit = null; + if ((xMean != null) && (yMean != null)) { + String text = String.format("fit x: m=" + fmt + " \u03C3=" + fmt + "\nfit y: m=" + fmt + " \u03C3=" + fmt, xMean, xSigma, yMean, ySigma); + textFit = new Overlays.Text(penFit, text, fontInfoText, textPosition); + textFit.setFixed(true); + textFit.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_LEFT); + Point center = new Point(xMean.intValue(), yMean.intValue()); + if (renderer.getCalibration() != null) { + center = renderer.getCalibration().convertToImagePosition(new PointDouble(xMean, yMean)); + xSigma /= renderer.getCalibration().getScaleX(); + ySigma /= renderer.getCalibration().getScaleY(); + } + cross = new Overlays.Crosshairs(penCross, center, new Dimension(Math.abs(2 * xSigma.intValue()), 2 * Math.abs(ySigma.intValue()))); + } + textPosition = new Point(textPosition.x, textPosition.y + 34); + fOv = new Overlay[]{hgaussian, vgaussian, cross, textFit}; + + if (goodRegion && (id != null)) { + try { + double[] x = id.gr_x_axis; + double[] y = id.gr_y_axis; + Overlays.Rect goodRegionOv = new Overlays.Rect(new Pen(penFit.getColor(), 0, Pen.LineStyle.dotted)); + goodRegionOv.setCalibration(renderer.getCalibration()); + goodRegionOv.setPosition(new Point(id.gr_pos_x, id.gr_pos_y)); + goodRegionOv.setSize(new Dimension(id.gr_x_axis.length, id.gr_y_axis.length)); + fOv = Arr.append(fOv, goodRegionOv); + + if (slicing) { + if (sliceCenters != null) { + for (PointDouble sliceCenter : sliceCenters) { + Overlays.Crosshairs center = new Overlays.Crosshairs(penSlices); + center.setCalibration(renderer.getCalibration()); + center.setAbsolutePosition(sliceCenter); + center.setSize(new Dimension(10, 10)); + fOv = Arr.append(fOv, center); + } + if (sliceCenters.length > 1) { + double[] fit = fitPolynomial(sliceCenters, 1); + double angle = Math.toDegrees(Math.atan(fit[1])); + Overlays.Text text = new Overlays.Text(penSlices, String.format("slice: \u03B8= %5.1fdeg", angle), fontInfoText, textPosition); + text.setFixed(true); + text.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_LEFT); + fOv = Arr.append(fOv, text); + } + } + } + } catch (Exception ex) { + } + } + + } + return new Overlay[][]{pOv, fOv}; + } + return null; + } + + class UserOverlay { + + String name; + Overlay obj; + String[] channels; + } + ArrayList userOverlayConfig; + + void parseUserOverlays() { + Properties userOverlays = new Properties(); + userOverlayConfig = new ArrayList<>(); + if (userOverlaysConfigFile != null) { + try { + try (FileInputStream in = new FileInputStream(getContext().getSetup().expandPath(userOverlaysConfigFile))) { + userOverlays.load(in); + + for (String name : userOverlays.stringPropertyNames()) { + String val = userOverlays.getProperty(name); + try { + UserOverlay uo = new UserOverlay(); + uo.name = name; + String type = val.substring(0, val.indexOf("(")).trim(); + String pars = val.substring(val.indexOf("(") + 1, val.lastIndexOf(")")).trim(); + String[] tokens = pars.split(","); + for (int i = 0; i < tokens.length; i++) { + tokens[i] = tokens[i].trim(); + } + Color color = Color.GRAY; + try { + color = (Color) Color.class.getField(tokens[tokens.length - 1].toUpperCase()).get(null); + } catch (Exception ex) { + } + Pen pen = new Pen(color); + try { + String[] penTokens = tokens[tokens.length - 1].split(":"); + color = (Color) Color.class.getField(penTokens[0].toUpperCase()).get(null); + int width = Integer.valueOf(penTokens[1]); + Pen.LineStyle style = Pen.LineStyle.valueOf(penTokens[2]); + pen = new Pen(color, width, style); + } catch (Exception ex) { + } + switch (type) { + case "Point": + uo.obj = new Overlays.Crosshairs(); + uo.obj.setSize(new Dimension(Integer.valueOf(tokens[2]), Integer.valueOf(tokens[3]))); + break; + case "Line": + uo.obj = new Overlays.Line(); + break; + case "Arrow": + uo.obj = new Overlays.Arrow(); + break; + case "Rect": + uo.obj = new Overlays.Rect(); + break; + case "Ellipse": + uo.obj = new Overlays.Ellipse(); + break; + case "Polyline": + uo.obj = new Overlays.Polyline(); + break; + } + if (type.equals("Polyline") || type.equals("Point")) { + uo.channels = new String[]{tokens[0], tokens[1]}; + } else { + uo.channels = new String[]{tokens[0], tokens[1], tokens[2], tokens[3]}; + } + uo.obj.setPen(pen); + userOverlayConfig.add(uo); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + Overlay[] getUserOverlays(Data data) { + ArrayList ret = new ArrayList<>(); + if (server != null) { + ImageData id = getFrame(data); + for (UserOverlay uo : userOverlayConfig) { + try { + Overlay ov = uo.obj; + //Overlay ov = (Overlay)uo.cls.newInstance(); + ov.setCalibration(renderer.getCalibration()); + boolean valid = false; + if (ov instanceof Overlays.Polyline) { + double[] x = (uo.channels[0].equals("null")) ? null : id.getDoubleArray(uo.channels[0]); + double[] y = (uo.channels[1].equals("null")) ? null : id.getDoubleArray(uo.channels[1]); + if ((x != null) || (y != null)) { + if (x == null) { + x = (renderer.getCalibration() == null) ? Arr.indexesDouble(y.length) : renderer.getCalibration().getAxisX(y.length); + } + if (y == null) { + y = (renderer.getCalibration() == null) ? Arr.indexesDouble(x.length) : renderer.getCalibration().getAxisY(x.length); + } + ((Overlays.Polyline) ov).updateAbsolute(x, y); + valid = true; + } + } else { + Double x = id.getDouble(uo.channels[0]); + Double y = id.getDouble(uo.channels[1]); + if ((x != null) && (y != null)) { + PointDouble position = new PointDouble(x, y); + ov.setAbsolutePosition(position); + if (!(ov instanceof Overlays.Crosshairs)) { + Double x2 = id.getDouble(uo.channels[2]); + Double y2 = id.getDouble(uo.channels[3]); + if ((x != null) && (y != null)) { + DimensionDouble size = new DimensionDouble(x2 - position.x, y2 - position.y); + ov.setAbsoluteSize(size); + valid = true; + } + } else { + valid = true; + } + } + } + if (valid) { + ret.add(ov); + } + } catch (Exception ex) { + //ex.printStackTrace(); + } + } + } + return ret.toArray(new Overlay[0]); + } + + double[] getComRms(double[] arr, double[] x) { + if (arr != null) { + double xmd = 0; + double xmd2 = 0; + double total = 0; + for (int i = 0; i < arr.length; i++) { + double v = (arr[i] * x[i]); + xmd += v; + xmd2 += (v * x[i]); + total += arr[i]; + } + if (total > 0) { + double com = xmd / total; + double com2 = xmd2 / total; + double rms = Math.sqrt(Math.abs(com2 - com * com)); + return new double[]{com, rms}; + } + } + return new double[]{Double.NaN, Double.NaN}; + } + + double[] fitGaussianScript(int[] y, int[] x) { + ScriptManager sm = Context.getInstance().getScriptManager(); + ArrayProperties pY = ArrayProperties.get(y); + sm.setVar("y", y); + sm.setVar("x", x); + InterpreterResult r = sm.eval("r = fit_gaussians(y, x, [" + pY.maxIndex + ",])"); + if (r.exception != null) { + r.exception.printStackTrace(); + } else { + List ret = (List) sm.getVar("r"); + if ((ret != null) && (ret.size() == 1) && (ret.get(0) instanceof List) && (((List) (ret.get(0))).size() == 3)) { + double norm = (Double) ((List) ret.get(0)).get(0); + double mean = (Double) ((List) ret.get(0)).get(1); + double sigma = (Double) ((List) ret.get(0)).get(2); + return new double[]{norm, mean, sigma}; + } + } + return null; + } + + double[] fitGaussian(double[] y, int[] x) { + try { + ArrayProperties pY = ArrayProperties.get(y); + GaussianCurveFitter fitter = GaussianCurveFitter.create().withStartPoint(new double[]{(pY.max - pY.min) / 2, x[pY.maxIndex], 1.0}).withMaxIterations(1000); + ArrayList values = new ArrayList<>(); + for (int i = 0; i < y.length; i++) { + values.add(new WeightedObservedPoint(1.0, x[i], y[i])); + } + return fitter.fit(values); + } catch (Exception ex) { + return null; + } + + } + + double[] fitPolynomial(PointDouble[] points, int order) { + double[] y = new double[points.length]; + double[] x = new double[points.length]; + for (int i = 0; i < points.length; i++) { + x[i] = points[i].x; + y[i] = points[i].y; + } + return fitPolynomial(y, x, order); + } + + double[] fitPolynomial(double[] y, double[] x, int order) { + try { + ArrayProperties pY = ArrayProperties.get(y); + PolynomialCurveFitter fitter = PolynomialCurveFitter.create(order).withMaxIterations(1000); + ArrayList values = new ArrayList<>(); + for (int i = 0; i < y.length; i++) { + values.add(new WeightedObservedPoint(1.0, x[i], y[i])); + } + return fitter.fit(values); + } catch (Exception ex) { + return null; + } + + } + + double[] getFitFunction(double[] pars, int[] x) { + double[] fit = new double[x.length]; + Gaussian g = new Gaussian(pars[0], pars[1], pars[2]); + for (int i = 0; i < x.length; i++) { + fit[i] = g.value(x[i]); + } + return fit; + } + + void setHistogramVisible(boolean value) { + if (value) { + if ((histogramDialog == null) || (!histogramDialog.isShowing())) { + Histogram histogram = new Histogram(true); + histogram.setRenderer(renderer); + histogramDialog = SwingUtils.showDialog(SwingUtils.getWindow(renderer), "Histogram", null, histogram); + renderer.refresh(); + } + } else { + if (histogramDialog != null) { + histogramDialog.setVisible(false); + histogramDialog = null; + } + } + } + + void setLaserState(int bunch, boolean value) throws Exception { + System.out.println("Setting laser state: " + value + " - bunch" + bunch); + //Epics.putq("SIN-TIMAST-TMA:Beam-Las-Delay-Sel", value ? 0 : 1); + if ((bunch<=0) || (bunch==1)){ + Epics.putq("SIN-TIMAST-TMA:Bunch-1-OnDelay-Sel", value ? 0 : 1); + } + if ((bunch<=0) || (bunch==2)){ + Epics.putq("SIN-TIMAST-TMA:Bunch-2-OnDelay-Sel", value ? 0 : 1); + } + + Epics.putq("SIN-TIMAST-TMA:Beam-Apply-Cmd.PROC", 1); + Thread.sleep(3000); + } + + boolean getLaserState(int bunch) throws Exception { + //return (Epics.get("SIN-TIMAST-TMA:Beam-Las-Delay-Sel", Integer.class) == 0); + try{ + if (bunch<=0){ + return getLaserState(1) && getLaserState(2); + } + if (bunch==2){ + return (Epics.get("SWISSFEL-STATUS:Bunch-2-OnDelay-Sel", Integer.class) == 0); + } + return (Epics.get("SWISSFEL-STATUS:Bunch-1-OnDelay-Sel", Integer.class) == 0); + } catch (Exception ex){ + return false; + } + } + + void elog(String logbook, String title, String message, String[] attachments) throws Exception { + String domain = ""; + String category = "Info"; + String entry = ""; + StringBuffer cmd = new StringBuffer(); + + cmd.append("G_CS_ELOG_add -l \"").append(logbook).append("\" "); + cmd.append("-a \"Author=ScreenPanel\" "); + cmd.append("-a \"Type=pshell\" "); + cmd.append("-a \"Entry=").append(entry).append("\" "); + cmd.append("-a \"Title=").append(title).append("\" "); + cmd.append("-a \"Category=").append(category).append("\" "); + cmd.append("-a \"Domain=").append(domain).append("\" "); + for (String attachment : attachments) { + cmd.append("-f \"").append(attachment).append("\" "); + } + cmd.append("-n 1 "); + cmd.append("\"").append(message).append("\" "); + System.out.println(cmd.toString()); + + final Process process = Runtime.getRuntime().exec(new String[]{"bash", "-c", cmd.toString()}); + new Thread(() -> { + try { + process.waitFor(); + int bytes = process.getInputStream().available(); + byte[] arr = new byte[bytes]; + process.getInputStream().read(arr, 0, bytes); + System.out.println(new String(arr)); + bytes = process.getErrorStream().available(); + arr = new byte[bytes]; + process.getErrorStream().read(arr, 0, bytes); + System.err.println(new String(arr)); + } catch (Exception ex) { + System.err.println(ex); + } + }).start(); + } + + void centralizeRenderer() { + Point center = null; + Dimension size = renderer.getImageSize(); + double zoom = (renderer.getMode() == RendererMode.Fixed) ? 1.0 : renderer.getZoom(); + if (renderer.getCalibration() != null) { + center = renderer.getCalibration().getCenter(); + } else if (size != null) { + center = new Point(size.width / 2, size.height / 2); + } + if (center != null) { + Point topleft = new Point(Math.max((int) (center.x - renderer.getWidth() / 2 / zoom), 0), + Math.max((int) (center.y - renderer.getHeight() / 2 / zoom), 0)); + renderer.setViewPosition(topleft); + } + } + + void updatePause() { + int index = ((int) pauseSelection.getValue()) - 1; + synchronized (imageBuffer) { + if (index < imageBuffer.size()) { + Data data = imageBuffer.get(index).data; + long pid = imageBuffer.get(index).cache.getPulseId(); + BufferedImage image = camera.generateImage(data); + renderer.setImage(renderer.getOrigin(), image, data); + + String text = "PID: " + pid; + if (imagePauseOverlay == null) { + Font font = new Font("Verdana", Font.PLAIN, 12); + Dimension d = SwingUtils.getTextSize(text, renderer.getFontMetrics(font)); + imagePauseOverlay = new Text(renderer.getPenErrorText(), "", font, new Point(-20 - d.width, 42)); + imagePauseOverlay.setFixed(true); + imagePauseOverlay.setAnchor(Overlay.ANCHOR_VIEWPORT_OR_IMAGE_TOP_RIGHT); + renderer.addOverlay(imagePauseOverlay); + } + imagePauseOverlay.update(text); + manageFit(image, data); + manageUserOverlays(image, data); + } + } + } + + void removePauseOverlay() { + renderer.removeOverlay(imagePauseOverlay); + imagePauseOverlay = null; + } + + void saveSnapshot() throws Exception { + boolean paused = isPaused(); + try{ + if (!paused){ + setPaused(true); + } + String snapshotFile = null; + synchronized (imageBuffer) { + Frame frame = getCurrentFrame(); + if (frame == null) { + throw new Exception("No current image"); + } + ArrayList frames = new ArrayList<>(); + frames.add(frame); + this.saveFrames(cameraAlias + "_camera_snapshot", frames); + + //Enforce the same timestamp to data & image files. + snapshotFile = getContext().getExecutionPars().getPath() + ".png"; + //renderer.saveSnapshot(snapshotFile, "png", true); + ImageBuffer.saveImage(SwingUtils.createImage(renderer), snapshotFile, "png"); + } + + JPanel panel = new JPanel(); + GridBagLayout layout = new GridBagLayout(); + layout.columnWidths = new int[]{0, 180}; //Minimum width + layout.rowHeights = new int[]{30, 30, 30}; //Minimum height + panel.setLayout(layout); + JComboBox comboLogbook = new JComboBox(new String[]{"SwissFEL commissioning data", "SwissFEL commissioning"}); + JTextField textComment = new JTextField(); + GridBagConstraints c = new GridBagConstraints(); + c.gridx = 0; + c.gridy = 0; + panel.add(new JLabel("Data file:"), c); + c.gridy = 1; + panel.add(new JLabel("Logbook:"), c); + c.gridy = 2; + panel.add(new JLabel("Comment:"), c); + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 1; + panel.add(textComment, c); + c.gridy = 1; + panel.add(comboLogbook, c); + c.gridy = 0; + panel.add(new JLabel(getContext().getExecutionPars().getPath()), c); + + if (SwingUtils.showOption(getTopLevel(), "Success", panel, OptionType.OkCancel) == OptionResult.Yes) { + StringBuilder message = new StringBuilder(); + message.append("Camera: ").append(cameraAlias).append(" ("). + append((server != null) ? "server" : "direct").append(")").append("\n"); + message.append("Screen: ").append(String.valueOf(valueScreen.getLabel().getText())).append("\n"); + message.append("Filter: ").append(String.valueOf(valueFilter.getLabel().getText())).append("\n"); + message.append("Data file: ").append(getContext().getExecutionPars().getPath()).append("\n"); + message.append("Comment: ").append(textComment.getText()).append("\n"); + //Add slicing message + if ((fitOv != null) && (fitOv.length > 5) && (fitOv[fitOv.length - 1] instanceof Overlays.Text)) { + Overlays.Text text = (Overlays.Text) fitOv[fitOv.length - 1]; + message.append(text.getText()).append("\n"); + } + elog((String) comboLogbook.getSelectedItem(), "ScreenPanel Snapshot", message.toString(), new String[]{snapshotFile}); + } + } finally{ + if (!paused){ + setPaused(false); + } + } + } + + void saveStack() throws Exception { + synchronized (imageBuffer) { + saveFrames(cameraAlias + "_camera_stack", imageBuffer); + } + SwingUtils.showMessage(getTopLevel(), "Success", "Generated data file:\n" + getContext().getExecutionPars().getPath()); + } + + public List getCameraTypes(String name) { + if (name == null) { + return null; + } + if (App.hasArgument(ARG_ALIAS) && (aliases!=null)){ + name = aliases.getOrDefault(name, name); + } + + List ret = new ArrayList(); + if (groups!=null){ + for (String group: Arr.sort(groups.keySet().toArray(new String[0]))){ + if (groups.get(group).contains(name)){ + ret.add(group); + } + } + } else { + for (String s : new String[]{"LCAM"}) { + if (name.contains(s)) { + ret.add(LASER_TYPE); + } + } + for (String s : new String[]{"DSCR", "DSRM", "DLAC"}) { + if (name.contains(s)) { + ret.add(ELECTRONS_TYPE); + } + } + for (String s : new String[]{"PROF", "PPRM", "PSSS", "PSCR", "PSRD"}) { + if (name.contains(s)) { + ret.add(PHOTONICS_TYPE); + } + } + } + ret.add("Unknown"); + return ret; + } + + public Map getProcessingParameters(StreamValue value) throws IOException { + return (Map) JsonSerializer.decode(value.getValue("processing_parameters").toString(), Map.class); + } + + void saveFrames(String name, ArrayList frames) throws IOException { + ArrayList values = new ArrayList<>(); + for (Frame frame : frames) { + values.add(frame.cache); + } + saveImages(name, values); + } + + class DifferentFormatException extends IOException{ + DifferentFormatException(){ + super("Images in stack have different formats"); + } + } + + boolean hasSameFormat(ArrayList frames){ + if (frames.size()>0){ + StreamValue first = frames.get(0).cache; + int width = ((Number) first.getValue("width")).intValue(); + int height = ((Number) first.getValue("height")).intValue(); + Class dataType = first.getValue("image").getClass().getComponentType(); + + for (Frame frame : frames){ + StreamValue image = frame.cache; + if ( (width != ((Number) image.getValue("width")).intValue()) || + (height != ((Number) image.getValue("height")).intValue()) || + (dataType != (image.getValue("image").getClass().getComponentType()))){ + return false; + } + } + } + return true; + } + + void saveImages(String name, ArrayList images) throws IOException { + int depth = images.size(); + if (depth == 0) { + return; + } + + StreamValue first = images.get(0); + String pathRoot = "/camera1/"; + String pathImage = pathRoot + "image"; + String pathPid = pathRoot + "pulse_id"; + String pathTimestampStr = pathRoot + "timestamp_str"; + Map processingPars = getProcessingParameters(first); + String camera = (String) processingPars.get("camera_name"); + List types = getCameraTypes(camera); + + int width = ((Number) first.getValue("width")).intValue(); + int height = ((Number) first.getValue("height")).intValue(); + Class dataType = first.getValue("image").getClass().getComponentType(); + + for (StreamValue image : images){ + if ( (width != ((Number) image.getValue("width")).intValue()) || + (height != ((Number) image.getValue("height")).intValue()) || + (dataType != (image.getValue("image").getClass().getComponentType()))){ + throw new DifferentFormatException(); + } + } + + + getContext().setExecutionPars(name); + DataManager dm = getContext().getDataManager(); + + //Create tables + dm.createDataset(pathImage, dataType, new int[]{depth, height, width}); + dm.createDataset(pathPid, Long.class, new int[]{depth}); + dm.createDataset(pathTimestampStr, String.class, new int[]{depth}); + for (String id : first.getIdentifiers()) { + Object val = first.getValue(id); + if (id.equals("image")) { + } else if (id.equals("processing_parameters")) { + Map pars = getProcessingParameters(first); + for (String key : pars.keySet()) { + if ((pars.get(key) != null) && (pars.get(key) instanceof Map)) { + for (String k : ((Map) pars.get(key)).keySet()) { + Object v = ((Map) pars.get(key)).get(k); + k = key + " " + k; + v = (v == null) ? "" : v; + try{ + dm.setAttribute(pathImage, k, v); + } catch (Exception ex){ + logger.info("Cannot set attribute " + pathImage + ": "+ k + " = " + v + " - " + ex.getMessage()); + } + + } + } else { + Object value = pars.get(key); + try{ + if (value == null) { + value = ""; + } else if (value instanceof List) { + if (((List) value).size() > 0){ + Class cls = ((List) value).get(0).getClass() ; + if (cls == String.class){ + value = ((List) value).toArray(new String[0]); + } else { + value = Convert.toPrimitiveArray(value, cls); + } + } else { + value = ""; + } + } + dm.setAttribute(pathImage, key, value); + } catch (Exception ex){ + logger.info("Cannot set attribute " + pathImage + ": "+ key + " = " + value + " - " + ex.getMessage()); + } + } + } + } else if (val.getClass().isArray()) { + dm.createDataset(pathRoot + id, Double.class, new int[]{depth, Array.getLength(val)}); + } else { + dm.createDataset(pathRoot + id, val.getClass(), new int[]{depth}); + } + } + + //Add metadata + dm.setAttribute(pathRoot, "Camera", camera); + dm.setAttribute(pathRoot, "Images", depth); + dm.setAttribute(pathRoot, "Interval", -1); + dm.setAttribute(pathRoot, "Type", types.toArray(new String[0])); + if (types.contains(ELECTRONS_TYPE)) { + dm.setAttribute(pathRoot, "Screen", String.valueOf(valueScreen.getLabel().getText())); + dm.setAttribute(pathRoot, "Filter", String.valueOf(valueFilter.getLabel().getText())); + } + + //Save data + for (int index = 0; index < depth; index++) { + StreamValue streamValue = images.get(index); + dm.setItem(pathImage, streamValue.getValue("image"), new long[]{index, 0, 0}, new int[]{1, height, width}); + dm.setItem(pathPid, streamValue.getPulseId(), index); + dm.setItem(pathTimestampStr, Chrono.getTimeStr(streamValue.getTimestamp(), "YYYY-MM-dd HH:mm:ss.SSS"), index); + + for (String id : streamValue.getIdentifiers()) { + try{ + Object val = streamValue.getValue(id); + if (id.equals("image")) { + } else if (id.equals("processing_parameters")) { + } else if (val.getClass().isArray()) { + dm.setItem(pathRoot + id, val, index); + } else { + dm.setItem(pathRoot + id, val, index); + } + } catch (Exception ex){ + logger.log(Level.WARNING, null, ex); + System.out.println("Error saving " + id + " index " + index + ": " + ex.getMessage()); + } + } + } + getContext().getDataManager().closeOutput(); + } + + StandardDialog calibrationDialolg; + + void calibrate() throws Exception { + if (server != null) { + server.resetRoi(); + calibrationDialolg = (StandardDialog) getContext().getClassByName("CameraCalibrationDialog").getConstructors()[0].newInstance(new Object[]{getTopLevel(), server.getCurrentCamera(), renderer}); + SwingUtils.centerComponent(getTopLevel(), calibrationDialolg); + calibrationDialolg.setVisible(true); + calibrationDialolg.setListener(new StandardDialogListener() { + @Override + public void onWindowOpened(StandardDialog dlg) { + } + + @Override + public void onWindowClosed(StandardDialog dlg, boolean accepted) { + if (accepted) { + //comboCamerasActionPerformed(null); + } + } + }); + } + } + + ImageIcon getIcon(String name) { + ImageIcon ret = null; + try { + //Path path = Paths.get(getClass().getProtectionDomain().getCodeSource().getLocation().getPath(),"resources", name + ".png"); + String dir = getClass().getProtectionDomain().getCodeSource().getLocation().getPath() + "resources/"; + if (new File(dir + name + ".png").exists()) { + ret = new javax.swing.ImageIcon(dir + name + ".png"); + } else { + ret = new ImageIcon(ch.psi.pshell.ui.App.class.getResource("/ch/psi/pshell/ui/" + name + ".png")); + if (MainFrame.isDark()) { + try { + ret = new ImageIcon(ch.psi.pshell.ui.App.class.getResource("/ch/psi/pshell/ui/dark/" + name + ".png")); + } catch (Exception e) { + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return ret; + } + + String getIconName(JButton button) { + String ret = button.getIcon().toString(); + if (ret.indexOf(".") > 0) { + ret = ret.substring(0, ret.indexOf(".")); + } + return ret; + } + + void setPaused(boolean paused){ + removePauseOverlay(); + if (camera != null) { + synchronized (imageBuffer) { + if (paused) { + renderer.pause(); + panelCameraSelection.setVisible(false); + pauseSelection.setVisible(true); + if (imageBuffer.size() > 0) { + pauseSelection.setEnabled(true); + pauseSelection.setMaxValue(imageBuffer.size()); + pauseSelection.setValue(imageBuffer.size()); + updatePause(); + } else { + pauseSelection.setEnabled(false); + pauseSelection.setMaxValue(1); + pauseSelection.setValue(1); + } + } else { + imageBuffer.clear(); + renderer.resume(); + //renderer.clear(); + pauseSelection.setVisible(false); + panelCameraSelection.setVisible(true); + } + } + } + } + + boolean isPaused(){ + return renderer.isPaused(); + } + + //////// + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + buttonGroup1 = new javax.swing.ButtonGroup(); + buttonGroup2 = new javax.swing.ButtonGroup(); + buttonGroup3 = new javax.swing.ButtonGroup(); + buttonGroup4 = new javax.swing.ButtonGroup(); + jProgressBar1 = new javax.swing.JProgressBar(); + sidePanel = new javax.swing.JPanel(); + panelZoom = new javax.swing.JPanel(); + buttonZoomFit = new javax.swing.JRadioButton(); + buttonZoomStretch = new javax.swing.JRadioButton(); + buttonZoomNormal = new javax.swing.JRadioButton(); + buttonZoom025 = new javax.swing.JRadioButton(); + buttonZoom05 = new javax.swing.JRadioButton(); + buttonZoom2 = new javax.swing.JRadioButton(); + panelColormap = new javax.swing.JPanel(); + checkHistogram = new javax.swing.JCheckBox(); + comboColormap = new javax.swing.JComboBox(); + jLabel3 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + buttonFullRange = new javax.swing.JRadioButton(); + buttonManual = new javax.swing.JRadioButton(); + buttonAutomatic = new javax.swing.JRadioButton(); + labelMin = new javax.swing.JLabel(); + spinnerMin = new javax.swing.JSpinner(); + spinnerMax = new javax.swing.JSpinner(); + labelMax = new javax.swing.JLabel(); + btFixColormapRange = new javax.swing.JButton(); + panelScreen = new javax.swing.JPanel(); + valueScreen = new ch.psi.pshell.swing.DeviceValuePanel(); + comboScreen = new javax.swing.JComboBox(); + panelFilter = new javax.swing.JPanel(); + valueFilter = new ch.psi.pshell.swing.DeviceValuePanel(); + comboFilter = new javax.swing.JComboBox(); + panelPipeline = new javax.swing.JPanel(); + checkThreshold = new javax.swing.JCheckBox(); + spinnerThreshold = new javax.swing.JSpinner(); + checkBackground = new javax.swing.JCheckBox(); + checkGoodRegion = new javax.swing.JCheckBox(); + spinnerGrScale = new javax.swing.JSpinner(); + spinnerGrThreshold = new javax.swing.JSpinner(); + labelGrThreshold = new javax.swing.JLabel(); + labelGrScale = new javax.swing.JLabel(); + panelSlicing = new javax.swing.JPanel(); + checkSlicing = new javax.swing.JCheckBox(); + labelSlScale = new javax.swing.JLabel(); + spinnerSlScale = new javax.swing.JSpinner(); + labelSlNumber = new javax.swing.JLabel(); + spinnerSlNumber = new javax.swing.JSpinner(); + labelSlOrientation = new javax.swing.JLabel(); + spinnerSlOrientation = new javax.swing.JSpinner(); + checkRotation = new javax.swing.JCheckBox(); + spinnerRotationAngle = new javax.swing.JSpinner(); + spinnerRotationOrder = new javax.swing.JSpinner(); + labelOrder = new javax.swing.JLabel(); + labelMode = new javax.swing.JLabel(); + spinnerRotationMode = new javax.swing.JSpinner(); + labelAngle = new javax.swing.JLabel(); + labelConstant = new javax.swing.JLabel(); + spinnerRotationConstant = new javax.swing.JSpinner(); + checkAveraging = new javax.swing.JCheckBox(); + spinnerAvFrames = new javax.swing.JSpinner(); + labelAvFrames = new javax.swing.JLabel(); + labelAvMode = new javax.swing.JLabel(); + spinnerAvMode = new javax.swing.JSpinner(); + spinnerBackground = new javax.swing.JSpinner(); + panelPulse = new javax.swing.JPanel(); + buttonPulse1 = new javax.swing.JButton(); + buttonPulse2 = new javax.swing.JButton(); + textPulse = new javax.swing.JTextField(); + topPanel = new javax.swing.JPanel(); + toolBar = new javax.swing.JToolBar(); + buttonSidePanel = new javax.swing.JToggleButton(); + buttonStreamData = new javax.swing.JButton(); + buttonSave = new javax.swing.JToggleButton(); + buttonGrabBackground = new javax.swing.JButton(); + buttonPause = new javax.swing.JToggleButton(); + jSeparator6 = new javax.swing.JToolBar.Separator(); + buttonMarker = new javax.swing.JToggleButton(); + buttonProfile = new javax.swing.JToggleButton(); + buttonFit = new javax.swing.JToggleButton(); + buttonReticle = new javax.swing.JToggleButton(); + buttonScale = new javax.swing.JToggleButton(); + buttonTitle = new javax.swing.JToggleButton(); + pauseSelection = new ch.psi.pshell.swing.ValueSelection(); + panelCameraSelection = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + comboCameras = new javax.swing.JComboBox(); + labelType = new javax.swing.JLabel(); + comboType = new javax.swing.JComboBox(); + renderer = new ch.psi.pshell.imaging.Renderer(); + + setPreferredSize(new java.awt.Dimension(873, 600)); + + panelZoom.setBorder(javax.swing.BorderFactory.createTitledBorder("Zoom")); + + buttonGroup1.add(buttonZoomFit); + buttonZoomFit.setText("Fit"); + buttonZoomFit.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoomFitActionPerformed(evt); + } + }); + + buttonGroup1.add(buttonZoomStretch); + buttonZoomStretch.setText("Stretch"); + buttonZoomStretch.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoomStretchActionPerformed(evt); + } + }); + + buttonGroup1.add(buttonZoomNormal); + buttonZoomNormal.setText("Normal"); + buttonZoomNormal.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoomNormalActionPerformed(evt); + } + }); + + buttonGroup1.add(buttonZoom025); + buttonZoom025.setText("1/4"); + buttonZoom025.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoom025ActionPerformed(evt); + } + }); + + buttonGroup1.add(buttonZoom05); + buttonZoom05.setText("1/2"); + buttonZoom05.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoom05ActionPerformed(evt); + } + }); + + buttonGroup1.add(buttonZoom2); + buttonZoom2.setText("2"); + buttonZoom2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoom2ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelZoomLayout = new javax.swing.GroupLayout(panelZoom); + panelZoom.setLayout(panelZoomLayout); + panelZoomLayout.setHorizontalGroup( + panelZoomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelZoomLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelZoomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonZoomFit) + .addComponent(buttonZoomNormal) + .addComponent(buttonZoomStretch)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(panelZoomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonZoom025) + .addComponent(buttonZoom05) + .addComponent(buttonZoom2)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + panelZoomLayout.setVerticalGroup( + panelZoomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelZoomLayout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(panelZoomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonZoomNormal) + .addComponent(buttonZoom025)) + .addGap(0, 0, 0) + .addGroup(panelZoomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonZoomFit) + .addComponent(buttonZoom05)) + .addGap(0, 0, 0) + .addGroup(panelZoomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonZoomStretch) + .addComponent(buttonZoom2)) + .addContainerGap()) + ); + + panelColormap.setBorder(javax.swing.BorderFactory.createTitledBorder("Colormap")); + + checkHistogram.setText("Histogram"); + checkHistogram.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkHistogramActionPerformed(evt); + } + }); + + comboColormap.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + onChangeColormap(evt); + } + }); + + jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel3.setText("Type:"); + + jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel4.setText("Range:"); + + buttonGroup3.add(buttonFullRange); + buttonFullRange.setText("Full"); + buttonFullRange.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + onChangeColormap(evt); + } + }); + + buttonGroup3.add(buttonManual); + buttonManual.setText("Manual"); + buttonManual.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + onChangeColormap(evt); + } + }); + + buttonGroup3.add(buttonAutomatic); + buttonAutomatic.setText("Automatic"); + buttonAutomatic.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + onChangeColormap(evt); + } + }); + + labelMin.setText("Min:"); + + spinnerMin.setModel(new javax.swing.SpinnerNumberModel(0, 0, 65535, 1)); + spinnerMin.setEnabled(false); + spinnerMin.setPreferredSize(new java.awt.Dimension(77, 20)); + spinnerMin.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + onChangeColormapRange(evt); + } + }); + + spinnerMax.setModel(new javax.swing.SpinnerNumberModel(255, 0, 65535, 1)); + spinnerMax.setEnabled(false); + spinnerMax.setPreferredSize(new java.awt.Dimension(77, 20)); + spinnerMax.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + onChangeColormapRange(evt); + } + }); + + labelMax.setText("Max:"); + + btFixColormapRange.setText("Fix"); + btFixColormapRange.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btFixColormapRangeActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelColormapLayout = new javax.swing.GroupLayout(panelColormap); + panelColormap.setLayout(panelColormapLayout); + panelColormapLayout.setHorizontalGroup( + panelColormapLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelColormapLayout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(panelColormapLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel3) + .addComponent(jLabel4)) + .addGap(4, 4, 4) + .addGroup(panelColormapLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonAutomatic) + .addComponent(buttonFullRange) + .addComponent(buttonManual) + .addComponent(comboColormap, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(panelColormapLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelColormapLayout.createSequentialGroup() + .addComponent(labelMax) + .addGap(2, 2, 2) + .addComponent(spinnerMax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(checkHistogram, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelColormapLayout.createSequentialGroup() + .addComponent(labelMin) + .addGap(2, 2, 2) + .addGroup(panelColormapLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btFixColormapRange, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(spinnerMin, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + .addContainerGap()) + ); + + panelColormapLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {btFixColormapRange, spinnerMax, spinnerMin}); + + panelColormapLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel3, jLabel4}); + + panelColormapLayout.setVerticalGroup( + panelColormapLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelColormapLayout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(panelColormapLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(comboColormap, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel3) + .addComponent(checkHistogram)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(panelColormapLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonAutomatic) + .addComponent(jLabel4) + .addComponent(btFixColormapRange, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 0, 0) + .addGroup(panelColormapLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(labelMin) + .addComponent(spinnerMin, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonFullRange)) + .addGroup(panelColormapLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonManual) + .addComponent(labelMax) + .addComponent(spinnerMax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + panelScreen.setBorder(javax.swing.BorderFactory.createTitledBorder("Screen")); + + comboScreen.setEnabled(false); + comboScreen.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + comboScreenActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelScreenLayout = new javax.swing.GroupLayout(panelScreen); + panelScreen.setLayout(panelScreenLayout); + panelScreenLayout.setHorizontalGroup( + panelScreenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelScreenLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelScreenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(valueScreen, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(comboScreen, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + panelScreenLayout.setVerticalGroup( + panelScreenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelScreenLayout.createSequentialGroup() + .addGap(4, 4, 4) + .addComponent(comboScreen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(valueScreen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + panelFilter.setBorder(javax.swing.BorderFactory.createTitledBorder("Filter")); + + comboFilter.setEnabled(false); + comboFilter.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + comboFilterActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter); + panelFilter.setLayout(panelFilterLayout); + panelFilterLayout.setHorizontalGroup( + panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelFilterLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(valueFilter, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(comboFilter, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + panelFilterLayout.setVerticalGroup( + panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelFilterLayout.createSequentialGroup() + .addGap(4, 4, 4) + .addComponent(comboFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(valueFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + panelPipeline.setBorder(javax.swing.BorderFactory.createTitledBorder("Pipeline")); + + checkThreshold.setText("Threshold"); + checkThreshold.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkThresholdActionPerformed(evt); + } + }); + + spinnerThreshold.setModel(new javax.swing.SpinnerNumberModel(0.0d, 0.0d, 99999.0d, 1.0d)); + spinnerThreshold.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerThresholdonChange(evt); + } + }); + + checkBackground.setText("Subtract Background"); + checkBackground.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkBackgroundActionPerformed(evt); + } + }); + + checkGoodRegion.setText("Good Region"); + checkGoodRegion.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkGoodRegionActionPerformed(evt); + } + }); + + spinnerGrScale.setModel(new javax.swing.SpinnerNumberModel(3.0d, 0.01d, 99999.0d, 1.0d)); + spinnerGrScale.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerGrThresholdonChange(evt); + } + }); + + spinnerGrThreshold.setModel(new javax.swing.SpinnerNumberModel(0.5d, 0.04d, 1.0d, 0.1d)); + spinnerGrThreshold.setPreferredSize(new java.awt.Dimension(92, 20)); + spinnerGrThreshold.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerGrThresholdonChange(evt); + } + }); + + labelGrThreshold.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelGrThreshold.setText("Threshold:"); + + labelGrScale.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelGrScale.setText("Scale:"); + + checkSlicing.setText("Slicing"); + checkSlicing.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkSlicingActionPerformed(evt); + } + }); + + labelSlScale.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelSlScale.setText("Scale:"); + + spinnerSlScale.setModel(new javax.swing.SpinnerNumberModel(3.0d, 0.01d, 99999.0d, 1.0d)); + spinnerSlScale.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerSlicingChange(evt); + } + }); + + labelSlNumber.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelSlNumber.setText("Slices:"); + + spinnerSlNumber.setModel(new javax.swing.SpinnerNumberModel(2, 0, 1000, 1)); + spinnerSlNumber.setPreferredSize(new java.awt.Dimension(92, 20)); + spinnerSlNumber.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerSlicingChange(evt); + } + }); + + labelSlOrientation.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelSlOrientation.setText("Orientation:"); + + spinnerSlOrientation.setModel(new javax.swing.SpinnerListModel(new String[] {"vertical", "horizontal"})); + spinnerSlOrientation.setPreferredSize(new java.awt.Dimension(92, 20)); + spinnerSlOrientation.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerSlicingChange(evt); + } + }); + + javax.swing.GroupLayout panelSlicingLayout = new javax.swing.GroupLayout(panelSlicing); + panelSlicing.setLayout(panelSlicingLayout); + panelSlicingLayout.setHorizontalGroup( + panelSlicingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelSlicingLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelSlicingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelSlicingLayout.createSequentialGroup() + .addComponent(checkSlicing) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(panelSlicingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelSlicingLayout.createSequentialGroup() + .addComponent(labelSlNumber) + .addGap(2, 2, 2) + .addComponent(spinnerSlNumber, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelSlicingLayout.createSequentialGroup() + .addComponent(labelSlScale) + .addGap(2, 2, 2) + .addComponent(spinnerSlScale, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelSlicingLayout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(labelSlOrientation) + .addGap(2, 2, 2) + .addComponent(spinnerSlOrientation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap()) + ); + + panelSlicingLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spinnerSlNumber, spinnerSlOrientation, spinnerSlScale}); + + panelSlicingLayout.setVerticalGroup( + panelSlicingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelSlicingLayout.createSequentialGroup() + .addGroup(panelSlicingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(checkSlicing) + .addGroup(panelSlicingLayout.createSequentialGroup() + .addGroup(panelSlicingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerSlNumber, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelSlNumber)) + .addGap(0, 0, 0) + .addGroup(panelSlicingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerSlScale, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelSlScale)))) + .addGap(0, 0, 0) + .addGroup(panelSlicingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerSlOrientation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelSlOrientation))) + ); + + panelSlicingLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {spinnerSlNumber, spinnerSlOrientation, spinnerSlScale}); + + checkRotation.setText("Rotation"); + checkRotation.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkRotationActionPerformed(evt); + } + }); + + spinnerRotationAngle.setModel(new javax.swing.SpinnerNumberModel(0.0d, -360.0d, 360.0d, 1.0d)); + spinnerRotationAngle.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerRotationAngleStateChanged(evt); + } + }); + + spinnerRotationOrder.setModel(new javax.swing.SpinnerNumberModel(1, 1, 5, 1)); + spinnerRotationOrder.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerRotationAngleStateChanged(evt); + } + }); + + labelOrder.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelOrder.setText("Order:"); + + labelMode.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelMode.setText("Mode:"); + + spinnerRotationMode.setModel(new javax.swing.SpinnerListModel(new String[] {"constant", "reflect", "nearest", "mirror", "wrap", "ortho"})); + spinnerRotationMode.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerRotationAngleStateChanged(evt); + } + }); + + labelAngle.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelAngle.setText("Angle:"); + + labelConstant.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelConstant.setText("Constant:"); + + spinnerRotationConstant.setModel(new javax.swing.SpinnerNumberModel(0, 0, 99999, 1)); + spinnerRotationConstant.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerRotationAngleStateChanged(evt); + } + }); + + checkAveraging.setText("Averaging"); + checkAveraging.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkAveragingActionPerformed(evt); + } + }); + + spinnerAvFrames.setModel(new javax.swing.SpinnerNumberModel(1, 1, 1000, 1)); + spinnerAvFrames.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerAvFramesStateChanged(evt); + } + }); + + labelAvFrames.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelAvFrames.setText("Frames:"); + + labelAvMode.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + labelAvMode.setText("Mode:"); + + spinnerAvMode.setModel(new javax.swing.SpinnerListModel(new String[] {"single", "window"})); + spinnerAvMode.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerAvModeonChange(evt); + } + }); + + spinnerBackground.setModel(new javax.swing.SpinnerListModel(new String[] {"normal", "signed", "passive"})); + spinnerBackground.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerBackgroundStateChanged(evt); + } + }); + + javax.swing.GroupLayout panelPipelineLayout = new javax.swing.GroupLayout(panelPipeline); + panelPipeline.setLayout(panelPipelineLayout); + panelPipelineLayout.setHorizontalGroup( + panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panelSlicing, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(panelPipelineLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPipelineLayout.createSequentialGroup() + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPipelineLayout.createSequentialGroup() + .addComponent(checkAveraging) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(labelAvFrames, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(labelAvMode, javax.swing.GroupLayout.Alignment.TRAILING))) + .addGroup(panelPipelineLayout.createSequentialGroup() + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(checkGoodRegion) + .addComponent(checkRotation) + .addComponent(checkThreshold)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(labelOrder, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(labelAngle, javax.swing.GroupLayout.Alignment.TRAILING)) + .addComponent(labelGrScale, javax.swing.GroupLayout.Alignment.TRAILING))) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelPipelineLayout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(labelConstant, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(labelMode, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(labelGrThreshold, javax.swing.GroupLayout.Alignment.TRAILING)))) + .addGap(2, 2, 2)) + .addGroup(panelPipelineLayout.createSequentialGroup() + .addComponent(checkBackground) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(spinnerGrThreshold, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(spinnerGrScale, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(spinnerThreshold, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(spinnerRotationOrder, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(spinnerRotationMode, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(spinnerRotationAngle, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(spinnerRotationConstant, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(spinnerAvFrames, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(spinnerAvMode, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(spinnerBackground, javax.swing.GroupLayout.Alignment.TRAILING)) + .addContainerGap()) + ); + + panelPipelineLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spinnerAvFrames, spinnerAvMode, spinnerBackground, spinnerGrScale, spinnerGrThreshold, spinnerRotationAngle, spinnerRotationConstant, spinnerRotationMode, spinnerRotationOrder, spinnerThreshold}); + + panelPipelineLayout.setVerticalGroup( + panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPipelineLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(checkBackground) + .addComponent(spinnerBackground, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(checkThreshold) + .addComponent(spinnerThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(checkAveraging) + .addComponent(spinnerAvFrames, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelAvFrames)) + .addGap(2, 2, 2) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerAvMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelAvMode)) + .addGap(2, 2, 2) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(checkRotation) + .addComponent(spinnerRotationAngle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelAngle)) + .addGap(0, 0, 0) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerRotationOrder, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelOrder)) + .addGap(0, 0, 0) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerRotationMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelMode)) + .addGap(0, 0, 0) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerRotationConstant, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelConstant)) + .addGap(2, 2, 2) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(checkGoodRegion) + .addComponent(spinnerGrScale, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelGrScale)) + .addGap(0, 0, 0) + .addGroup(panelPipelineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerGrThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelGrThreshold)) + .addGap(2, 2, 2) + .addComponent(panelSlicing, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + panelPipelineLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {spinnerAvFrames, spinnerAvMode, spinnerBackground, spinnerGrScale, spinnerGrThreshold, spinnerRotationAngle, spinnerRotationConstant, spinnerRotationMode, spinnerRotationOrder, spinnerThreshold}); + + panelPulse.setBorder(javax.swing.BorderFactory.createTitledBorder("Pulse")); + + buttonPulse1.setText("Pulse 1"); + buttonPulse1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPulse1ActionPerformed(evt); + } + }); + + buttonPulse2.setText("Pulse 2"); + buttonPulse2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPulse2ActionPerformed(evt); + } + }); + + textPulse.setEditable(false); + textPulse.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + javax.swing.GroupLayout panelPulseLayout = new javax.swing.GroupLayout(panelPulse); + panelPulse.setLayout(panelPulseLayout); + panelPulseLayout.setHorizontalGroup( + panelPulseLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPulseLayout.createSequentialGroup() + .addContainerGap() + .addComponent(buttonPulse1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonPulse2) + .addGap(18, 18, Short.MAX_VALUE) + .addComponent(textPulse, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + panelPulseLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonPulse1, buttonPulse2}); + + panelPulseLayout.setVerticalGroup( + panelPulseLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPulseLayout.createSequentialGroup() + .addGroup(panelPulseLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonPulse1, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonPulse2, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(textPulse, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + javax.swing.GroupLayout sidePanelLayout = new javax.swing.GroupLayout(sidePanel); + sidePanel.setLayout(sidePanelLayout); + sidePanelLayout.setHorizontalGroup( + sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(sidePanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(panelZoom, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelColormap, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelPipeline, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelScreen, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelFilter, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelPulse, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + sidePanelLayout.setVerticalGroup( + sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(sidePanelLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(panelPipeline, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelZoom, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelColormap, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelScreen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelPulse, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + toolBar.setFloatable(false); + toolBar.setRollover(true); + + buttonSidePanel.setIcon(getIcon("List")); + buttonSidePanel.setSelected(true); + buttonSidePanel.setText(" "); + buttonSidePanel.setToolTipText("Show Side Panel"); + buttonSidePanel.setFocusable(false); + buttonSidePanel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonSidePanel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonSidePanelActionPerformed(evt); + } + }); + toolBar.add(buttonSidePanel); + + buttonStreamData.setIcon(getIcon("Details")); + buttonStreamData.setText(" "); + buttonStreamData.setToolTipText("Show Data Window"); + buttonStreamData.setFocusable(false); + buttonStreamData.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonStreamData.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonStreamDataActionPerformed(evt); + } + }); + toolBar.add(buttonStreamData); + + buttonSave.setIcon(getIcon("Save")); + buttonSave.setText(" "); + buttonSave.setToolTipText("Save Snapshot"); + buttonSave.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonSave.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonSaveActionPerformed(evt); + } + }); + toolBar.add(buttonSave); + + buttonGrabBackground.setIcon(getIcon("Background")); + buttonGrabBackground.setText(" "); + buttonGrabBackground.setToolTipText("Grab Background"); + buttonGrabBackground.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonGrabBackground.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonGrabBackgroundActionPerformed(evt); + } + }); + toolBar.add(buttonGrabBackground); + + buttonPause.setIcon(getIcon("Pause")); + buttonPause.setText(" "); + buttonPause.setToolTipText("Pause"); + buttonPause.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonPause.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPauseActionPerformed(evt); + } + }); + toolBar.add(buttonPause); + + jSeparator6.setMaximumSize(new java.awt.Dimension(20, 32767)); + jSeparator6.setPreferredSize(new java.awt.Dimension(20, 0)); + jSeparator6.setRequestFocusEnabled(false); + toolBar.add(jSeparator6); + + buttonMarker.setIcon(getIcon("Marker")); + buttonMarker.setText(" "); + buttonMarker.setToolTipText("Show Marker"); + buttonMarker.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonMarker.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMarkerActionPerformed(evt); + } + }); + toolBar.add(buttonMarker); + + buttonProfile.setIcon(getIcon("Profile" + + "")); + buttonProfile.setSelected(true); + buttonProfile.setText(" "); + buttonProfile.setToolTipText("Show Image Profile"); + buttonProfile.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonProfile.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonProfileActionPerformed(evt); + } + }); + toolBar.add(buttonProfile); + + buttonFit.setIcon(getIcon("Fit")); + buttonFit.setSelected(true); + buttonFit.setText(" "); + buttonFit.setToolTipText("Show Fit"); + buttonFit.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonFit.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonFitActionPerformed(evt); + } + }); + toolBar.add(buttonFit); + + buttonReticle.setIcon(getIcon("Reticule")); + buttonReticle.setSelected(true); + buttonReticle.setText(" "); + buttonReticle.setToolTipText("Show Reticle"); + buttonReticle.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonReticle.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonReticleActionPerformed(evt); + } + }); + toolBar.add(buttonReticle); + + buttonScale.setIcon(getIcon("Scale")); + buttonScale.setSelected(true); + buttonScale.setText(" "); + buttonScale.setToolTipText("Show Colormap Scale"); + buttonScale.setFocusable(false); + buttonScale.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonScale.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonScaleActionPerformed(evt); + } + }); + toolBar.add(buttonScale); + + buttonTitle.setIcon(getIcon("Title")); + buttonTitle.setSelected(true); + buttonTitle.setText(" "); + buttonTitle.setToolTipText("Show Camera Name"); + buttonTitle.setFocusable(false); + buttonTitle.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonTitle.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonTitleActionPerformed(evt); + } + }); + toolBar.add(buttonTitle); + + pauseSelection.setDecimals(0); + + jLabel1.setText("Camera:"); + + comboCameras.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N + comboCameras.setMaximumRowCount(30); + comboCameras.setMinimumSize(new java.awt.Dimension(127, 27)); + comboCameras.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + comboCamerasActionPerformed(evt); + } + }); + + labelType.setText("Type:"); + + comboType.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N + comboType.setMaximumRowCount(30); + comboType.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "All", "Laser", "Electrons", "Photonics" })); + comboType.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + comboTypeActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelCameraSelectionLayout = new javax.swing.GroupLayout(panelCameraSelection); + panelCameraSelection.setLayout(panelCameraSelectionLayout); + panelCameraSelectionLayout.setHorizontalGroup( + panelCameraSelectionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelCameraSelectionLayout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addGap(0, 0, 0) + .addComponent(comboCameras, javax.swing.GroupLayout.PREFERRED_SIZE, 222, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(labelType) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(comboType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0)) + ); + panelCameraSelectionLayout.setVerticalGroup( + panelCameraSelectionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelCameraSelectionLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelCameraSelectionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(comboType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(labelType) + .addComponent(jLabel1) + .addComponent(comboCameras, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 0, 0)) + ); + + javax.swing.GroupLayout topPanelLayout = new javax.swing.GroupLayout(topPanel); + topPanel.setLayout(topPanelLayout); + topPanelLayout.setHorizontalGroup( + topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, topPanelLayout.createSequentialGroup() + .addComponent(toolBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(panelCameraSelection, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(18, 18, 18) + .addComponent(pauseSelection, javax.swing.GroupLayout.PREFERRED_SIZE, 334, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + topPanelLayout.setVerticalGroup( + topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(topPanelLayout.createSequentialGroup() + .addGap(1, 1, 1) + .addGroup(topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(pauseSelection, javax.swing.GroupLayout.PREFERRED_SIZE, 29, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(toolBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelCameraSelection, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(sidePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(renderer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(topPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(topPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(sidePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(renderer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + ); + }// //GEN-END:initComponents + + private void buttonZoomFitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoomFitActionPerformed + try { + renderer.setMode(RendererMode.Fit); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonZoomFitActionPerformed + + private void buttonZoomStretchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoomStretchActionPerformed + try { + renderer.setMode(RendererMode.Stretch); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonZoomStretchActionPerformed + + private void buttonZoomNormalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoomNormalActionPerformed + try { + renderer.setMode(RendererMode.Fixed); + centralizeRenderer(); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonZoomNormalActionPerformed + + private void onChangeColormap(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onChangeColormap + try { + if ((camera != null) && (camera instanceof ColormapSource) && !updatingColormap) { + ColormapSource source = (ColormapSource) camera; + Color colorReticule = new Color(16, 16, 16); + Color colorMarker = new Color(128, 128, 128); + Colormap colormap = (Colormap) comboColormap.getSelectedItem(); + source.getConfig().colormap = (colormap == null) ? Colormap.Flame : colormap; + switch (source.getConfig().colormap) { + case Grayscale: + case Inverted: + case Red: + case Green: + case Blue: + colorReticule = new Color(0, 192, 0); + colorMarker = new Color(64, 255, 64); + break; + case Flame: + colorReticule = new Color(0, 192, 0); + colorMarker = new Color(64, 255, 64); + break; + } + + renderer.setPenReticle(new Pen(colorReticule)); + renderer.setPenProfile(new Pen(colorReticule, 0)); + renderer.setPenMarker(new Pen(colorMarker, 2)); + renderer.setShowReticle(false); + checkReticle(); + source.getConfig().colormapAutomatic = buttonAutomatic.isSelected(); + source.getConfig().colormapMin = buttonFullRange.isSelected() ? Double.NaN : (Integer) spinnerMin.getValue(); + source.getConfig().colormapMax = buttonFullRange.isSelected() ? Double.NaN : (Integer) spinnerMax.getValue(); + try { + source.getConfig().save(); + } catch (Exception ex) { + logger.log(Level.WARNING, null, ex); + } + source.refresh(); + if (buttonPause.isSelected()) { + updatePause(); + } + updateColormap(); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_onChangeColormap + + private void onChangeColormapRange(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_onChangeColormapRange + onChangeColormap(null); + }//GEN-LAST:event_onChangeColormapRange + + private void buttonZoom025ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoom025ActionPerformed + renderer.setZoom(0.25); + renderer.setMode(RendererMode.Zoom); + centralizeRenderer(); + }//GEN-LAST:event_buttonZoom025ActionPerformed + + private void buttonZoom05ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoom05ActionPerformed + renderer.setZoom(0.5); + renderer.setMode(RendererMode.Zoom); + centralizeRenderer(); + }//GEN-LAST:event_buttonZoom05ActionPerformed + + private void comboScreenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboScreenActionPerformed + + comboScreen.setEnabled(false); + new Thread(new Runnable() { + @Override + public void run() { + ChannelInteger setpoint = null; + try { + int index = comboScreen.getSelectedIndex(); + if (index >= 0) { + if (cameraName.contains("DSRM")) { + setpoint = new ChannelInteger(null, cameraName + ":POSITION_SP"); + } else { + setpoint = new ChannelInteger(null, cameraName + ":SET_SCREEN1_POS"); + } + setpoint.initialize(); + Integer readback = setpoint.read(); + if ((readback == null) || (setpoint.read() != index)) { + setpoint.write(index); + } + screen.read(); + } + } catch (Exception ex) { + showException(ex); + } finally { + comboScreen.setEnabled(true); + if (setpoint != null) { + setpoint.close(); + } + } + } + }).start(); + }//GEN-LAST:event_comboScreenActionPerformed + + private void comboFilterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboFilterActionPerformed + try { + String setpoint = (String) comboFilter.getSelectedItem(); + if (setpoint != null) { + if (!setpoint.equals(filter.read())) { + filter.write(setpoint); + } + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_comboFilterActionPerformed + + private void checkHistogramActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkHistogramActionPerformed + try { + setHistogramVisible(checkHistogram.isSelected()); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_checkHistogramActionPerformed + + private void buttonZoom2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoom2ActionPerformed + renderer.setZoom(2.0); + renderer.setMode(RendererMode.Zoom); + centralizeRenderer(); + }//GEN-LAST:event_buttonZoom2ActionPerformed + + private void spinnerThresholdonChange(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerThresholdonChange + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + server.setThreshold((Double) spinnerThreshold.getValue()); + } + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + } + } + }//GEN-LAST:event_spinnerThresholdonChange + + private void checkBackgroundActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkBackgroundActionPerformed + if (server != null) { + if (!updatingServerControls) { + try { + if (server.isStarted()) { + spinnerBackground.setVisible(checkBackground.isSelected()); + Object bg_mode = checkBackground.isSelected() ? String.valueOf(spinnerBackground.getValue()) : false; + server.setBackgroundSubtraction(bg_mode.equals("normal") ? true : bg_mode); + } + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + updatingServerControls = true; + checkBackground.setSelected(false); + updatingServerControls = false; + + } + } + } else { + camera.setBackgroundEnabled(checkBackground.isSelected()); + } + }//GEN-LAST:event_checkBackgroundActionPerformed + + private void checkThresholdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkThresholdActionPerformed + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + spinnerThreshold.setVisible(checkThreshold.isSelected()); + server.setThreshold(checkThreshold.isSelected() ? (Double) spinnerThreshold.getValue() : null); + } + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + } + } + }//GEN-LAST:event_checkThresholdActionPerformed + + private void checkGoodRegionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkGoodRegionActionPerformed + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + goodRegion = checkGoodRegion.isSelected(); + setGoodRegionOptionsVisible(goodRegion); + if (goodRegion) { + server.setGoodRegion(((Number) spinnerGrThreshold.getValue()).doubleValue(), ((Number) spinnerGrScale.getValue()).doubleValue()); + } else { + server.setGoodRegion(null); + } + } + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + } + } + }//GEN-LAST:event_checkGoodRegionActionPerformed + + private void spinnerGrThresholdonChange(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerGrThresholdonChange + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + server.setGoodRegion((Double) spinnerGrThreshold.getValue(), (Double) spinnerGrScale.getValue()); + } + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + } + } + }//GEN-LAST:event_spinnerGrThresholdonChange + + private void btFixColormapRangeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btFixColormapRangeActionPerformed + try { + updatingColormap = true; + ArrayProperties properties = currentFrame.data.getProperties(); + spinnerMax.setValue(properties.max.intValue()); + spinnerMin.setValue(properties.min.intValue()); + buttonManual.setSelected(true); + } catch (Exception ex) { + showException(ex); + } finally { + updatingColormap = false; + onChangeColormap(null); + } + }//GEN-LAST:event_btFixColormapRangeActionPerformed + + private void checkSlicingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkSlicingActionPerformed + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + slicing = checkSlicing.isSelected(); + setSlicingOptionsVisible(slicing); + if (slicing) { + server.setSlicing((Integer) spinnerSlNumber.getValue(), (Double) spinnerSlScale.getValue(), spinnerSlOrientation.getValue().toString()); + } else { + server.setSlicing(null); + } + } + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + } + } + }//GEN-LAST:event_checkSlicingActionPerformed + + private void spinnerSlicingChange(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerSlicingChange + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + server.setSlicing((Integer) spinnerSlNumber.getValue(), (Double) spinnerSlScale.getValue(), spinnerSlOrientation.getValue().toString()); + } + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + } + } + }//GEN-LAST:event_spinnerSlicingChange + + private void buttonReticleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonReticleActionPerformed + try { + checkReticle(); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonReticleActionPerformed + + private void buttonFitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonFitActionPerformed + try { + showFit = buttonFit.isSelected(); + if (showFit) { + renderer.setProfile(Renderer.Profile.None); + } else { + renderer.removeOverlays(fitOv); + fitOv = null; + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonFitActionPerformed + + private void buttonProfileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonProfileActionPerformed + try { + showProfile = buttonProfile.isSelected(); + if (showProfile) { + renderer.setProfile(Renderer.Profile.None); + } else { + renderer.removeOverlays(profileOv); + profileOv = null; + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonProfileActionPerformed + + private void buttonMarkerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMarkerActionPerformed + try { + checkMarker(null); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonMarkerActionPerformed + + private void buttonPauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPauseActionPerformed + try { + if (!updatingButtons) { + setPaused(buttonPause.isSelected()); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonPauseActionPerformed + + private void buttonGrabBackgroundActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonGrabBackgroundActionPerformed + try { + if (camera != null) { + boolean laserOn1 = getLaserState(1); + boolean laserOn2 = getLaserState(2); + OptionResult ret = null; + if (laserOn1 || laserOn2) { + if (laserOn1){ + ret = SwingUtils.showOption(getTopLevel(), "Capture Background", "Do you want to put Bunch 1 laser on delay for capturing background?", OptionType.YesNoCancel); + if (ret == OptionResult.No) { + laserOn1 = false; + } + if (ret == OptionResult.Cancel) { + return; + } + } + if (laserOn2){ + ret = SwingUtils.showOption(getTopLevel(), "Capture Background", "Do you want to put Bunch 2 laser on delay for capturing background?", OptionType.YesNoCancel); + if (ret == OptionResult.No) { + laserOn2= false; + } + } + } else { + ret = SwingUtils.showOption(getTopLevel(), "Capture Background", "Do you want to capture background now?", OptionType.OkCancel); + } + + if (ret == OptionResult.Cancel) { + return; + } + + if (laserOn1) { + setLaserState(1,false); + } + if (laserOn2) { + setLaserState(2,false); + } + try { + System.out.println("Grabbing background for: " + cameraAlias); + if (server != null) { + server.captureBackground(5); + } else { + camera.captureBackground(5, 0); + } + } finally { + if (laserOn1) { + setLaserState(1,true); + } + if (laserOn2) { + setLaserState(2,true); + } + } + SwingUtils.showMessage(getTopLevel(), "Success", "Success capturing background", 5000); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonGrabBackgroundActionPerformed + + private void buttonSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveActionPerformed + try { + saveSnapshot(); + } catch (Exception ex) { + logger.log(Level.WARNING, null, ex); + showException(ex); + } + }//GEN-LAST:event_buttonSaveActionPerformed + + private void buttonStreamDataActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStreamDataActionPerformed + try { + streamPanel = showDevicePanel(server.getStream()); + ((JDialog)streamPanel.getWindow()).setTitle("Stream Data"); + streamPanel.setReadOnly(true); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonStreamDataActionPerformed + + private void buttonSidePanelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSidePanelActionPerformed + sidePanel.setVisible(buttonSidePanel.isSelected()); + }//GEN-LAST:event_buttonSidePanelActionPerformed + + private void comboTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboTypeActionPerformed + try { + if (!updatingCameraSelection) { + updateCameraList(); + if ((cameraAlias != null) && (!cameraAlias.equals(comboCameras.getSelectedItem()))) { + setCamera(null); + } + } + + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + updateButtons(); + } + }//GEN-LAST:event_comboTypeActionPerformed + + private void comboCamerasActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboCamerasActionPerformed + try { + if (!updatingCameraSelection) { + if (!comboCameras.isEnabled()) { + throw new Exception("Invalid state"); + } + comboCameras.setEnabled(false); + comboType.setEnabled(false); + final String cameraName = (String) comboCameras.getSelectedItem(); + new Thread(new Runnable() { + @Override + public void run() { + if (requestCameraListUpdate) { + requestCameraListUpdate = false; + try { + updateCameraList(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + try { + setCamera(cameraName.trim().isEmpty() ? null : cameraName); + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + updateButtons(); + comboCameras.setEnabled(true); + comboType.setEnabled(true); + } + } + }).start(); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_comboCamerasActionPerformed + + private void buttonTitleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonTitleActionPerformed + try { + manageTitleOverlay(); + } catch (Exception ex) { + showException(ex); + } finally { + } + }//GEN-LAST:event_buttonTitleActionPerformed + + private void buttonScaleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonScaleActionPerformed + try { + renderer.setShowColormapScale(buttonScale.isSelected()); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonScaleActionPerformed + + private void checkRotationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkRotationActionPerformed + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + boolean rotation = checkRotation.isSelected(); + setRotationOptionsVisible(rotation); + if (rotation) { + spinnerRotationAngleStateChanged(null); + } else { + server.setRotation(null); + } + } + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + } + } + }//GEN-LAST:event_checkRotationActionPerformed + + private void spinnerRotationAngleStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerRotationAngleStateChanged + try { + String mode = String.valueOf(spinnerRotationMode.getValue()); + server.setRotation(((Number) spinnerRotationAngle.getValue()).doubleValue(), + ((Number) spinnerRotationOrder.getValue()).intValue(), + mode.equals("constant") ? String.valueOf(spinnerRotationConstant.getValue()): mode); + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + } + }//GEN-LAST:event_spinnerRotationAngleStateChanged + + private void checkAveragingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkAveragingActionPerformed + if (!updatingServerControls) { + try { + if ((server != null) && (server.isStarted())) { + setAveragingOptionsVisible(checkAveraging.isSelected()); + Integer av = spinnerAvMode.getValue().equals("window") ? - (Integer)spinnerAvFrames.getValue() : (Integer)spinnerAvFrames.getValue(); + setInstanceConfigValue("averaging", checkAveraging.isSelected() ? av : null); + } + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + } + } + }//GEN-LAST:event_checkAveragingActionPerformed + + private void spinnerAvModeonChange(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerAvModeonChange + checkAveragingActionPerformed(null); + }//GEN-LAST:event_spinnerAvModeonChange + + private void spinnerAvFramesStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerAvFramesStateChanged + checkAveragingActionPerformed(null); + }//GEN-LAST:event_spinnerAvFramesStateChanged + + private void spinnerBackgroundStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerBackgroundStateChanged + if (!updatingServerControls) { + try { + Object bg_mode = String.valueOf(spinnerBackground.getValue()); + server.setBackgroundSubtraction((bg_mode=="normal") ? true : bg_mode); + } catch (Exception ex) { + showException(ex); + updatePipelineControls(); + } + } + }//GEN-LAST:event_spinnerBackgroundStateChanged + + private void buttonPulse1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPulse1ActionPerformed + try { + if ((server != null) && (server.isStarted())) { + server.setInstanceConfigValue("pulse",1); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonPulse1ActionPerformed + + private void buttonPulse2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPulse2ActionPerformed + try { + if ((server != null) && (server.isStarted())) { + server.setInstanceConfigValue("pulse",2); + } + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonPulse2ActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btFixColormapRange; + private javax.swing.JRadioButton buttonAutomatic; + private javax.swing.JToggleButton buttonFit; + private javax.swing.JRadioButton buttonFullRange; + private javax.swing.JButton buttonGrabBackground; + private javax.swing.ButtonGroup buttonGroup1; + private javax.swing.ButtonGroup buttonGroup2; + private javax.swing.ButtonGroup buttonGroup3; + private javax.swing.ButtonGroup buttonGroup4; + private javax.swing.JRadioButton buttonManual; + private javax.swing.JToggleButton buttonMarker; + private javax.swing.JToggleButton buttonPause; + private javax.swing.JToggleButton buttonProfile; + private javax.swing.JButton buttonPulse1; + private javax.swing.JButton buttonPulse2; + private javax.swing.JToggleButton buttonReticle; + private javax.swing.JToggleButton buttonSave; + private javax.swing.JToggleButton buttonScale; + private javax.swing.JToggleButton buttonSidePanel; + private javax.swing.JButton buttonStreamData; + private javax.swing.JToggleButton buttonTitle; + private javax.swing.JRadioButton buttonZoom025; + private javax.swing.JRadioButton buttonZoom05; + private javax.swing.JRadioButton buttonZoom2; + private javax.swing.JRadioButton buttonZoomFit; + private javax.swing.JRadioButton buttonZoomNormal; + private javax.swing.JRadioButton buttonZoomStretch; + private javax.swing.JCheckBox checkAveraging; + private javax.swing.JCheckBox checkBackground; + private javax.swing.JCheckBox checkGoodRegion; + private javax.swing.JCheckBox checkHistogram; + private javax.swing.JCheckBox checkRotation; + private javax.swing.JCheckBox checkSlicing; + private javax.swing.JCheckBox checkThreshold; + private javax.swing.JComboBox comboCameras; + private javax.swing.JComboBox comboColormap; + private javax.swing.JComboBox comboFilter; + private javax.swing.JComboBox comboScreen; + private javax.swing.JComboBox comboType; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JProgressBar jProgressBar1; + private javax.swing.JToolBar.Separator jSeparator6; + private javax.swing.JLabel labelAngle; + private javax.swing.JLabel labelAvFrames; + private javax.swing.JLabel labelAvMode; + private javax.swing.JLabel labelConstant; + private javax.swing.JLabel labelGrScale; + private javax.swing.JLabel labelGrThreshold; + private javax.swing.JLabel labelMax; + private javax.swing.JLabel labelMin; + private javax.swing.JLabel labelMode; + private javax.swing.JLabel labelOrder; + private javax.swing.JLabel labelSlNumber; + private javax.swing.JLabel labelSlOrientation; + private javax.swing.JLabel labelSlScale; + private javax.swing.JLabel labelType; + private javax.swing.JPanel panelCameraSelection; + private javax.swing.JPanel panelColormap; + private javax.swing.JPanel panelFilter; + private javax.swing.JPanel panelPipeline; + private javax.swing.JPanel panelPulse; + private javax.swing.JPanel panelScreen; + private javax.swing.JPanel panelSlicing; + private javax.swing.JPanel panelZoom; + private ch.psi.pshell.swing.ValueSelection pauseSelection; + private ch.psi.pshell.imaging.Renderer renderer; + private javax.swing.JPanel sidePanel; + private javax.swing.JSpinner spinnerAvFrames; + private javax.swing.JSpinner spinnerAvMode; + private javax.swing.JSpinner spinnerBackground; + private javax.swing.JSpinner spinnerGrScale; + private javax.swing.JSpinner spinnerGrThreshold; + private javax.swing.JSpinner spinnerMax; + private javax.swing.JSpinner spinnerMin; + private javax.swing.JSpinner spinnerRotationAngle; + private javax.swing.JSpinner spinnerRotationConstant; + private javax.swing.JSpinner spinnerRotationMode; + private javax.swing.JSpinner spinnerRotationOrder; + private javax.swing.JSpinner spinnerSlNumber; + private javax.swing.JSpinner spinnerSlOrientation; + private javax.swing.JSpinner spinnerSlScale; + private javax.swing.JSpinner spinnerThreshold; + private javax.swing.JTextField textPulse; + private javax.swing.JToolBar toolBar; + private javax.swing.JPanel topPanel; + private ch.psi.pshell.swing.DeviceValuePanel valueFilter; + private ch.psi.pshell.swing.DeviceValuePanel valueScreen; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/ScreenPanel9.form b/plugins/ScreenPanel9.form index 0f11c92..5aba95b 100644 --- a/plugins/ScreenPanel9.form +++ b/plugins/ScreenPanel9.form @@ -1177,7 +1177,6 @@ - diff --git a/plugins/ScreenPanel9.java b/plugins/ScreenPanel9.java index cf7a6e2..0a37a39 100644 --- a/plugins/ScreenPanel9.java +++ b/plugins/ScreenPanel9.java @@ -1320,7 +1320,7 @@ public class ScreenPanel9 extends Panel { updatePipelineControls(); if (renderer.getDevice() == null) { //renderer.setZoom(1.0); - //renderer.setMode(RendererMode.Zoom); + //renderer.setMode(RenderegetDisplayNamerMode.Zoom); errorOverlay = new Text(renderer.getPenErrorText(), ex.toString(), new Font("Verdana", Font.PLAIN, 12), new Point(20, 20)); errorOverlay.setFixed(true); errorOverlay.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_LEFT); @@ -2832,13 +2832,18 @@ public class ScreenPanel9 extends Panel { dm.setItem(pathTimestampStr, Chrono.getTimeStr(streamValue.getTimestamp(), "YYYY-MM-dd HH:mm:ss.SSS"), index); for (String id : streamValue.getIdentifiers()) { - Object val = streamValue.getValue(id); - if (id.equals("image")) { - } else if (id.equals("processing_parameters")) { - } else if (val.getClass().isArray()) { - dm.setItem(pathRoot + id, val, index); - } else { - dm.setItem(pathRoot + id, val, index); + try{ + Object val = streamValue.getValue(id); + if (id.equals("image")) { + } else if (id.equals("processing_parameters")) { + } else if (val.getClass().isArray()) { + dm.setItem(pathRoot + id, val, index); + } else { + dm.setItem(pathRoot + id, val, index); + } + } catch (Exception ex){ + logger.log(Level.WARNING, null, ex); + System.out.println("Error saving " + id + " index " + index + ": " + ex.getMessage()); } } } @@ -2998,7 +3003,7 @@ public class ScreenPanel9 extends Panel { Frame frame = getCurrentFrame(); int[] sel_rows = (dataTable == null) ? null : dataTable.getSelectedRows(); int[] sel_cols = (dataTable == null) ? null : dataTable.getSelectedColumns(); - List ids = (value == null) ? new ArrayList<>() : new ArrayList(value.getIdentifiers()); + List ids = (value == null) ? new ArrayList<>() : value.getIdentifiers();//### TODO if (ids.size() + 4 != dataTableModel.getRowCount()) { dataTableModel.setNumRows(0); try { diff --git a/plugins/ShiftsIO.java b/plugins/ShiftsIO.java new file mode 100644 index 0000000..9c3daff --- /dev/null +++ b/plugins/ShiftsIO.java @@ -0,0 +1,109 @@ +import ij.io.OpenDialog; +import ij.io.SaveDialog; +import java.util.ArrayList; +import java.io.IOException; +import java.io.File; +import jmatio.types.*; +import jmatio.io.*; +import ij.gui.GenericDialog; +import ij.IJ; +import ij.Prefs; + +public class ShiftsIO { + + public ShiftsIO () {} + + public double[][] load(String filename, String varname) { + if (filename==null){ + String analysis_dir = Prefs.get("peem.analysis_dir", ""); + OpenDialog od = new OpenDialog("Open_shifts .mat file:", analysis_dir, "shifts.mat"); + String dir = od.getDirectory(); + if (null == dir) return null; // dialog was canceled + if (!dir.endsWith(File.separator)) dir += File.separator; + filename = dir + od.getFileName(); + Prefs.set("peem.analysis_dir", dir); + } + return low_load(filename, varname); + } + + private double[][] low_load(String filename, String varname) { + MatFileReader mfr = null; + try { + mfr = new MatFileReader(filename); + } catch (IOException e) { + System.err.println("Caught IOException: " + + e.getMessage()); + } + + if (mfr != null) { + MLDouble array = (MLDouble)mfr.getMLArray(varname); + if (array != null){ + return array.getArray(); + } else { + return null; + } + } else { + return null; + } + } + + public void save(String filename, double[][] shifts, String varname) { + boolean update = false; + if (filename==null){ + String analysis_dir = Prefs.get("peem.analysis_dir", ""); + SaveDialog sd = new SaveDialog("Save_shifts .mat file:", analysis_dir, "shifts.mat", ".mat"); + String dir = sd.getDirectory(); + String fname = sd.getFileName(); + if (null == fname) return; // user canceled dialog + if (!dir.endsWith(File.separator)) dir += File.separator; + Prefs.set("peem.analysis_dir", dir); + + if ((new File(dir + fname)).exists()) { // if file exist, overwrite or update shifts ? + GenericDialog gd = new GenericDialog("Update"); + String[] options = {"overwrite","update"}; + gd.addChoice("Mode of operation with existing file. You want to: ", options, options[0]); + gd.showDialog(); + if (gd.wasCanceled()) return; + if (gd.getNextChoiceIndex() == 1) update = true; + } + filename = dir + fname; + } + double[][] final_shifts; + if (update) { + double[][] prev_shifts = low_load(filename, "directshifts"); + if (prev_shifts == null) { + IJ.error("Can't read the direct shifts in this file"); + return; + } + + if (prev_shifts.length == shifts.length) { + for (int j = 0; j < prev_shifts.length; j++) { + prev_shifts[j][3] += shifts[j][3]; + prev_shifts[j][4] += shifts[j][4]; + } + } else if (shifts.length == 2) {// 2 shifts, like between two slices of different + // sequences + for (int j = 0; j < prev_shifts.length; j++) { + prev_shifts[j][3] += shifts[1][3]; + prev_shifts[j][4] += shifts[1][4]; + } + } else { + IJ.error("Old and new shifts have incompatible length !"); + return; + } + final_shifts = prev_shifts; + } else { + final_shifts = shifts; + } + + MLDouble mlDouble = new MLDouble(varname, final_shifts); + ArrayList list = new ArrayList(); + list.add(mlDouble); + try { + new MatFileWriter(filename, list); + } catch (IOException e) { + System.err.println("Caught IOException: " + + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/plugins/SpinnerLayoutTest.java b/plugins/SpinnerLayoutTest.java index 0eed633..8629629 100644 --- a/plugins/SpinnerLayoutTest.java +++ b/plugins/SpinnerLayoutTest.java @@ -19,7 +19,7 @@ public class SpinnerLayoutTest { super.setLayout(new SpinnerLayout()); } }; - spinner.set + JPanel p = new JPanel(new BorderLayout(5,5)); p.add(new JSpinner(m), BorderLayout.NORTH); p.add(spinner, BorderLayout.SOUTH); diff --git a/plugins/Standard.java b/plugins/Standard.java new file mode 100644 index 0000000..7ab542f --- /dev/null +++ b/plugins/Standard.java @@ -0,0 +1,6 @@ +public class Standard{ + + public void run() { + System.out.println("run"); + } +} diff --git a/plugins/TstProc.form b/plugins/TstProc.form new file mode 100644 index 0000000..ff9cfab --- /dev/null +++ b/plugins/TstProc.form @@ -0,0 +1,28 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/TstProc.java b/plugins/TstProc.java new file mode 100644 index 0000000..21112dc --- /dev/null +++ b/plugins/TstProc.java @@ -0,0 +1,195 @@ + +import ch.psi.pshell.core.JsonSerializer; +import ch.psi.pshell.ui.PanelProcessor; +import ch.psi.pshell.ui.Task; +import ch.psi.utils.State; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +/** + * Template for a processor plugin backed by json files. + */ +public class TstProc extends PanelProcessor { + + public static final String TYPE = "TstProc"; + public static final String FILE_EXTENSION = "json"; + public static final String HOME_PATH = "{home}/" + TYPE; + + File currentFile; + + public TstProc() { + initComponents(); + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + + } + + @Override + public void onStateChange(State state, State former) { + + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + @Override + public void onTaskFinished(Task task) { + } + + @Override + protected void onTimer() { + } + + @Override + protected void onLoaded() { + + } + + @Override + protected void onUnloaded() { + + } + + //Invoked by 'update()' to update components in the event thread + @Override + protected void doUpdate() { + } + + //Processor Configuration + @Override + public String getType() { + return TYPE; + } + + @Override + public String getDescription() { + return getType() + " definition file (*." + FILE_EXTENSION + ")"; + } + + @Override + public String getHomePath() { + return HOME_PATH; + } + + @Override + public String[] getExtensions() { + return new String[]{FILE_EXTENSION}; + } + + @Override + public String getFileName() { + return (currentFile == null) ? null : currentFile.toString(); + } + + @Override + public boolean createFilePanel() { + return true; + } + + @Override + public boolean createMenuNew() { + return true; + } + + @Override + public boolean canStep() { + return false; + } + + @Override + public boolean canPause() { + return false; + } + + @Override + public boolean isTabNameUpdated() { + return false; + } + + @Override + public void saveAs(String fileName) throws IOException { + currentFile = new File(fileName); + Map config = getConfig(); + String json = JsonSerializer.encode(config, true); + Files.write(currentFile.toPath(), json.getBytes()); + } + + @Override + public void open(String fileName) throws IOException { + clear(); + if (fileName != null) { + Path path = Paths.get(fileName); + String json = new String(Files.readAllBytes(path)); + Map config = (Map) JsonSerializer.decode(json, Map.class); + currentFile = path.toFile(); + setConfig(config); + } + } + + //Component update + public void clear() throws IOException { + currentFile=null; + //TODO + } + + Map getConfig() throws IOException { + //TODO + return new HashMap(); + } + + void setConfig(Map config) throws IOException { + //TODO + } + + //Workbench actions + @Override + public void plotDataFile(File file) throws Exception { + throw new Exception("Not implemented"); + } + + @Override + public void step() { + } + + @Override + public void pause() { + } + + @Override + public void abort() throws InterruptedException { + super.abort(); + } + + @Override + public void execute() throws Exception { + this.evalAsync("tscan(sin,10,0.2)"); + } + + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 449, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 137, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/resources/.DS_Store b/plugins/resources/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/plugins/resources/.DS_Store differ diff --git a/plugins/sc.form b/plugins/sc.form new file mode 100644 index 0000000..27e166f --- /dev/null +++ b/plugins/sc.form @@ -0,0 +1,41 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/sc.java b/plugins/sc.java new file mode 100644 index 0000000..832a911 --- /dev/null +++ b/plugins/sc.java @@ -0,0 +1,91 @@ + +import ch.psi.pshell.ui.App; +import ch.psi.pshell.ui.Panel; +import ch.psi.pshell.ui.StripChart; +import ch.psi.utils.State; +import ch.psi.utils.Sys; +import java.io.File; + +/** + * + */ +public class sc extends Panel { + StripChart stripChart; + public sc() { + initComponents(); + + /* + stripChart = new StripChart(this.getTopLevel(),false, null); + this.add(stripChart.getPlotPanel()); + try { + stripChart.open(new File("test.scd")); + stripChart.start(); + } catch (Exception ex) { showException(ex); + } + */ + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + plotPanel.removeAll(); + plotPanel.add(StripChart.getPlotPanel(new File("test.scd"))); + } + + @Override + public void onStateChange(State state, State former) { + + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + @Override + protected void onTimer() { + } + + @Override + protected void onLoaded() { + + } + + @Override + protected void onUnloaded() { + + } + + //Invoked by 'update()' to update components in the event thread + @Override + protected void doUpdate() { + } + + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + plotPanel = new javax.swing.JPanel(); + + plotPanel.setLayout(new java.awt.BorderLayout()); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(plotPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(plotPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 232, Short.MAX_VALUE) + .addGap(170, 170, 170)) + ); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel plotPanel; + // End of variables declaration//GEN-END:variables +} diff --git a/script/.DS_Store b/script/.DS_Store new file mode 100644 index 0000000..ed1d72b Binary files /dev/null and b/script/.DS_Store differ diff --git a/script/20150418_0012_Tb_hyst_plus.xml b/script/20150418_0012_Tb_hyst_plus.xml index af3cf69..344fdf0 100755 --- a/script/20150418_0012_Tb_hyst_plus.xml +++ b/script/20150418_0012_Tb_hyst_plus.xml @@ -9,8 +9,8 @@ - - + + 1236.9 1243.9 @@ -22,8 +22,8 @@ - - + + 0.0 @@ -33,23 +33,19 @@ - + - + return c/d - + - + return c/d diff --git a/script/20210614181250_XRD_XRF_otf_200ms_17200eV_XY_tisbe_Cu_HR2um.xml b/script/20210614181250_XRD_XRF_otf_200ms_17200eV_XY_tisbe_Cu_HR2um.xml new file mode 100644 index 0000000..641b014 --- /dev/null +++ b/script/20210614181250_XRD_XRF_otf_200ms_17200eV_XY_tisbe_Cu_HR2um.xml @@ -0,0 +1,171 @@ + + + + tisbe Cu sample, Norway + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -0.15 + 0.52 + 0.002 + 0.2 + 0.005 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -0.0 + 1.0 + 0.002 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/script/52_ParametersAndReturn.py b/script/52_ParametersAndReturn.py new file mode 100644 index 0000000..65145cb --- /dev/null +++ b/script/52_ParametersAndReturn.py @@ -0,0 +1,23 @@ +################################################################################################### +# Setting script parameters and return value +################################################################################################### + + +#Providing a map of global variables +#run ("52_ParametersAndReturn", {"start":10.0, "end":50.0, "step":40}) + +#Providing the locals dictionary +# The parameters are not set as globals, and nor script definitions +#run ("52_ParametersAndReturn", locals={"start":10.0, "end":50.0, "step":40}) + +#Setting sys.argv: +#run ("52_ParametersAndReturn", [10.0, 50.0, 40]) + +#In this case the parameters would be parsed as: +#start = sys.argv[0] +#end = sys.argv[1] +#step = sys.argv[2] + + +ret = lscan(ao1, ai1, start, end, step, 0.1) +set_return(ret[ai1]) \ No newline at end of file diff --git a/script/Correlation/Correlation.py b/script/Correlation/Correlation.py index 7f872fe..b58e49b 100644 --- a/script/Correlation/Correlation.py +++ b/script/Correlation/Correlation.py @@ -2,7 +2,7 @@ import math import sys, traceback from mathutils import fit_polynomial, PolynomialFunction from plotutils import plot_line, plot_function -from ch.psi.pshell.swing.Shell import STDOUT_COLOR +from ch.psi.pshell.swing.Shell import getColorStdout import org.apache.commons.math3.stat.correlation.PearsonsCorrelation as PearsonsCorrelation start_task("outupdate", 0.0, 0.0) @@ -146,7 +146,7 @@ try: if marker is not None: p.removeMarker(marker) marker = p.addMarker(x2+res, p.AxisId.X, s, p.getBackground()) - marker.setLabelPaint(STDOUT_COLOR) + marker.setLabelPaint(getColorStdout()) if linear_fit: #Calculate, print and plot linear fit pars_lin = (a0,a1) = fit_polynomial(ay, ax, 1) diff --git a/script/ManipulatorScan.py b/script/ManipulatorScan.py index 6bc3cff..d34e89b 100755 --- a/script/ManipulatorScan.py +++ b/script/ManipulatorScan.py @@ -8,8 +8,8 @@ STEPS (int or tuple) LATENCY (double) RELATIVE (BOOLEAN) """ - -if get_exec_pars().source == CommandSource.ui: + +if not get_exec_pars().args: MOTOR = motor SENSORS = (det.dataMatrix, scienta.spectrum, scienta.stats[0]) RANGE = (-5.0, 5.0) @@ -17,6 +17,6 @@ if get_exec_pars().source == CommandSource.ui: LATENCY = 0.0 RELATIVE = False - + lscan(MOTOR, SENSORS, RANGE[0], RANGE[1], STEPS, LATENCY, RELATIVE, before_read=trig_scienta) diff --git a/script/ManualScan.py b/script/ManualScan.py new file mode 100644 index 0000000..1f79be2 --- /dev/null +++ b/script/ManualScan.py @@ -0,0 +1,43 @@ +################################################################################################### +#Manual scan: Manually setting positioners and reading back sensors, but still using +#the standard data handling and plotting of built-in scans. +################################################################################################### + + +mu.setSpeed(10.0) + +pos1 = mu +pos2 = out +det1 =sin +det2 = arr +det3 = cm1#ri1 + + + + +MOTOR_RANGE = (0.0, 8.0) +OUTPUT_SETPOINTS = (1.0, 2.0, 3.0) +FIXED_X = True + +writables_names = [pos1.getName()] +readable_names = [det1.getName(), "arr[10]","cm1[3][2]"] +start = [ MOTOR_RANGE[0] if FIXED_X else -1, ] +stop = [ MOTOR_RANGE[1] if FIXED_X else -1] +steps = [int(MOTOR_RANGE[1]-MOTOR_RANGE[0])] + +scan = ManualScan(writables_names, readable_names ,start, stop, steps, monitors = [sin]) + + +#This option is to plot the foe each output value one 1D series, instead of all in a matrix plot +#set_exec_pars(line_plots = (det1, det2)) + +scan.start() +pos1.setSpeed(10.0) +for setpoint1 in frange(MOTOR_RANGE[0], MOTOR_RANGE[1], 1.0, True): + pos1.move(setpoint1) + for setpoint2 in OUTPUT_SETPOINTS: + pos2.write(setpoint2) + scan.append ([setpoint1], [pos1.read()], [det1.read(), det2.read(), cm1.read()]) + + +scan.end() diff --git a/script/Regine.py b/script/Regine.py index 0bc3e40..044fe80 100644 --- a/script/Regine.py +++ b/script/Regine.py @@ -86,7 +86,7 @@ if EXPOSURES: POSITIONERS = POSITIONERS + [exposure_index()] SENSORS = SENSORS + [exposure()] RANGE_E=[0, len(EXPOSURES)-1] - + #set_exec_pars(manual_range=RANGE_E, manual_range_y=RANGE_Y) CUSTOM_PLOT_TYPES[sin]=1 @@ -102,7 +102,7 @@ def gen(): xpos = CENTER_X + x_step*STEP_SIZE_X + (random.random()-0.5)*NOISE*2*STEP_SIZE_X range_y= range(STEPS_Y, -STEPS_Y-1, -1) if (ZIGZAG and(x_index%2 ==1)) else range(-STEPS_Y, STEPS_Y+1) for y_step in range_y: - ypos = CENTER_Y + y_step*STEP_SIZE_Y + (random.random()-0.5)*NOISE*2*STEP_SIZE_Y + ypos = CENTER_Y + y_step*STEP_SIZE_Y + (random.random()-0.5)*NOISE*2*STEP_SIZE_Y if EXPOSURES: range_e= range(len(EXPOSURES)-1,-1, -1) if (ZIGZAG and(y_index%2 ==1)) else range(len(EXPOSURES)) for e in range_e: @@ -116,8 +116,9 @@ def gen(): try: r = vscan(POSITIONERS, SENSORS , gen(), False,\ - SETTLING_TIME, relative=False, zigzag = ZIGZAG, \ - before_read=before_readout, after_read = after_read, \ + SETTLING_TIME, relative=False, zigzag = ZIGZAG, initial_move=False, \ + before_read=before_readout, after_read = after_readout, \ + manual_range=RANGE_X, manual_range_y=RANGE_Y, \ compression = COMPRESSION, enabled_plots=ENABLED_PLOTS, \ keep=False, check_positions=False, plot_types=CUSTOM_PLOT_TYPES) set_return(r) diff --git a/script/ShellCommand.py b/script/ShellCommand.py new file mode 100644 index 0000000..d92ae51 --- /dev/null +++ b/script/ShellCommand.py @@ -0,0 +1,73 @@ +#CAS.setServerPort(5064) +import java.util.function.BiFunction as BiFunction + +class ShellCommand(RegisterBase, RegisterArray): + def __init__(self, name): + RegisterBase.__init__(self, name) + self.val = "" + self.debug=False + self.max_size = 10000 + + def getSize(self): + return 1 + + def doRead(self): + if self.debug: + print "READ: ", self.val + return self.val + + def doWrite(self, val): + self.val = "RUNNING" + + + + + + try: + if self.debug: + print "WRITE: ", val + cmd = str(val[0]) + + class eval_callback(BiFunction): + def apply(self_callback, ret, ex): + try: + if ex is not None: + err=ex.message + if "Exception:" in err: + err = err[err.index("Exception:")+10:].strip() + self.val = "ERR:" + err + else: + self.val = "RET:" + str(ret) + self.val = self.val[0:self.max_size] + except: + err=str(sys.exc_info()[1]) + self.val = "EXC: " + err + if self.debug: + print self.val + + #self.val = cmd + get_context().evalLineBackgroundAsync(cmd).handle(eval_callback()) + except: + err=str(sys.exc_info()[1]) + if "Exception:" in err: + err = err[err.index("Exception:")+10:].strip() + self.val = "EXC: " + err + self.val = self.val[0:self.max_size] + if self.debug: + print self.val + + + +add_device(ShellCommand("sc"), True) +cas = CAS("TESTCAS:sc", sc, 'string') + + + +#print caget("TESTCAS:sc","s") +#/Users/gobbo_a/anaconda3/envs/epics/epics/bin/darwin-x86 + + + + + + diff --git a/script/StateCAS.py b/script/StateCAS.py new file mode 100644 index 0000000..e776b9d --- /dev/null +++ b/script/StateCAS.py @@ -0,0 +1,50 @@ +class EpicsServerState(ReadonlyAsyncRegisterBase): + def __init__(self, name, channel, as_string=True): + RegisterBase.__init__(self, name) + self.channel=channel + self.as_string=as_string + self.val = "Unknown" + self.cas = None + self.state_change_listener=None + + def doInitialize(self): + super(EpicsServerState, self).doInitialize() + if self.as_string: + self.cas = CAS(self.channel, self, 'string') + else: + self.cas = CAS(self.channel, self, 'byte') + if self.state_change_listener is None: + class StateChangeListener(ContextListener): + def onContextStateChanged(_self, state, former): + self.set(state) + self.state_change_listener = StateChangeListener() + get_context().addListener(self.state_change_listener) + + def getSize(self): + if self.as_string: + return 1 + else: + return 100 + + def doClose(self): + if self.state_change_listener: + get_context().removeListener(self.state_change_listener) + if self.cas: + self.cas.close() + self.cas = None + super(EpicsServerState, self).doClose() + + def set(self, value): + if self.as_string: + self.onReadout(str(value)) + else: + self.onReadout(string_to_list(str(value))) + + + + + +if "server_state_channel" in globals(): + server_state_channel.close() +server_state_channel = EpicsServerState("server_state_channel", "PSHELL_OP:STATE", False) +server_state_channel.initialize() \ No newline at end of file diff --git a/script/Test.xml b/script/Test.xml index 299bae3..e69de29 100644 --- a/script/Test.xml +++ b/script/Test.xml @@ -1,41 +0,0 @@ - - - - - - - - - - - 0.0 - 10.0 - 1.0 - - - - - - - - - - - - diff --git a/script/Test3.xml b/script/Test3.xml new file mode 100644 index 0000000..dab51b7 --- /dev/null +++ b/script/Test3.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + 0.0 + 10.0 + 1.0 + + + + + + + + + + + + + + + + diff --git a/script/Test4.xml b/script/Test4.xml new file mode 100644 index 0000000..0935959 --- /dev/null +++ b/script/Test4.xml @@ -0,0 +1,24 @@ + + + + + + + + + + 0.0 + 10.0 + 1.0 + + + + + 1 + + + + + + + diff --git a/script/Test4b.xml b/script/Test4b.xml new file mode 100644 index 0000000..a8ca934 --- /dev/null +++ b/script/Test4b.xml @@ -0,0 +1,19 @@ + + + + + + + + + + 0.0 + 0.0 + 1.0 + NINT + + + + + + diff --git a/script/Test4c.xml b/script/Test4c.xml new file mode 100644 index 0000000..b1da0ed --- /dev/null +++ b/script/Test4c.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + var + + + + + + diff --git a/script/Test4e.xml b/script/Test4e.xml new file mode 100644 index 0000000..9c8534c --- /dev/null +++ b/script/Test4e.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + 0.0 + 0.0 + 1.0 + V + + + + + + + 1 + + + + + + + diff --git a/script/Test5.xml b/script/Test5.xml new file mode 100644 index 0000000..5dbb75c --- /dev/null +++ b/script/Test5.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/script/TriggerScan.py b/script/TriggerScan.py index b357a9b..094be76 100755 --- a/script/TriggerScan.py +++ b/script/TriggerScan.py @@ -6,18 +6,25 @@ class Trigger(ReadonlyRegisterBase): trigger = Trigger() trigger.initialize() -sca = "asd" +scan = None def scan(): - global sca - sca = mscan(trigger, [sc1, sin.cache], 20) + global scan + scan = mscan(trigger, [out, sin.cache]) + print scan -scan_task = fork(scan) +scan_task = fork(scan)[0] time.sleep(0.5) -for i in range(10): +for i in range(20): trigger.update() time.sleep(random.random()/5) -#ret = join(scan_task) +time.sleep(1.0) +ep=get_exec_pars() + +ep.currentScan.abort() +#scan_task.cancel(True) + +ret = join(scan_task) diff --git a/script/align/Demo2D.py b/script/align/Demo2D.py new file mode 100644 index 0000000..62d4e37 --- /dev/null +++ b/script/align/Demo2D.py @@ -0,0 +1,41 @@ +################################################################################################### +# Using bsearch(Binary Search) and hsearch(Hill Climbing Search) to find optimum +################################################################################################### + +class Sensor(ReadonlyRegisterBase): + def doRead(self): + return 1000.0 - (math.pow(motor.take()-0.5, 2) + math.pow(pe.take()+2, 2)) +add_device(Sensor("sensor"), True) + +range_x, step_x=1.0, 0.1 +range_y, step_y=10.0, 0.1 + +motor.speed=5.0 +motor.move(0.0) +pe.move(0.0) + +print "--------------- Full 2D Scan -----------------" +r = ascan([motor, pe], sensor, [-range_x,-range_y], [range_x,range_y], [step_x, step_x], relative=True, zigzag=True) +data = Convert.reshape(r[sensor], r.scan.numberOfSteps[0]+1, r.scan.numberOfSteps[1]+1) +data = [(data[i][::-1] if ((i%2)==1) else data[i]) for i in range(len(data))] +d=Data(to_array(data,'d')) +v,h=d.integrateVertically(), d.integrateHorizontally() +mv=fit(v)[1] +mh=fit(h)[1] +index = int(round(mh))*(r.scan.numberOfSteps[1]+1) + int(round(mv)) +max_pe, max_motor= r[pe][index], r[motor][index] +print "2s scan peak at motor=" , max_motor , " pe=", max_pe +motor.move(max_motor) +pe.move(max_pe) + +print "--------------- Binary Search -----------------" +motor.move(0.0);pe.move(0.0) +r = bsearch([motor, pe], sensor, [-range_x,-range_y], [range_x,range_y], [step_x/4, step_y/4], \ + relative=True, maximum=True, strategy = "Normal", restore_position=False ) +print "bsearch peak at position=", r.optimalPosition , " in ", len(r), "evaluations" + +motor.move(0.0);pe.move(0.0) +print "--------------- Hill Climbing Search -----------------" +r = hsearch([motor, pe], sensor, [-range_x,-range_y],[range_x,range_y], [step_x*2, step_y*2], \ + [step_x/4, step_y/4], relative=True, maximum=True, restore_position=False ) +print "hsearch peak at position=", r.optimalPosition, " in ", len(r), "evaluations" \ No newline at end of file diff --git a/script/align/SimpleDemo.py b/script/align/SimpleDemo.py new file mode 100644 index 0000000..19f96f4 --- /dev/null +++ b/script/align/SimpleDemo.py @@ -0,0 +1,33 @@ +################################################################################################### +# Simple alignment example +################################################################################################### + + +from mathutils import * +from plotutils import * + +scan_range = 2.0 +step_size = 0.1 + +r = lscan(motor,sinp,-scan_range,scan_range,[step_size,],relative=True) + +p=get_plots()[0] +p.setLegendVisible(True) +y = r[sinp] +x = r[motor] + +fit_pars = (offset, normalization, mean_val, sigma) = fit_gaussian_offset(y, x) +print fit_pars + +if (mean_val is not None): + gaussian = GaussianOffset(*fit_pars) + plot_function(p, gaussian, "Fit" , x) + +#Fitting error +if mean_val is None or mean_valx[-1]: + mean_val= x[y.index(max(y))] + print "Fitting error - using max value" + + +p.addMarker(mean_val, None, "Mean=" + str(round(mean_val,2)), Color.LIGHT_GRAY) +motor.move(mean_val) \ No newline at end of file diff --git a/script/bsread_camera.py b/script/bsread_camera.py index 21938f3..b6d7725 100644 --- a/script/bsread_camera.py +++ b/script/bsread_camera.py @@ -1,4 +1,4 @@ - +import java.lang.Short as Short import ch.psi.pshell.epics.CAS as CAS import ch.psi.pshell.device.Register.RegisterArray as RegisterArray import random @@ -12,6 +12,7 @@ EPICS_PV_SUFFIX_STATUS = ":INIT" EPICS_PV_SUFFIX_WIDTH = ":WIDTH" EPICS_PV_SUFFIX_HEIGHT = ":HEIGHT" EPICS_PV_SUFFIX_STREAM_ADDRESS = ":BSREADCONFIG" +EPICS_PV_SUFFIX_IMG = ":FPICTURE" class Scalar(RegisterBase): def __init__(self, name): @@ -29,6 +30,7 @@ add_device(Scalar("cam_width"), True) add_device(Scalar("cam_height"), True) add_device(Scalar("cam_add"), True) + cam_width.write(IMG_WIDTH) cam_height.write(IMG_HEIGHT) cam_init.write("INIT") @@ -42,6 +44,13 @@ cas3 = CAS(camera + EPICS_PV_SUFFIX_HEIGHT, cam_height, 'int') cas4 = CAS(camera + EPICS_PV_SUFFIX_STREAM_ADDRESS, cam_add, 'string') +class Img(ReadonlyRegisterBase, ReadonlyRegisterArray): + def doRead(self): + return Convert.toPrimitiveArray(Convert.flatten(cam_server.getArray()),Short) +add_device(Img("cam_img"), True) +cas5 = CAS(camera + EPICS_PV_SUFFIX_IMG, cam_img, 'double') + + print caget(camera + EPICS_PV_SUFFIX_STATUS) print caget(camera + EPICS_PV_SUFFIX_WIDTH) print caget(camera + EPICS_PV_SUFFIX_HEIGHT) diff --git a/script/calc.py b/script/calc.py index 0006d1e..ba18b58 100755 --- a/script/calc.py +++ b/script/calc.py @@ -1,3 +1,4 @@ def calc(a): return a*2 + \ No newline at end of file diff --git a/script/cpy/BugMonitor.py b/script/cpy/BugMonitor.py new file mode 100644 index 0000000..c169da5 --- /dev/null +++ b/script/cpy/BugMonitor.py @@ -0,0 +1,2 @@ +av = create_averager(sin, 5 , monitored=True) +tscan ([sin,av], 100, 0.1) \ No newline at end of file diff --git a/script/cpy/Device.py b/script/cpy/Device.py new file mode 100644 index 0000000..b80b573 --- /dev/null +++ b/script/cpy/Device.py @@ -0,0 +1,170 @@ +class GenericDevice(Nameable): + cls=[ "ch.psi.pshell.device.GenericDevice", \ + "ch.psi.utils.Observable", \ + "ch.psi.pshell.device.Timestamped", \ + "java.lang.AutoCloseable", \ + "ch.psi.utils.Configurable", \ + "ch.psi.pshell.device.Record" ] + + def __init__(self, name=None, cls=GenericDevice.cls): + Nameable.__init__(self, name, cls) + self.simulated=False + self.state=State.Ready + self.monitored=False + self.polling=None + self.cache=None + self.age=None + + + def addListener(self, listener): + pass + + def getListeners(self): + pass + + def removeListener(self, listener): + pass + + def removeAllListeners(self): + pass + + def getTimestamp(self): + return 0 + + def getTimestampNanos(self): + return 0 + + def getConfig(self): + return None + + def getState(self): + return State.Ready + + def waitState(self, state, timeout): + return + + def waitStateNot(self, state, timeout): + pass + + def initialize(self): + pass + + def isInitialized(self): + return True + + def waitInitialized(self, timeout): + pass + + def setSimulated(self): + self.simulated = True + + def isSimulated(self): + return self.simulated + + def isMonitored(self): + return self.monitored + + def setMonitored(self,monitored): + self.monitored=self.monitored + + def setPolling(self, interval): + self.polling=interval + + def getPolling(self): + return self.polling + + def isPollingBackground(self): + return self.polling and self.polling>0 + + def setAccessType(self, mode): + pass + + def getAccessType(self): + return None + + def take(self): + return self.cache + + def getAge(self): + return self.age + + def request(self): + self.update() + + def update(self): + pass + + def setWaitSleep(self, value): + pass + + def getWaitSleep(self): + return 5 + + def isPolled(self): + return self.getPolling() > 0 + + def takeAsNumber(self): + cache = take(); + try: + return float(cache) + except: + return None + + def close(self): + pass + +class Device(GenericDevice): + cls="ch.psi.pshell.device.Device" + + def __init__(self, name=None): + GenericDevice.__init__(self, name, [Device.cls] + GenericDevice.cls) + + def isReady(): + return getState()==State.Ready + + def waitReady(self, timeout): + return + + def waitValue(self, value, timeout): + return + + def waitValueNot(self, value, timeout): + return + + def waitValueChange(self,timeout): + return false + + def waitCacheChange(self,timeout): + return false + + def getComponents(self): + return None + + def getComponent(self, name): + return None + + def getChildren(self): + return None + + def getChild(self, name): + return None + + def getParent(self): + return None + + def setTriggers(self,triggers): + pass + + def getTriggers(self): + return None + + def takeTimestamped(self,): + return None + + def isChild(self, device): + return False + + + +dev= Device("test") +add_device(dev, True) \ No newline at end of file diff --git a/script/cpy/ManualScan.py b/script/cpy/ManualScan.py new file mode 100644 index 0000000..f253e46 --- /dev/null +++ b/script/cpy/ManualScan.py @@ -0,0 +1,43 @@ +################################################################################################### +#Manual scan: Manually setting positioners and reading back sensors, but still using +#the standard data handling and plotting of built-in scans. +################################################################################################### + + +mu.setSpeed(10.0) + +pos1 = mu +pos2 = out +det1 =rs1 +det2 = sin#rw1 +det3 = out#ri1 + + + + +MOTOR_RANGE = (0.0, 8.0) +OUTPUT_SETPOINTS = (1.0, 2.0, 3.0) +FIXED_X = True + +writables_names = [pos1.getName(), pos2.getName()] +readable_names = [det1.getName(), det2.getName()] +start = [ MOTOR_RANGE[0] if FIXED_X else -1, OUTPUT_SETPOINTS[0]] +stop = [ MOTOR_RANGE[1] if FIXED_X else -1, OUTPUT_SETPOINTS[-1]] +steps = [int(MOTOR_RANGE[1]-MOTOR_RANGE[0]), len(OUTPUT_SETPOINTS)-1] + +scan = ManualScan(writables_names, readable_names ,start, stop, steps, monitors = [sin]) + + +#This option is to plot the foe each output value one 1D series, instead of all in a matrix plot +set_exec_pars(line_plots = (det1, det2)) + +scan.start() +pos1.setSpeed(10.0) +for setpoint1 in frange(MOTOR_RANGE[0], MOTOR_RANGE[1], 1.0, True): + pos1.move(setpoint1) + for setpoint2 in OUTPUT_SETPOINTS: + pos2.write(setpoint2) + scan.append ([setpoint1, setpoint2], [pos1.read(), pos2.read()], [det1.read(), det2.read()]) + + +scan.end() diff --git a/script/cpy/Signal.py b/script/cpy/Signal.py new file mode 100644 index 0000000..0a3157b --- /dev/null +++ b/script/cpy/Signal.py @@ -0,0 +1,14 @@ +import signal + +def is_main_thread(): + try: + # Backup the current signal handler + back_up = signal.signal(signal.SIGINT, signal.SIG_DFL) + except ValueError: + # Only Main Thread can handle signals + return False + # Restore signal handler + signal.signal(signal.SIGINT, back_up) + return True +print (is_main_thread()) + \ No newline at end of file diff --git a/script/cpy/TestBlueskyPause.py b/script/cpy/TestBlueskyPause.py new file mode 100644 index 0000000..7e99f30 --- /dev/null +++ b/script/cpy/TestBlueskyPause.py @@ -0,0 +1,48 @@ +from functools import partial +import threading +import traceback +import socket + +CTRL_CMD_PORT = 9587 +msg=None +if ("ctrl_cmd_socket" in globals()) and (ctrl_cmd_socket is not None): + ctrl_cmd_socket.close() + ctrl_cmd_task_thread.join(5.0) + if ctrl_cmd_task_thread.is_alive(): + raise Exception("Cannot stop ctrl_cmd_task_thread") + +def on_ctrl_cmd(cmd): + global RE + print ("Control command: ", cmd) + if cmd=="abort": + if "RE" in globals(): + if RE.state not in ['idle','paused', 'pausing']: + print ("Run Engine pause request") + RE.request_pause() + +def ctlm_cmd_task(port,parent_thread, rc): + try: + global ctrl_cmd_socket + print ("Starting control command task") + quit=False + with socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) as ctrl_cmd_socket: + ctrl_cmd_socket.bind(("127.0.0.1", port)) + ctrl_cmd_socket.settimeout(2.0) + while(quit==False) and (run_count==rc) and parent_thread.is_alive() and not ctrl_cmd_socket._closed: + try: + msg,add = ctrl_cmd_socket.recvfrom(100) + except socket.timeout: + continue + cmd =msg.decode('UTF-8') + on_ctrl_cmd(cmd) + if cmd=="exit": + quit=True + ctrl_cmd_socket.sendto("ack".encode('UTF-8'), add) + finally: + print("Quitting control command task") + +ctrl_cmd_task_thread = threading.Thread(target=partial(ctlm_cmd_task, CTRL_CMD_PORT, threading.currentThread(), run_count)) +ctrl_cmd_task_thread.setDaemon(True) +ctrl_cmd_task_thread.start() + +#RE(rel_scan(dets, motor, -1, 1, 10)) \ No newline at end of file diff --git a/script/cpy/TestJProxy.py b/script/cpy/TestJProxy.py new file mode 100644 index 0000000..5f988f2 --- /dev/null +++ b/script/cpy/TestJProxy.py @@ -0,0 +1,75 @@ +from jep import jproxy +import random + + +class MyWritable(Writable): + def write(self, value): + print ("Write: ",value) + +class MyReadable(Readable): + def read(self): + return random.random() + +class MyReadableArray(ReadableArray): + def read(self): + ret = [] + for i in range (self.getSize()): + ret.append(random.random()) + return ret + + def getSize(self): + return 20 + +class MyReadableCalibratedArray(ReadableCalibratedArray): + def read(self): + return rw1.read() + + def getSize(self): + return rw1.getSize() + + def getCalibration(self): + return ArrayCalibration(5,1000) + +class MyReadableMatrix(ReadableMatrix): + def read(self): + ret = [] + for i in range (self.getHeight()): + ret.append([random.random()] * self.getWidth()) + return to_array(ret, 'd') + + def getWidth(self): + return 80 + + def getHeight(self): + return 40 + + +class MyReadableCalibratedMatrix(ReadableCalibratedMatrix): + def read(self): + return ri1.read() + + def getWidth(self): + return ri1.getWidth() + + def getHeight(self): + return ri1.getHeight() + + def getCalibration(self): + return MatrixCalibration(2,4,100,200) + + +#plot([1,2,3]) + +ws1 = MyWritable("ws1") +rs1 = MyReadable("rs1") +rw1 = MyReadableArray("rw1") +ri1 = MyReadableMatrix("ri1") +ac1 = MyReadableCalibratedArray("ac1") +mc1 = MyReadableCalibratedMatrix("mc1") + + + +t=lscan(ws1, (rs1, rw1, ri1, ac1, mc1), 0, 5, 5) + + + diff --git a/script/cpy/TestJProxy2.py b/script/cpy/TestJProxy2.py new file mode 100644 index 0000000..e071fc2 --- /dev/null +++ b/script/cpy/TestJProxy2.py @@ -0,0 +1,68 @@ +from jep import jproxy +import random + + +""" +class proxy(): + def __init__(self,cls): + self.cls=cls + def __call__(self, name): + return jproxy(self, self.cls) + +@proxy(['ch.psi.pshell.device.Readable']) +""" +class Readable(): + def __init__(self, name=None): + self.name=name + self.proxy=jproxy(self, ['ch.psi.pshell.device.Readable']) + + def __call__(self): + return self.read() + + def __getattribute__(self, name): + if name in ('proxy',): + return object.__getattribute__(self, name) + print(name) + return self.proxy.__getattribute__(name) + + def getName(self): + if self.name : + return self.name + + return str(self.__class__.__name__) + def read(self): + raise Exception ("Not implemented") + + + +class ReadableScalar(Readable): + def read(self): + ret =random.random() + print (ret) + return ret + +class ReadableWaveform(Readable): + + def __call__(self): + return self.read() + def getSize(self): + return 20 + def read(self): + ret = [] + for i in range (self.getSize()): + ret.append(random.random()) + return ret + def getName(self): + return "rw1" + + + +#rs1 = jproxy(ReadableScalar(), ['ch.psi.pshell.device.Readable']) +rs1 = ReadableScalar() +#rw1 = jproxy(ReadableWaveform(), ['ch.psi.pshell.device.Readable$ReadableArray']) +#ri1 = jproxy(ReadableImage(), ['ch.psi.pshell.device.Readable$ReadableMatrix']) +#rw1=ReadableWaveform() +rs1.read() +#rw1.read() +#rs1 = jproxy(rs1 , ['ch.psi.pshell.device.Readable'])# +#tscan([rs1],10,0.1, save=False) \ No newline at end of file diff --git a/script/cpy/TestJepError.py b/script/cpy/TestJepError.py new file mode 100644 index 0000000..f58f531 --- /dev/null +++ b/script/cpy/TestJepError.py @@ -0,0 +1,97 @@ +################################################################################################### +#Data Manipulation: Using the data access API to generate and retrieve data +################################################################################################### + + +#Creating a 1D dataset from an array +path="group/data1" +data1d = [1.0, 2.0, 3.0, 4.0, 5.0] +save_dataset(path, data1d) +#Reading ii back +read =load_data(path) +print (list(read)) +assert data1d==list(read) +plot(read) + +#Creating a 2D dataset from an array with some attributes +data2d = [ [1.0, 2.0, 3.0, 4.0, 5.0], [2.0, 3.0, 4.0, 5.0, 6.0, ], [3.0, 4.0, 5.0, 6.0, 7.0]] +path="group/data2" +save_dataset(path, data2d) +set_attribute(path, "AttrString", "Value") +set_attribute(path, "AttrInteger", 1) +set_attribute(path, "AttrDouble", 2.0) +set_attribute(path, "AttrBoolean", True) +#Reading it back +read =load_data(path) +print (list(read)) +plot(read) + +#Creating a 3D dataset from an array +data3d = [ [ [1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7]], [ [3,2,3,4,5], [4,3,4,5,6], [5,4,5,6,7]]] +path="group/data3" +save_dataset(path, data3d) +#Reading it back +read =load_data(path,0) +print (list(read)) +read =load_data(path,1) +print (list(read)) + +#Creating a INT dataset adding elements one by one +path = "group/data4" +create_dataset(path, 'i') +for i in range(10): + append_dataset(path,i) + + +#Creating a 2D data FLOAT dataset adding lines one by one +path = "group/data5" +create_dataset(path, 'd', False, (0,0)) +for row in data2d: + append_dataset(path, row) + + +#Creating a Table (compund type) +path = "group/data6" +names = ["a", "b", "c", "d"] +types = ["d", "d", "d", "[d"] +lenghts = [0,0,0,5] +table = [ [1,2,3,[0,1,2,3,4]], + [2,3,4,[3,4,5,6,7]], + [3,4,5,[6,7,8,9,4]] ] +create_table(path, names, types, lenghts) +for row in table: + append_table(path, row) +flush_data() +#Read it back +read =load_data(path) +print (read) + + +#Writing scalars (datasets with rank 0) +save_dataset("group/val1", 1) +save_dataset("group/val2", 3.14) +save_dataset("group/val3", "test") +print (load_data("group/val1")) +print (load_data("group/val2")) +print (load_data("group/val3")) + + + + + + +time.sleep(1.0) + + +code="""def is_java_instance(obj, cls): + print(1) +################################################################################################### +#Access to context singleton +################################################################################################### +def get_context(): + return core.Context.getInstance() +""" + +comp=compile(code, '', 'exec') + +set_return(2) \ No newline at end of file diff --git a/script/cpy/bluesky.py b/script/cpy/bluesky.py new file mode 100644 index 0000000..71443a9 --- /dev/null +++ b/script/cpy/bluesky.py @@ -0,0 +1,178 @@ +import signal +signal.signal = lambda *args: None +################################################################################################### +#import matplotlib +#matplotlib.use('Qt5Agg') +import traceback + + +from bluesky import RunEngine +from bluesky.callbacks.best_effort import BestEffortCallback +from bluesky.utils import install_kicker + +from bluesky.utils import ProgressBarManager +from ophyd.sim import det1, det2, det3, det4, det, motor, motor1, motor2, motor3,img, sig, direct_img, pseudo1x3 +from ophyd import Signal +from ophyd.signal import EpicsSignal +from bluesky.plans import count, scan, rel_scan, list_scan, grid_scan, list_grid_scan +from bluesky.simulators import summarize_plan +import bluesky.plan_stubs as bps +from bluesky.plan_stubs import mv +import bluesky.preprocessors as bpp +from bluesky.preprocessors import SupplementalData +import databroker +#import suitcase +#import suitcase.csv +#from databroker import Broker + + +RE = RunEngine({}) +bec = BestEffortCallback() +bec.disable_plots() +RE.subscribe(bec) +#db = Broker.named('temp') +#RE.subscribe(db.insert) +#RE.waiting_hook = ProgressBarManager() +dets = [det1, det2] + + +RE(count(dets, num=5)) +RE(scan(dets, motor, -1, 1, 10)) +dir (motor) + +vel=motor.velocity.get() +motor.velocity.set(vel+1) +RE(scan(dets, motor, -1, 1, 10)) +det.read() +det.get() +dets=[det] + +RE(rel_scan(dets, motor, -1, 1, 10)) + +points = [1, 1, 2, 3, 5, 8, 13] +RE(list_scan(dets, motor, points)) + +dets=[det4] +RE(scan(dets,motor1, -1.5, 1.5, motor2, -0.1, 0.1, 11)) +RE(list_scan(dets, motor1, [1, 1, 3, 5, 8], motor2, [25, 16, 9, 4, 1])) +RE(grid_scan(dets, motor1, -1.5, 1.5, 3, motor2, -0.1, 0.1, 5, motor3, 10, -10, 5)) + +RE(grid_scan(dets, motor1, -1.5, 1.5, 3, motor2, -0.1, 0.1, 5)) +RE(grid_scan(dets, motor1, -1.5, 1.5, 3, motor2, -0.1, 0.1, 5, motor3, 10, -10, 5)) + +RE(list_grid_scan(dets, motor1, [1, 1, 2, 3, 5], motor2, [25, 16, 9])) + + +db[-1].table() + + + +def coarse_and_fine(detectors, motor, start, stop): + yield from scan(detectors, motor, start, stop, 10) + yield from scan(detectors, motor, start, stop, 100) + RE(coarse_and_fine(dets, motor, -1, 1)) + +# Move motor1 to 1 and motor2 to 10, simultaneously. Wait for both to arrive. +RE(mv(motor1, 1, motor2, 10)) +print (motor1.get().readback, motor2.get().readback) + +# Move motor1 to 1 and motor2 to 10, simultaneously. Wait for both to arrive. +print (motor1.get(), motor2.get()) +def move_then_count(): + yield from mv(motor1, 1, motor2, 10) + yield from count(dets) +RE(move_then_count()) + + +sd = SupplementalData() +RE.preprocessors.append(sd) +sd.baseline = [det1, det2, det3, motor1, motor2] +RE(scan([det], motor, -1, 1, 5)) +print(db[-1].table("baseline")) +print(db[-1].table("primary")) + + +""" +docs = db[-1].documents(fill=True) +try: + suitcase.csv.export(docs, "~/data/bluesky") +except: + print (sys.exc_info()[1]) +""" + +motor.delay = 1.1 # simulate slow motor movement +sd.monitors=[motor] +RE(scan(dets, motor, -1, 1, 10)) +print(db[-1].table("baseline")) +print(db[-1].table("monitor")) + + +#RE.resume() +#RE.abort() +#RE.stop() + + +RE(scan([det], motor, 1, 10, 10), user="alex") +for x in db(user="alex"): + print (x.table()) + + +summarize_plan(count([det], 3)) +summarize_plan(scan(dets, motor, -1, 1, 10)) +summarize_plan(grid_scan(dets, motor1, -1.5, 1.5, 3, motor2, -0.1, 0.1, 5)) + + +def one_run_one_event(detectors): + + md = { + # Human-friendly names of detector Devices (useful for searching) + 'detectors': [det.name for det in detectors], + + # The Python 'repr's each argument to the plan + 'plan_args': {'detectors': list(map(repr, detectors))}, + + # The name of this plan + 'plan_name': 'one_run_one_event', + } + @bpp.stage_decorator(detectors) + @bpp.run_decorator(md=md) + def inner(): + yield from bps.trigger_and_read(detectors) + + return (yield from inner()) + +dets = [det1,det2] +RE(one_run_one_event(dets)) + + +def conditional_break(threshold): + """Set, trigger, read until the detector reads intensity < threshold""" + + @bpp.stage_decorator([det, motor]) + @bpp.run_decorator() + def inner(): + i = 0 + while True: + yield from bps.mv(motor, i) + readings = yield from bps.trigger_and_read([det]) + if readings['det']['value'] < threshold: + break + i += 1 + return (yield from inner()) + +RE(conditional_break(0.2)) + +#catalog = databroker.catalog() + +dets=[pseudo1x3] +RE(scan(dets, motor, -1, 1, 10)) + +es = EpicsSignal("TESTIOC:TESTSINUS:SinCalc") +print (es.read()) + + +try: + plot(direct_img.read()['img']['value'].data) + +except: + traceback.print_exc() \ No newline at end of file diff --git a/script/cpy/bluesky2.py b/script/cpy/bluesky2.py new file mode 100644 index 0000000..b8462a0 --- /dev/null +++ b/script/cpy/bluesky2.py @@ -0,0 +1,30 @@ +""" +RE = RunEngine({}, during_task=EventProcessingTask()) +bec = BestEffortCallback() +bec.disable_plots() +RE.subscribe(bec) +RE.subscribe(handler) + +motor.delay = 1.1 # simulate slow motor movement + + +ch1 = EpicsSignal("TESTIOC:TESTSINUS:SinCalc") +#TODO: DEmonstrate use of waveform and areadetector (Manual scan setup with the indexes in name) +#ch2 = EpicsSignal("TESTIOC:TESTWF2:MyWF", name="arr[10]") +#ch3 = EpicsSignal("TESTIOC:TESTWF2:MyWF", name="img[3][2]")det3=ReaderWrapper(sin) +""" +dets = [det1, det2] + +RE(count(dets, num=5, delay=0.5)) +RE(scan(dets, motor, 0, 1, 5)) +RE(rel_scan(dets, motor, -1, 1, 10)) +RE(list_scan(dets, motor, [1, 1, 2, 3, 5, 8, 13])) +RE(grid_scan(dets, motor1, -1.5, 1.5, 3, motor2, -0.1, 0.1, 5)) +RE(list_grid_scan(dets, motor1, [1, 1, 2, 3, 5], motor2, [25, 16, 9])) + + +det4=ReaderWrapper(arr) +det5=ReaderWrapper(get_device("det").getDataMatrix() ) +m1=MoverWrapper(get_device("motor")) +dets = [det1, det2, ch1, det3, det4, det5] +RE(scan(dets, m1, 0, 1, 5)) diff --git a/script/cpy/local.py b/script/cpy/local.py new file mode 100644 index 0000000..847b204 --- /dev/null +++ b/script/cpy/local.py @@ -0,0 +1,487 @@ +################################################################################################### +# Deployment specific global definitions - executed after startup.py +################################################################################################### + +################################################################################################### +#Devices for PShell standard scans +################################################################################################### + +import random + +#################################################################################################### +# Simulated devices +#################################################################################################### + +add_device(DummyMotor("m1"), True) +add_device(DummyMotor("m2"), True) +add_device(DummyRegister("reg1",3), True) +add_device(DummyPositioner("p1"),True) +add_device(MotorGroupBase("mg1", m1, m2), True) +add_device(MotorGroupDiscretePositioner("dp1", mg1), True) + + +#Initial Configuration +if p1.getConfig().unit is None: + p1.getConfig().minValue = 0.0 #Not persisted + p1.getConfig().maxValue = 1000.0 + p1.getConfig().unit = "mm" + p1.getConfig().save() + p1.initialize() + +if dp1.getConfig().positions is None: + dp1.getConfig().positions = ["Park","Ready","Out","Clear"] + dp1.getConfig().motor1 = ["0.0","4.0","8.0" ,"0.0"] + dp1.getConfig().motor2 = ["0.0","5.0","3.0" ,"NaN"] + dp1.getConfig().save() + dp1.initialize() + + + +#Update +m1.setMonitored(True) +m2.setMonitored(True) + +#################################################################################################### +# Readable / Writable objects can be created and used in scans +#################################################################################################### + +class MyWritable(Writable): + def write(self, value): + #print ("Write: ",value) + pass + +class MyReadable(Readable): + def read(self): + return random.random() + +class MyReadableArray(ReadableArray): + def read(self): + ret = [] + for i in range (self.getSize()): + ret.append(random.random()) + return to_array(ret,'d') + + def getSize(self): + return 20 + +class MyReadableArrayNumpy(ReadableArray): + def read(self): + ret = numpy.ones(self.getSize(),'d') + return ret + + def getSize(self): + return 20 + +class MyReadableMatrix(ReadableMatrix): + def read(self): + ret = [] + for i in range (self.getHeight()): + ret.append([random.random()] * self.getWidth()) + return to_array(ret, 'd') + + def getWidth(self): + return 80 + + def getHeight(self): + return 40 + +class MyReadableMatrixNumpy(ReadableMatrix): + def read(self): + ret = numpy.ones((self.getHeight(), self.getWidth()),'d') + for i in range(self.getHeight()): + ret[i]=i + return to_array(ret, 'd') + + def getWidth(self): + return 80 + + def getHeight(self): + return 40 + + +ao1 = MyWritable("ao1") +ao2 = MyWritable("ao2") +ai1 = MyReadable("ai1") +ai2 = MyReadable("ai2") +wf1 = MyReadableArray("wf1") +wf2 = MyReadableArrayNumpy("wf2") +im1 = MyReadableMatrix("im1") +im2 = MyReadableMatrixNumpy("im2") + + +#################################################################################################### +# Imaging +#################################################################################################### + +configured = os.path.exists(GenericDevice.getConfigFileName("src1")) + +add_device(RegisterMatrixSource("src1", im1.proxy), True) +add_device(RegisterMatrixSource("src2", im2.proxy), True) + +#src1.setPolling(100) +#src2.setPolling(100) + +#Some configuration for so the imaging will work out of the box +if not configured: + src1.getConfig().colormapAutomatic = True + src1.getConfig().colormap = Colormap.Temperature + src1.getConfig().save() + src2.getConfig().colormapAutomatic = True + src2.getConfig().save() + + + + +################################################################################################### +#Embedding Bluesky +################################################################################################### + + +import signal +signal.signal = lambda *args: None +from bluesky import RunEngine +from bluesky.callbacks import CallbackBase +from bluesky.callbacks.best_effort import BestEffortCallback +from bluesky.utils import install_kicker, DuringTask +#from bluesky.utils import ProgressBarManager +from ophyd.sim import det1, det2, det3, det4, det, motor, motor1, motor2, motor3,img, sig, direct_img, pseudo1x3 +from ophyd import Signal +from ophyd.signal import EpicsSignal +from bluesky.plans import count, scan, rel_scan, list_scan, grid_scan, list_grid_scan +from bluesky.simulators import summarize_plan +import bluesky.plan_stubs as bps +from bluesky.plan_stubs import mv +import bluesky.preprocessors as bpp +from bluesky.preprocessors import SupplementalData +#import databroker +from databroker import Broker +#import suitcase +#import suitcase.csv + +CAN_PAUSE=True + + + +#def on_ctrl_cmd(cmd): +def on_abort(parent_thread): + global RE + # print ("Control command: ", cmd) + # if cmd=="abort": + if "RE" in globals(): + if RE.state not in ['idle','paused', 'pausing']: + if CAN_PAUSE: + print ("Abort command: Run Engine aborted") + sys.stderr=None + RE.abort("User abort") + return + else: + print ("Abort command: Run Engine pause request") + RE.request_pause() + return + tid=parent_thread.ident + exception = KeyboardInterrupt + ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), ctypes.py_object(exception)) + +def on_close(parent_thread): + on_abort(parent_thread) + + + + +from collections import deque + +is_scan_paused = False +class MyHandler(CallbackBase): + + def __init__(self): + self.queue= deque(maxlen=1000) + + def clear(self): + self.queue.append(("clear",None)) + + def start(self, doc): + self.queue.append(("start",doc)) + + def stop(self, doc): + self.queue.append(("stop",doc)) + + def descriptor(self, doc): + self.queue.append(("descriptor",doc)) + + def resource(self, doc): + self.queue.append(("resource",doc)) + + def event(self, doc): + self.queue.append(("event",doc)) + while is_scan_paused: + time.sleep(0.1) + + def datum(self, doc): + self.queue.append(("datum",doc)) + + def event_page(self, doc): + self.queue.append(("event_page",doc)) + + def datum_page(self, doc): + self.queue.append(("datum_page",doc)) + +handler= MyHandler() +re_scan=re_res=None + + +class EventProcessingTask(DuringTask): + def __init__(self): + pass + + def block(self, blocking_event): + global start_doc,descriptor_coc, stop_doc, event_doc, re_scan, re_res, __return__,__exception__ + re_scan=None + while True: + done = blocking_event.wait(.1) + if done: + return + try: + check_pause() + while len(handler.queue): + (msg, doc) = handler.queue.popleft() + #print("-> " ,msg) + if msg=="start": + global start_doc + start_doc=doc + writables=doc.get('motors',[]) + + readables=doc.get('detectors',[]) + start,stop, steps=-1,-1,doc.get('num_intervals',-1) + try: + if doc.get("plan_name","")=="grid_scan": + steps=[x-1 for x in doc['shape']] + start=[x[0] for x in doc['extents']] + stop=[x[1] for x in doc['extents']] + elif doc.get("plan_name","")=="list_grid_scan": + steps=[-1 for x in doc['shape']] + start=[x[0] for x in doc['extents']] + stop=[x[1] for x in doc['extents']] + elif doc.get("plan_name","")=="scan": + _,start,stop = doc['plan_args']['args'] + elif doc.get("plan_name","")=="list_scan": + _,positions=doc['plan_args']['args'] + start = min(positions) + stop = max(positions) + except: + pass + + diags=None + monitors=None + meta={} + for k in start_doc.keys(): + o=start_doc[k] + if o is not None: + if k=="extents": + o = str(o) + elif type(o) in (list, tuple): + o=to_array(o,'s') + elif type(o) == dict: + o=str(o) + meta[k]=o + re_res = None + re_scan = ManualScan(writables, readables ,start, stop, steps, diags=diags, monitors=monitors, meta=meta) + re_scan.scan.setCanPause(CAN_PAUSE) + re_scan.start() + + elif msg=="stop": + global stop_doc + stop_doc=doc + if re_scan is not None: + if not re_scan.scan.isCompleted(): + re_scan.end() + re_res = re_scan.scan.getResult() + sys.stderr=jep_stderr + elif msg=="descriptor": + global descriptor_doc + descriptor_doc=doc + elif msg=="event": + global event_doc + event_doc=doc + if (re_scan is not None) and not (re_scan.scan.isCompleted()): + setpoints=[] + readbacks=[] + detectors=[] + data=doc['data'] + for dev in start_doc.get("motors",[]): + readbacks.append(data[dev]) + try: + setpoints.append(data[dev+"_setpoint"]) + except: + setpoints.append(data[dev]) + for dev in start_doc.get("detectors",[]): + v=data[dev] + if str(type(v))=="": + v=numpy.array(v) + detectors.append(v) + re_scan.append (setpoints, readbacks, detectors) + elif msg=="resource": + pass + elif msg=="datum": + pass + elif msg=="event_page": + pass + elif msg=="datum_page": + pass + elif msg=="clear": + pass + elif msg=="check_pause": + pass + elif msg=="read": + try: + (dev)=doc + __return__ = dev.read() + except Exception as e: + __exception__ = e + elif msg=="write": + try: + (dev, value)=doc + dev.write(value) + __return__ = True + except Exception as e: + __exception__ = e + except Exception as e: + #print (e) + pass + + +def check_pause(): + try: + global RE, re_scan, is_scan_paused + if CAN_PAUSE: + if ("RE" in globals()) and (re_scan is not None) and not (re_scan.scan.isCompleted()): + is_scan_paused =re_scan.scan.isPaused() and not re_scan.scan.isAborted() + else: + is_scan_paused = False + #if re_scan.scan.isAborted(): + # if RE.state not in ['idle','paused', 'pausing']: + # print ("Scan abort") + # RE.abort("Scan abort") + """ + if re_scan.scan.isPaused(): + if RE.state not in ['idle','paused', 'pausing']: + print ("Scan paused: Run Engine pause request") + RE.request_pause() + is_scan_paused = True + else: + if RE.state in ['paused', 'pausing']: + print ("Scan resumed: Run Engine resuming") + #RE.resume() + """ + except: + pass + + +class ReaderWrapper(): + def __init__(self, dev): + self.dev=dev + self.name=dev.getName() + self.parent = None + try: + self.source = self.dev.getChannelName() + except: + self.source = "Unknown" + try: + try: + self.shape = [self.dev.getHeight(), self.dev.getWidth()] + self.shape_str = "["+str(self.shape[0])+"]"+"["+str(self.shape[1])+"]" + except: + self.shape = [self.dev.getSize()] + self.shape_str = "["+str(self.shape[0])+"]" + except: + self.shape = [] + self.shape_str="" + try: + self.precision = self.dev.getPrecision() + except: + self.precision = None + self.description = {self.name: { \ + 'dtype':'number', \ + 'shape': self.shape, \ + 'source': self.source, \ + 'precision': self.precision \ + }} + + self.cfg_description = {"shape_str":{"dtype":"string", 'shape':(len(self.shape_str),), "source":""}, } + self.configuration = {"shape_str":{"value":self.shape_str, "timestamp":time.time()}} + self.name = self.name+self.shape_str + + def read(self): + if is_main_thread(): + return {self.name:{"value":self.dev.read(), "timestamp":time.time()}} + global __return__,__exception__ + __return__ = __exception__ = None + handler.queue.append(("read", (self.dev))) + while (__return__ is None) and (__exception__ is None): + time.sleep(0.01) + if __exception__ is not None: + raise __exception__ + return {self.name:{"value":__return__, "timestamp":time.time()}} + + def describe(self): + return self.description + + def describe_configuration(self): + return self.cfg_description + + def read_configuration(self): + return self.configuration + +class NullStatus: + "a simple Status object that is always immediately done" + def __init__(self): + self._cb = None + self.done = True + self.success = True + + @property + def finished_cb(self): + return self._cb + + @finished_cb.setter + def finished_cb(self, cb): + cb() + self._cb = cb + +class MoverWrapper(ReaderWrapper): + def set(self, value): + if is_main_thread(): + self.dev.write(value) + else: + global __return__,__exception__ + __return__ = __exception__ = None + handler.queue.append(("write", (self.dev, value))) + while (__return__ is None) and (__exception__ is None): + time.sleep(0.01) + if __exception__ is not None: + raise __exception__ + self.dev.waitReady(-1) + return NullStatus() + + @property + def position(self): + return self.dev.getPosition() + + def stop(self, *, success=False): + self.dev.stop() + + + +RE = RunEngine({}, during_task=EventProcessingTask()) +if CAN_PAUSE: + RE.pause_msg="User abort" +bec = BestEffortCallback() +bec.disable_plots() +RE.subscribe(bec) +RE.subscribe(handler) + +motor.delay = 1.1 # simulate slow motor movement +ch1 = EpicsSignal("TESTIOC:TESTSINUS:SinCalc") +#TODO: DEmonstrate use of waveform and areadetector (Manual scan setup with the indexes in name) +#ch2 = EpicsSignal("TESTIOC:TESTWF2:MyWF", name="arr[10]") +#ch3 = EpicsSignal("TESTIOC:TESTWF2:MyWF", name="img[3][2]")det3=ReaderWrapper(sin) +dets = [det1, det2] \ No newline at end of file diff --git a/script/cpy/startup_jep.py b/script/cpy/startup_jep.py new file mode 100644 index 0000000..2855bfc --- /dev/null +++ b/script/cpy/startup_jep.py @@ -0,0 +1,2796 @@ +################################################################################################### +# Global definitions and built-in functions +################################################################################################### + +import sys +sys.argv=[''] +import time +import math +from inspect import signature +import os.path +from operator import add, mul, sub, truediv +from time import sleep +from array import array +import types + +#TODO +#from jep import PyJArray +def is_array(obj): + return str(type(obj)) == "" + +from java.lang import Class +from java.lang import Object +from java.beans import PropertyChangeListener +from java.util import concurrent +from java.util import List +from java.util import ArrayList +from java.lang import reflect +from java.lang import Thread + +from java.awt.image import BufferedImage +from java.awt import Color +from java.awt import Point +from java.awt import Dimension +from java.awt import Rectangle +from java.awt import Font + + +from java.lang import Boolean, Integer, Float, Double, Short, Byte, Long, String + +from ch.psi.pshell import core +from ch.psi.pshell.scripting import ScriptUtils +from ch.psi.utils import Convert +from ch.psi.utils import Arr + +__THREAD_EXEC_RESULT__=None + +################################################################################################### +#Type conversion and checking +################################################################################################### + +def to_array(obj, type = None, primitive = True): + """Convert Python list to Java array. + + Args: + obj(list): Original data. + type(str): array type 'b' = byte, 'h' = short, 'i' = int, 'l' = long, 'f' = float, 'd' = double, + 'c' = char, 'z' = boolean, 's' = String, 'o' = Object + Returns: + Java array. + """ + if obj is None: + return None + if type is None: + type = 'o' + enforceArrayType=False + else: + enforceArrayType=True + if type[0] == '[': + type = type[1:] + element_type = ScriptUtils.getPrimitiveType(type) if primitive else ScriptUtils.getType(type) + + def convert_1d_array(obj): + if type == 'c': + ret = reflect.Array.newInstance(element_type,len(obj)) + for i in range(len(obj)): ret[i] = chr(obj[i]) + return ret + if type == 'z': + ret = reflect.Array.newInstance(element_type,len(obj)) + for i in range(len(obj)): + ret[i]= True if obj[i] else False + return ret + if type == 'o': + ret = reflect.Array.newInstance(element_type,len(obj)) + for i in range(len(obj)): + ret[i]= obj[i] + return ret + if type == "s": + return Convert.toStringArray(obj) + if primitive: + ret = Convert.toPrimitiveArray(obj, element_type) + else: + ret = reflect.Array.newInstance(element_type,len(obj)) + for i in range(len(obj)): ret[i] = Convert.toType(obj[i],element_type) + return ret + + if is_array(obj): + if enforceArrayType: + if Arr.getComponentType(obj) != element_type: + rank = Arr.getRank(obj) + if (rank== 1): + obj=convert_1d_array(obj) + elif (rank>1): + pars, aux = [element_type], obj + for i in range(rank): + pars.append(len(aux)) + aux = aux[0] + ret = reflect.Array.newInstance(*pars) + for i in range(len(obj)): + ret[i]=to_array(obj[i], type) + obj = ret + elif is_list(obj): + if type=='o': + ret = reflect.Array.newInstance(element_type, len(obj)) + for i in range (len(obj)): + if is_list(obj[i]) or is_array(obj[i]): + ret[i] = to_array(obj[i],type) + else: + ret[i] = obj[i] + obj=ret + elif len(obj)>0 and (is_list(obj[0]) or is_array(obj[0])): + pars, aux = [element_type], obj + while len(aux)>0 and (is_list(aux[0]) or is_array(aux[0])): + pars.append(len(aux)) + aux = aux[0] + pars.append(0) + ret = reflect.Array.newInstance(*pars) + for i in range(len(obj)): + ret[i]=to_array(obj[i], type) + obj=ret + else: + obj= convert_1d_array(obj) + return obj + +def to_list(obj): + """Convert an object into a Python List. + + Args: + obj(tuple or array or ArrayList): Original data. + + Returns: + List. + """ + if obj is None: + return None + if isinstance(obj,tuple) or is_java_instance(obj,ArrayList) : + return list(obj) + #if is_array(obj): + # return obj.tolist() + if not isinstance(obj,list): + return [obj,] + return obj + +def is_list(obj): + return isinstance(obj,tuple) or isinstance(obj,list) or is_java_instance (obj, ArrayList) + +def is_string(obj): + return (type(obj) is str) + + +def is_interpreter_thread(): + return Thread.currentThread().getName() == "Interpreter Thread" + + +def is_java_instance(obj, cls): + try: + return obj.getClass() == Class.forName(cls.java_name) + except: + return False +################################################################################################### +#Access to context singleton +################################################################################################### +def get_context(): + return core.Context.getInstance() + +################################################################################################### +#Builtin classes +################################################################################################### + +from ch.psi.utils import Threading as Threading +from ch.psi.utils import State as State +from ch.psi.utils import Convert as Convert +from ch.psi.utils import Str as Str +from ch.psi.utils import Sys as Sys +from ch.psi.utils import Arr as Arr +from ch.psi.utils import IO as IO +from ch.psi.utils import Chrono as Chrono +from ch.psi.utils import Folder as Folder +from ch.psi.utils import Histogram as Histogram +from ch.psi.utils import History as History +from ch.psi.utils import Condition as Condition +from ch.psi.utils import ArrayProperties as ArrayProperties +from ch.psi.utils import Audio as Audio +from ch.psi.utils import BitMask as BitMask +from ch.psi.utils import Config as Config +from ch.psi.utils import Inventory as Inventory +from ch.psi.utils import DataAPI as DataAPI +from ch.psi.utils import DispatcherAPI as DispatcherAPI +from ch.psi.utils import EpicsBootInfoAPI as EpicsBootInfoAPI +from ch.psi.utils import Mail as Mail +from ch.psi.utils import Posix as Posix +from ch.psi.utils import ProcessFactory as ProcessFactory +from ch.psi.utils import Range as Range +from ch.psi.utils import Reflection as Reflection +from ch.psi.utils import Serializer as Serializer +from ch.psi.utils import Windows as Windows +from ch.psi.utils import NumberComparator as NumberComparator + + +from ch.psi.pshell.core import CommandSource as CommandSource +from ch.psi.pshell.core import ContextAdapter as ContextListener +from ch.psi.pshell.core import Context +from ch.psi.pshell.core import InlineDevice as InlineDevice + +from ch.psi.pshell.data import DataSlice as DataSlice +from ch.psi.pshell.data import PlotDescriptor as PlotDescriptor +from ch.psi.pshell.data import Table as Table +from ch.psi.pshell.data import Provider as Provider +from ch.psi.pshell.data import ProviderHDF5 as ProviderHDF5 +from ch.psi.pshell.data import ProviderText as ProviderText +from ch.psi.pshell.data import ProviderCSV as ProviderCSV +from ch.psi.pshell.data import ProviderFDA as ProviderFDA +from ch.psi.pshell.data import Converter as DataConverter +from ch.psi.pshell.data import Layout as Layout +from ch.psi.pshell.data import LayoutBase as LayoutBase +from ch.psi.pshell.data import LayoutDefault as LayoutDefault +from ch.psi.pshell.data import LayoutTable as LayoutTable +from ch.psi.pshell.data import LayoutFDA as LayoutFDA +from ch.psi.pshell.data import LayoutSF as LayoutSF + +from ch.psi.pshell.device import Device as Device +from ch.psi.pshell.device import DeviceBase as DeviceBase +from ch.psi.pshell.device import DeviceConfig as DeviceConfig +from ch.psi.pshell.device import PositionerConfig as PositionerConfig +from ch.psi.pshell.device import RegisterConfig as RegisterConfig +from ch.psi.pshell.device import ReadonlyProcessVariableConfig as ReadonlyProcessVariableConfig +from ch.psi.pshell.device import ProcessVariableConfig as ProcessVariableConfig +from ch.psi.pshell.device import MotorConfig as MotorConfig +from ch.psi.pshell.device import Register as Register +from ch.psi.pshell.device import RegisterBase as RegisterBase +from ch.psi.pshell.device import ProcessVariableBase as ProcessVariableBase +from ch.psi.pshell.device import ControlledVariableBase as ControlledVariableBase +from ch.psi.pshell.device import PositionerBase as PositionerBase +from ch.psi.pshell.device import MasterPositioner as MasterPositioner +from ch.psi.pshell.device import MotorBase as MotorBase +from ch.psi.pshell.device import DiscretePositionerBase as DiscretePositionerBase +from ch.psi.pshell.device import MotorGroupBase as MotorGroupBase +from ch.psi.pshell.device import MotorGroupDiscretePositioner as MotorGroupDiscretePositioner +from ch.psi.pshell.device import ReadonlyRegisterBase as ReadonlyRegisterBase +from ch.psi.pshell.device import ReadonlyAsyncRegisterBase as ReadonlyAsyncRegisterBase +from ch.psi.pshell.device import Register as Register +RegisterArray = Register.RegisterArray +RegisterNumber = Register.RegisterNumber +RegisterBoolean = Register.RegisterBoolean +from ch.psi.pshell.device import RegisterCache as RegisterCache +from ch.psi.pshell.device import ReadonlyRegister +ReadonlyRegisterArray = ReadonlyRegister.ReadonlyRegisterArray +ReadonlyRegisterMatrix = ReadonlyRegister.ReadonlyRegisterMatrix +from ch.psi.pshell.device import DummyPositioner as DummyPositioner +from ch.psi.pshell.device import DummyMotor as DummyMotor +from ch.psi.pshell.device import DummyRegister as DummyRegister +from ch.psi.pshell.device import Timestamp as Timestamp +from ch.psi.pshell.device import Interlock as Interlock +from ch.psi.pshell.device import Readable as Readable +ReadableArray = Readable.ReadableArray +ReadableMatrix = Readable.ReadableMatrix +ReadableCalibratedArray = Readable.ReadableCalibratedArray +ReadableCalibratedMatrix = Readable.ReadableCalibratedMatrix +from ch.psi.pshell.device import ArrayCalibration as ArrayCalibration +from ch.psi.pshell.device import MatrixCalibration as MatrixCalibration +from ch.psi.pshell.device import Writable as Writable +WritableArray = Writable.WritableArray +from ch.psi.pshell.device import Stoppable as Stoppable +from ch.psi.pshell.device import Averager as Averager +from ch.psi.pshell.device import ArrayAverager as ArrayAverager +from ch.psi.pshell.device import Delta as Delta +from ch.psi.pshell.device import DeviceAdapter as DeviceListener +from ch.psi.pshell.device import ReadbackDeviceAdapter as ReadbackDeviceListener +from ch.psi.pshell.device import MotorAdapter as MotorListener +from ch.psi.pshell.device import MoveMode as MoveMode +from ch.psi.pshell.device import SettlingCondition as SettlingCondition +from ch.psi.pshell.device import HistogramGenerator as HistogramGenerator + +from ch.psi.pshell.epics import Epics as Epics +from ch.psi.pshell.epics import EpicsScan as EpicsScan +from ch.psi.pshell.epics import ChannelSettlingCondition as ChannelSettlingCondition +from ch.psi.pshell.epics import AreaDetector as AreaDetector +from ch.psi.pshell.epics import BinaryPositioner as BinaryPositioner +from ch.psi.pshell.epics import ChannelByte as ChannelByte +from ch.psi.pshell.epics import ChannelByteArray as ChannelByteArray +from ch.psi.pshell.epics import ChannelByteMatrix as ChannelByteMatrix +from ch.psi.pshell.epics import ChannelDouble as ChannelDouble +from ch.psi.pshell.epics import ChannelDoubleArray as ChannelDoubleArray +from ch.psi.pshell.epics import ChannelDoubleMatrix as ChannelDoubleMatrix +from ch.psi.pshell.epics import ChannelFloat as ChannelFloat +from ch.psi.pshell.epics import ChannelFloatArray as ChannelFloatArray +from ch.psi.pshell.epics import ChannelFloatMatrix as ChannelFloatMatrix +from ch.psi.pshell.epics import ChannelInteger as ChannelInteger +from ch.psi.pshell.epics import ChannelIntegerArray as ChannelIntegerArray +from ch.psi.pshell.epics import ChannelIntegerMatrix as ChannelIntegerMatrix +from ch.psi.pshell.epics import ChannelShort as ChannelShort +from ch.psi.pshell.epics import ChannelShortArray as ChannelShortArray +from ch.psi.pshell.epics import ChannelShortMatrix as ChannelShortMatrix +from ch.psi.pshell.epics import ChannelString as ChannelString +from ch.psi.pshell.epics import ControlledVariable as ControlledVariable +from ch.psi.pshell.epics import DiscretePositioner as DiscretePositioner +from ch.psi.pshell.epics import GenericChannel as GenericChannel +from ch.psi.pshell.epics import GenericArray as GenericArray +from ch.psi.pshell.epics import GenericMatrix as GenericMatrix +from ch.psi.pshell.epics import Manipulator as Manipulator +from ch.psi.pshell.epics import Motor as EpicsMotor +from ch.psi.pshell.epics import Positioner as Positioner +from ch.psi.pshell.epics import ProcessVariable as ProcessVariable +from ch.psi.pshell.epics import ReadonlyProcessVariable as ReadonlyProcessVariable +from ch.psi.pshell.epics import Scaler as Scaler +from ch.psi.pshell.epics import Scienta as Scienta +from ch.psi.pshell.epics import Slit as Slit +from ch.psi.pshell.epics import AreaDetectorSource as AreaDetectorSource +from ch.psi.pshell.epics import ArraySource as ArraySource +from ch.psi.pshell.epics import ByteArraySource as ByteArraySource +from ch.psi.pshell.epics import PsiCamera as PsiCamera +from ch.psi.pshell.epics import CAS as CAS + +from ch.psi.pshell.serial import SerialPortDevice as SerialPortDevice +from ch.psi.pshell.serial import TcpDevice as TcpDevice +from ch.psi.pshell.serial import UdpDevice as UdpDevice +from ch.psi.pshell.serial import SerialPortDeviceConfig as SerialPortDeviceConfig +from ch.psi.pshell.serial import SocketDeviceConfig as SocketDeviceConfig + +from ch.psi.pshell.modbus import ModbusTCP as ModbusTCP +from ch.psi.pshell.modbus import ModbusUDP as ModbusUDP +from ch.psi.pshell.modbus import ModbusSerial as ModbusSerial +from ch.psi.pshell.modbus import AnalogInput as ModbusAI +from ch.psi.pshell.modbus import AnalogInputArray as ModbusMAI +from ch.psi.pshell.modbus import AnalogOutput as ModbusAO +from ch.psi.pshell.modbus import AnalogOutputArray as ModbusMAO +from ch.psi.pshell.modbus import DigitalInput as ModbusDO +from ch.psi.pshell.modbus import DigitalInputArray as ModbusMDI +from ch.psi.pshell.modbus import DigitalOutput as ModbusDO +from ch.psi.pshell.modbus import DigitalOutputArray as ModbusMDO +from ch.psi.pshell.modbus import Register as ModbusReg +from ch.psi.pshell.modbus import ReadonlyProcessVariable as ModbusROPV +from ch.psi.pshell.modbus import ProcessVariable as ModbusPV +from ch.psi.pshell.modbus import ControlledVariable as ModbusCB +from ch.psi.pshell.modbus import ModbusDeviceConfig as ModbusDeviceConfig + +from ch.psi.pshell.imaging import Source as Source +from ch.psi.pshell.imaging import SourceBase as SourceBase +from ch.psi.pshell.imaging import DirectSource as DirectSource +from ch.psi.pshell.imaging import RegisterArraySource as RegisterArraySource +from ch.psi.pshell.imaging import RegisterMatrixSource as RegisterMatrixSource +from ch.psi.pshell.imaging import ImageListener as ImageListener +from ch.psi.pshell.imaging import ImageMeasurement as ImageMeasurement +from ch.psi.pshell.imaging import CameraSource as CameraSource +from ch.psi.pshell.imaging import ColormapAdapter as ColormapAdapter +from ch.psi.pshell.imaging import FileSource as FileSource +from ch.psi.pshell.imaging import MjpegSource as MjpegSource +from ch.psi.pshell.imaging import Webcam as Webcam +from ch.psi.pshell.imaging import Filter as Filter +from ch.psi.pshell.imaging import Utils as ImagingUtils +from ch.psi.pshell.imaging import Overlay as Overlay +from ch.psi.pshell.imaging import Overlays as Overlays +from ch.psi.pshell.imaging import Pen as Pen +from ch.psi.pshell.imaging import Data as Data +from ch.psi.pshell.imaging import Colormap as Colormap +from ch.psi.pshell.imaging import Renderer as Renderer + + +from ch.psi.pshell.plot import RangeSelectionPlot as RangeSelectionPlot +RangeSelectionPlotListener= RangeSelectionPlot.RangeSelectionPlotListener +from ch.psi.pshell.plot import LinePlot as LinePlot +from ch.psi.pshell.plot import MatrixPlot as MatrixPlot +from ch.psi.pshell.plot import TimePlot as TimePlot +from ch.psi.pshell.plot import SlicePlot as SlicePlot +from ch.psi.pshell.plot import LinePlotJFree as LinePlotJFree +from ch.psi.pshell.plot import MatrixPlotJFree as MatrixPlotJFree +from ch.psi.pshell.plot import TimePlotJFree as TimePlotJFree +from ch.psi.pshell.plot import SlicePlotDefault as SlicePlotDefault +from ch.psi.pshell.plot import LinePlotSeries as LinePlotSeries +from ch.psi.pshell.plot import LinePlotErrorSeries as LinePlotErrorSeries +from ch.psi.pshell.plot import MatrixPlotSeries as MatrixPlotSeries +from ch.psi.pshell.plot import TimePlotSeries as TimePlotSeries +from ch.psi.pshell.plot import SlicePlotSeries as SlicePlotSeries + +from ch.psi.pshell import scan as scans +from ch.psi.pshell.scan import ScanBase as ScanBase +from ch.psi.pshell.scan import ScanResult +from ch.psi.pshell.scan import Otf as Otf +from ch.psi.pshell.scan import ScanAbortedException as ScanAbortedException + +from ch.psi.pshell.crlogic import CrlogicPositioner as CrlogicPositioner +from ch.psi.pshell.crlogic import CrlogicSensor as CrlogicSensor + +from ch.psi.pshell.bs import BsScan +from ch.psi.pshell.bs import Stream as Stream +from ch.psi.pshell.bs import Provider as Provider +from ch.psi.pshell.bs import Dispatcher as Dispatcher +from ch.psi.pshell.bs import Scalar as Scalar +from ch.psi.pshell.bs import Waveform as Waveform +from ch.psi.pshell.bs import Matrix as Matrix +from ch.psi.pshell.bs import StreamCamera as StreamCamera +from ch.psi.pshell.bs import CameraServer as CameraServer +from ch.psi.pshell.bs import PipelineServer as PipelineServer +from ch.psi.pshell.bs import ProviderConfig as ProviderConfig +from ch.psi.pshell.bs import StreamConfig as StreamConfig +from ch.psi.pshell.bs import ScalarConfig as ScalarConfig +from ch.psi.pshell.bs import WaveformConfig as WaveformConfig +from ch.psi.pshell.bs import MatrixConfig as MatrixConfig + +from ch.psi.pshell.detector import DetectorConfig as DetectorConfig + +from ch.psi.pshell.ui import App as App + +from ch.psi.pshell.scripting import ViewPreference as Preference +from ch.psi.pshell.scripting import ScriptUtils as ScriptUtils +from ch.psi.pshell.device import Record +from javax.swing import SwingUtilities +invokeLater = SwingUtilities.invokeLater +invokeAndWait = SwingUtilities.invokeAndWait + +from org.jfree.ui import RectangleAnchor as RectangleAnchor +from org.jfree.ui import TextAnchor as TextAnchor + + +def string_to_obj(o): + if is_string(o): + o=str(o) + if "://" in o: + return InlineDevice(o) + ret = get_context().getInterpreterVariable(o) + if ret is None: + try: + return get_context().scriptManager.evalBackground(o).result + except: + return None + return ret + elif is_list(o): + ret = [] + for i in o: + ret.append(string_to_obj(i)) + return ret + return o + +def json_to_obj(o): + if is_string(o): + import json + return json.loads(o) + elif is_list(o): + ret = [] + for i in o: + ret.append(json_to_obj(i)) + return ret + return o + +################################################################################################### +#Scan classes +################################################################################################### + +def __no_args(f): + ret = f.func_code.co_argcount + return (ret-1) if type(f)==PyMethod else ret + +def __before_readout(scan, pos): + try: + if scan.before_read != None: + args = __no_args(scan.before_read) + if args==0: scan.before_read() + elif args==1: scan.before_read(pos.tolist()) + elif args==2: scan.before_read(pos.tolist(), scan) + except AttributeError: + pass + +def __after_readout(scan, record): + try: + if scan.after_read != None: + args = __no_args(scan.after_read) + if args==0: scan.after_read() + elif args==1: scan.after_read(record) + elif args==2: scan.after_read(record, scan) + except AttributeError: + pass + +def __before_pass(scan, num_pass): + try: + if scan.before_pass != None: + args = __no_args(scan.before_pass) + if args==0:scan.before_pass() + elif args==1:scan.before_pass(num_pass) + elif args==2:scan.before_pass(num_pass, scan) + except AttributeError: + pass + +def __after_pass(scan, num_pass): + try: + if scan.after_pass != None: + args = __no_args(scan.after_pass) + if args==0:scan.after_pass() + elif args==1:scan.after_pass(num_pass) + elif args==2:scan.after_pass(num_pass, scan) + except AttributeError: + pass + +def __before_region(scan, num_region): + try: + if scan.before_region != None: + args = __no_args(scan.before_region) + if args==0:scan.before_region() + elif args==1:scan.before_region(num_region) + elif args==2:scan.before_region(num_region, scan) + except AttributeError: + pass + +#TODO +LineScan=scans.LineScan +AreaScan=scans.AreaScan +RegionScan=scans.RegionScan +VectorScan=scans.VectorScan +ContinuousScan=scans.ContinuousScan +TimeScan=scans.TimeScan +MonitorScan=scans.MonitorScan +ManualScan=scans.ManualScan +BinarySearch=scans.BinarySearch +HillClimbingSearcharySearch=scans.HillClimbingSearch + +""" +class LineScan(scans.LineScan): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) + def onBeforePass(self, num): __before_pass(self, num) + def onAfterPass(self, num): __after_pass(self, num) + +class ContinuousScan(scans.ContinuousScan): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) + def onBeforePass(self, num): __before_pass(self, num) + def onAfterPass(self, num): __after_pass(self, num) + +class AreaScan(scans.AreaScan): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) + def onBeforePass(self, num): __before_pass(self, num) + def onAfterPass(self, num): __after_pass(self, num) + +class RegionScan(scans.RegionScan): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) + def onBeforePass(self, num): __before_pass(self, num) + def onAfterPass(self, num): __after_pass(self, num) + def onBeforeRegion(self, num): __before_region(self,num) + +class VectorScan(scans.VectorScan): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) + def onBeforePass(self, num): __before_pass(self, num) + def onAfterPass(self, num): __after_pass(self, num) + +class ContinuousScan(scans.ContinuousScan): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) + def onBeforePass(self, num): __before_pass(self, num) + def onAfterPass(self, num): __after_pass(self, num) + +class TimeScan(scans.TimeScan): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) + def onBeforePass(self, num): __before_pass(self, num) + def onAfterPass(self, num): __after_pass(self, num) + +class MonitorScan(scans.MonitorScan): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) + def onBeforePass(self, num): __before_pass(self, num) + def onAfterPass(self, num): __after_pass(self, num) + +class BsScan(scans.BsScan): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) + def onBeforePass(self, num): __before_pass(self, num) + def onAfterPass(self, num): __after_pass(self, num) + +class ManualScan(scans.ManualScan): + def __init__(self, writables, readables, start = None, end = None, steps = None, relative = False, dimensions = None): + ManualScan.__init__(self, writables, readables, start, end, steps, relative) + self._dimensions = dimensions + + def append(self,setpoints, positions, values, timestamps=None): + ManualScan.append(self, to_array(setpoints), to_array(positions), to_array(values), None if (timestamps is None) else to_array(timestamps)) + + def getDimensions(self): + if self._dimensions == None: + return ManualScan.getDimensions(self) + else: + return self._dimensions + +class BinarySearch(scans.BinarySearch): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) + +class HillClimbingSearch(scans.HillClimbingSearch): + def onBeforeReadout(self, pos): __before_readout(self, pos) + def onAfterReadout(self, rec): __after_readout(self, rec) +""" + +def processScanPars(scan, pars): + #TODO + #scan.before_read = pars.pop("before_read",None) + #scan.after_read = pars.pop("after_read",None) + #scan.before_pass = pars.pop("before_pass",None) + #scan.after_pass = pars.pop("after_pass",None) + #scan.before_region= pars.pop("before_region",None) + scan.setPlotTitle(pars.pop("title",None)) + scan.setHidden(pars.pop("hidden",False)) + scan.setSettleTimeout (pars.pop("settle_timeout",ScanBase.getScansSettleTimeout())) + scan.setUseWritableReadback (pars.pop("use_readback",ScanBase.getScansUseWritableReadback())) + scan.setInitialMove(pars.pop("initial_move",ScanBase.getScansTriggerInitialMove())) + scan.setParallelPositioning(pars.pop("parallel_positioning",ScanBase.getScansParallelPositioning())) + scan.setAbortOnReadableError(pars.pop("abort_on_error",ScanBase.getAbortScansOnReadableError())) + scan.setRestorePosition (pars.pop("restore_position",ScanBase.getRestorePositionOnRelativeScans())) + scan.setCheckPositions(pars.pop("check_positions",ScanBase.getScansCheckPositions())) + scan.setMonitors(to_list(string_to_obj(pars.pop("monitors",None)))) + scan.setSnaps(to_list(string_to_obj(pars.pop("snaps",None)))) + scan.setDiags(to_list(string_to_obj(pars.pop("diags",None)))) + scan.setMeta(pars.pop("meta",None)) + get_context().setCommandPars(scan, pars) + + + +################################################################################################### +#Simple EPICS Channel abstraction +################################################################################################### + +def create_channel(name, type=None, size=None): + return Epics.newChannel(name, Epics.getChannelType(type), size) + + +#Not using finalizer: closing channels in garbage collection generate errors +class Channel(): #TODO (PropertyChangeListener, Writable, Readable, DeviceBase): + def __init__(self, channel_name, type = None, size = None, callback=None, alias = None, monitored=None, name = None): + """ Create an object that encapsulates an Epics PV connection. + Args: + channel_name(str):name of the channel + type(str, optional): type of PV. By default gets the PV standard field type. + Scalar values: 'b', 'i', 'l', 'd', 's'. + Array values: '[b', '[i,', '[l', '[d', '[s'. + size(int, optional): the size of the channel + callback(function, optional): The monitor callback. + alias(str): name to be used on scans. + """ + super(DeviceBase, self).__init__(name if (name is not None) else channel_name.replace(":","_").replace(".","_")) + self.channel = create_channel(channel_name, type, size) + self.callback = callback + self._alias = alias + if monitored is not None:self.setMonitored(monitored) + self.initialize() + + def get_channel_name(self): + """Return the name of the channel. + """ + return self.channel.getName() + + def get_size(self): + """Return the size of the channel. + """ + return self.channel.size + + def set_size(self, size): + """Set the size of the channel. + """ + self.channel.size = size + + def is_connected(self): + """Return True if channel is connected. + """ + return self.channel.connected + + def doSetMonitored(self, value): + self.channel.monitored = value + if (value): + self.channel.addPropertyChangeListener(self) + else: + self.channel.removePropertyChangeListener(self) + + + def is_monitored(self): + """Return True if channel is monitored + """ + return self.channel.monitored + + def set_monitored(self, value): + """Set a channel monitor to trigger the callback function defined in the constructor. + """ + self.setMonitored(value) + + def propertyChange(self, pce): + if pce.getPropertyName() == "value": + value=pce.getNewValue() + self.setCache(value, None) + if self.callback is not None: + self.callback(value) + + def put(self, value, timeout=None): + """Write to channel and wait value change. In the case of a timeout throws a TimeoutException. + Args: + value(obj): value to be written + timeout(float, optional): timeout in seconds. If none waits forever. + """ + if (timeout==None): + self.channel.setValue(value) + else: + self.channel.setValueAsync(value).get(int(timeout*1000), java.util.concurrent.TimeUnit.MILLISECONDS) + self.setCache(value, None) + + def putq(self, value): + """Write to channel and don't wait. + """ + self.channel.setValueNoWait(value) + + def get(self, force = False): + """Get channel value. + """ + ret = self.channel.getValue(force) + self.setCache(ret, None) + return ret + + def wait_for_value(self, value, timeout=None, comparator=None): + """Wait channel to reach a value, using a given comparator. In the case of a timeout throws a TimeoutException. + Args: + value(obj): value to be verified. + timeout(float, optional): timeout in seconds. If None waits forever. + comparator (java.util.Comparator, optional). If None, uses Object.equals. + """ + if comparator is None: + if timeout is None: + self.channel.waitForValue(value) + else: + self.channel.waitForValue(value, int(timeout*1000)) + self.setCache(value, None) + else: + if timeout is None: + self.channel.waitForValue(value, comparator) + else: + self.channel.waitForValue(value, comparator, int(timeout*1000)) + + def doUpdate(self): + self.get() + + def close(self): + """Close the channel. + """ + Epics.closeChannel(self.channel) + + def setAlias(self, alias): + self._alias = alias + + def getAlias(self): + return self._alias if self._alias else self.getName() + + def write(self, value): + self.put(value) + + def read(self): + return self.get() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + +print("Startup") + +################################################################################################### +#Default empty callbacks +################################################################################################### +def on_command_started(info): pass +def on_command_finished(info): pass +def on_session_started(id): pass +def on_session_finished(id): pass +def on_change_data_path(path): pass + + +################################################################################################### +#Help and access to function documentation +################################################################################################### +def _getBuiltinFunctions(filter = None): + ret = [] + for name in globals().keys(): + val = globals()[name] + if isinstance(val, types.FunctionType): + if filter is None or filter in name: + #Only "public" documented functions + if not name.startswith('_') and (val.__doc__ is not None): + ret.append(val) + return to_array(ret) + + +def _getBuiltinFunctionNames(filter = None): + ret = [] + for function in _getBuiltinFunctions(filter): + ret.append(function.__name__) + return to_array(ret) + +def _getFunctionDoc(function): + if is_string(function): + if function not in globals(): + return + function = globals()[function] + if isinstance(function, types.FunctionType): + if '__doc__' in dir(function): + return function.__name__ + str(signature(function)) + "\n\n" + function.__doc__ + +def help(object = None): + """ + Print help message for function or object (if available). + + Args: + object (any, optional): function or object to get help. + If null prints a list of the builtin functions. + + Returns: + None + """ + if object is None: + print ("Built-in functions:") + for f in _getBuiltinFunctionNames(): + print ("\t" + f) + else: + if isinstance(object, types.FunctionType): + print (_getFunctionDoc(object)) + elif '__doc__' in dir(object): + print (object.__doc__) + +################################################################################################### +#Variable injection +################################################################################################### + +def _get_caller(): + #Not doing inspect.currentframe().f_back because inspect is slow to load + return sys._getframe(1).f_back if hasattr(sys, "_getframe") else None + +def inject(): + """Restore initial globals: re-inject devices and startup variables to the interpreter. + + Args: + None + + Returns: + None + """ + if __name__ == "__main__": + get_context().injectVars() + else: + _get_caller().f_globals.update(get_context().scriptManager.injections) + + +################################################################################################### +#Script evaluation and return values +################################################################################################### + +def run(script_name, args = None, locals = None): + """Run script: can be absolute path, relative, or short name to be search in the path. + Args: + args(Dict ot List): Sets sys.argv (if list) or gobal variables(if dict) to the script. + locals(Dict): If not none sets the locals()for the runing script. + If locals is used then script definitions will not go to global namespace. + + Returns: + The script return value (if set with set_return) + """ + script = get_context().scriptManager.library.resolveFile(script_name) + if script is not None and os.path.isfile(script): + info = get_context().startScriptExecution(script_name, args) + try: + set_return(None) + if args is not None: + if isinstance(args,list) or isinstance(args,tuple): + sys.argv = list(args) + globals()["args"] = sys.argv + else: + for arg in args.keys(): + globals()[arg] = args[arg] + if (locals is None): + execfile(script, globals()) + else: + execfile(script, globals(), locals) + ret = get_return() + get_context().finishScriptExecution(info, ret) + return ret + except Exception as ex: + get_context().finishScriptExecution(info, ex) + raise ex + raise IOError("Invalid script: " + str(script_name)) + +def abort(): + """Abort the execution of ongoing task. It can be called from the script to quit. + + Args: + None + + Returns: + None + """ + fork(get_context().abort) #Cannot be on script execution thread + while True: sleep(10.0) + +def set_return(value): + """Sets the script return value. This value is returned by the "run" function. + + Args: + value(Object): script return value. + + Returns: + None + """ + global __THREAD_EXEC_RESULT__ + __THREAD_EXEC_RESULT__=value + return value #Used when parsing file + +def get_return(): + if __name__ == "__main__": + global __THREAD_EXEC_RESULT__ + return __THREAD_EXEC_RESULT__ + else: + return _get_caller().f_globals["__THREAD_EXEC_RESULT__"] + + + +################################################################################################### +#Builtin functions +################################################################################################### + + +################################################################################################### +#Scan commands +################################################################################################### + +def lscan(writables, readables, start, end, steps, latency=0.0, relative=False, passes=1, zigzag=False, **pars): + """Line Scan: positioners change together, linearly from start to end positions. + + Args: + writables(list of Writable): Positioners set on each step. + readables(list of Readable): Sensors to be sampled on each step. + start(list of float): start positions of writables. + end(list of float): final positions of writables. + steps(int or float or list of float): number of scan steps (int) or step size (float). + relative (bool, optional): if true, start and end positions are relative to current. + latency(float, optional): settling time for each step before readout, defaults to 0.0. + passes(int, optional): number of passes + zigzag(bool, optional): if true writables invert direction on each pass. + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - hidden(bool, optional): if true generates no effects on user interface. + - before_read (function(positions, scan), optional): called on each step, before sampling. + - after_read (function(record, scan), optional): called on each step, after sampling. + - before_pass (function(pass_num, scan), optional): called before each pass. + - after_pass (function(pass_num, scan), optional): callback after each pass. + - settle_timeout(int, optional): timeout for each positioner get to position. Default (-1) waits forever. + - initial_move (bool, optional): if true (default) perform move to initial position prior to scan start. + - parallel_positioning (bool, optional): if true (default) all positioners are set in parallel. + - abort_on_error (bool, optional): if true then aborts scan in sensor failures. Default is false. + - restore_position (bool, optional): if true (default) then restore initial position after relative scans. + - check_positions (bool, optional): if true (default) verifies if in correct positions after move finishes. + - monitors (list of Device, optional): device values are saved on every change event during the scan. + - snaps (list of Readable, optional): snapshot device values are saved before the scan. + - diags (list of Readable, optional): diagnostic device values are saved at each scan point. + - meta (dict, optional): scan metadata. + - Aditional arguments defined by set_exec_pars. + + Returns: + ScanResult. + """ + latency_ms=int(latency*1000) + #writables=to_list(string_to_obj(writables)) + readables=to_list(string_to_obj(readables)) + #start=to_list(start) + #end=to_list(end) + if type(steps) is float or is_list(steps): + steps = to_list(steps) + scan = LineScan(writables,readables, start, end , steps, relative, latency_ms, int(passes), zigzag) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + +def vscan(writables, readables, vector, line = False, latency=0.0, relative=False, passes=1, zigzag=False, **pars): + """Vector Scan: positioner values provided in a vector. + + Args: + writables(list of Writable): Positioners set on each step. + readables(list of Readable): Sensors to be sampled on each step. + vector (generator (floats or lists of float) or list of list of float): positioner values. + line (bool, optional): if true, processs as line scan (1d) + relative (bool, optional): if true, start and end positions are relative to current. + latency(float, optional): settling time for each step before readout, defaults to 0.0. + passes(int, optional): number of passes (disregarded if vector is a generator). + zigzag(bool, optional): if true writables invert direction on each pass (disregarded if vector is a generator). + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - before_read (function(positions, scan), optional): called on each step, before sampling. + - after_read (function(record, scan), optional): called on each step, after sampling. + - before_pass (function(pass_num, scan), optional): called before each pass. + - after_pass (function(pass_num, scan), optional): callback after each pass. + - settle_timeout(int, optional): timeout for each positioner get to position. Default (-1) waits forever. + - initial_move (bool, optional): if true (default) perform move to initial position prior to scan start. + - parallel_positioning (bool, optional): if true (default) all positioners are set in parallel. + - abort_on_error (bool, optional): if true then aborts scan in sensor failures. Default is false. + - restore_position (bool, optional): if true (default) then restore initial position after relative scans. + - check_positions (bool, optional): if true (default) verifies if in correct positions after move finishes. + - monitors (list of Device, optional): device values are saved on every change event during the scan. + - snaps (list of Readable, optional): snapshot device values are saved before the scan. + - diags (list of Readable, optional): diagnostic device values are saved at each scan point. + - meta (dict, optional): scan metadata. + - Aditional arguments defined by set_exec_pars. + + Returns: + ScanResult. + """ + latency_ms=int(latency*1000) + writables=to_list(string_to_obj(writables)) + readables=to_list(string_to_obj(readables)) + if type (vector) == PyGenerator: + scan = VectorScan(writables,readables, vector, line, relative, latency_ms) + else: + if len(vector) == 0: + vector.append([]) + elif (not is_list(vector[0])) and (not is_array(vector[0])): + vector = [[x,] for x in vector] + vector = to_array(vector, 'd') + scan = VectorScan(writables,readables, vector, line, relative, latency_ms, int(passes), zigzag) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + +def ascan(writables, readables, start, end, steps, latency=0.0, relative=False, passes=1, zigzag=False, **pars): + """Area Scan: multi-dimentional scan, each positioner is a dimention. + + Args: + writables(list of Writable): Positioners set on each step. + readables(list of Readable): Sensors to be sampled on each step. + start(list of float): start positions of writables. + end(list of float): final positions of writables. + steps(list of int or list of float): number of scan steps (int) or step size (float). + latency(float, optional): settling time for each step before readout, defaults to 0.0. + relative (bool, optional): if true, start and end positions are relative to current. + passes(int, optional): number of passes + zigzag (bool, optional): if true writables invert direction on each row. + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - before_read (function(positions, scan), optional): called on each step, before sampling. + - after_read (function(record, scan), optional): called on each step, after sampling. + - before_pass (function(pass_num, scan), optional): called before each pass. + - after_pass (function(pass_num, scan), optional): callback after each pass. + - settle_timeout(int, optional): timeout for each positioner get to position. Default (-1) waits forever. + - initial_move (bool, optional): if true (default) perform move to initial position prior to scan start. + - parallel_positioning (bool, optional): if true (default) all positioners are set in parallel. + - abort_on_error (bool, optional): if true then aborts scan in sensor failures. Default is false. + - restore_position (bool, optional): if true (default) then restore initial position after relative scans. + - check_positions (bool, optional): if true (default) verifies if in correct positions after move finishes. + - monitors (list of Device, optional): device values are saved on every change event during the scan. + - snaps (list of Readable, optional): snapshot device values are saved before the scan. + - diags (list of Readable, optional): diagnostic device values are saved at each scan point. + - meta (dict, optional): scan metadata. + - Aditional arguments defined by set_exec_pars. + + Returns: + ScanResult. + """ + latency_ms=int(latency*1000) + writables=to_list(string_to_obj(writables)) + readables=to_list(string_to_obj(readables)) + start=to_list(start) + end=to_list(end) + if is_list(steps): + steps = to_list(steps) + scan = AreaScan(writables,readables, start, end , steps, relative, latency_ms, int(passes), zigzag) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + + +def rscan(writable, readables, regions, latency=0.0, relative=False, passes=1, zigzag=False, **pars): + """Region Scan: positioner scanned linearly, from start to end positions, in multiple regions. + + Args: + writable(Writable): Positioner set on each step, for each region. + readables(list of Readable): Sensors to be sampled on each step. + regions (list of tuples (float,float, int) or (float,float, float)): each tuple define a scan region + (start, stop, steps) or (start, stop, step_size) + relative (bool, optional): if true, start and end positions are relative to current. + latency(float, optional): settling time for each step before readout, defaults to 0.0. + passes(int, optional): number of passes + zigzag(bool, optional): if true writable invert direction on each pass. + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - before_read (function(positions, scan), optional): called on each step, before sampling. + - after_read (function(record, scan), optional): called on each step, after sampling. + - before_pass (function(pass_num, scan), optional): called before each pass. + - after_pass (function(pass_num, scan), optional): callback after each pass. + - before_region (function(region_num, scan), optional): callback before entering a region. + - settle_timeout(int, optional): timeout for each positioner get to position. Default (-1) waits forever. + - initial_move (bool, optional): if true (default) perform move to initial position prior to scan start. + - parallel_positioning (bool, optional): if true (default) all positioners are set in parallel. + - abort_on_error (bool, optional): if true then aborts scan in sensor failures. Default is false. + - restore_position (bool, optional): if true (default) then restore initial position after relative scans. + - check_positions (bool, optional): if true (default) verifies if in correct positions after move finishes. + - monitors (list of Device, optional): device values are saved on every change event during the scan. + - snaps (list of Readable, optional): snapshot device values are saved before the scan. + - diags (list of Readable, optional): diagnostic device values are saved at each scan point. + - meta (dict, optional): scan metadata. + - Aditional arguments defined by set_exec_pars. + + Returns: + ScanResult. + """ + start=[] + end=[] + steps=[] + for region in regions: + start.append(region[0]) + end.append(region[1]) + steps.append(region[2]) + latency_ms=int(latency*1000) + writable=string_to_obj(writable) + readables=to_list(string_to_obj(readables)) + start=to_list(start) + end=to_list(end) + steps = to_list(steps) + scan = RegionScan(writable,readables, start, end , steps, relative, latency_ms, int(passes), zigzag) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + +def cscan(writables, readables, start, end, steps, latency=0.0, time=None, relative=False, passes=1, zigzag=False, **pars): + """Continuous Scan: positioner change continuously from start to end position and readables are sampled on the fly. + + Args: + writable(Speedable or list of Motor): A positioner with a getSpeed method or + a list of motors. + readables(list of Readable): Sensors to be sampled on each step. + start(float or list of float): start positions of writables. + end(float or list of float): final positions of writabless. + steps(int or float or list of float): number of scan steps (int) or step size (float). + latency(float, optional): sleep time in each step before readout, defaults to 0.0. + time (float, seconds): if not None then speeds are set according to time. + relative (bool, optional): if true, start and end positions are relative to current. + passes(int, optional): number of passes + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - before_read (function(positions, scan), optional): called on each step, before sampling. + - after_read (function(record, scan), optional): called on each step, after sampling. + - before_pass (function(pass_num, scan), optional): called before each pass. + - after_pass (function(pass_num, scan), optional): callback after each pass. + - abort_on_error (bool, optional): if true then aborts scan in sensor failures. Default is false. + - restore_position (bool, optional): if true (default) then restore initial position after relative scans. + - monitors (list of Device, optional): device values are saved on every change event during the scan. + - snaps (list of Readable, optional): snapshot device values are saved before the scan. + - diags (list of Readable, optional): diagnostic device values are saved at each scan point. + - meta (dict, optional): scan metadata. + - Aditional arguments defined by set_exec_pars. + + Returns: + ScanResult. + """ + latency_ms=int(latency*1000) + readables=to_list(string_to_obj(readables)) + writables=to_list(string_to_obj(writables)) + start=to_list(start) + end=to_list(end) + #A single Writable with fixed speed + if time is None: + if is_list(steps): steps=steps[0] + scan = ContinuousScan(writables[0],readables, start[0], end[0] , steps, relative, latency_ms, int(passes), zigzag) + #A set of Writables with speed configurable + else: + if type(steps) is float or is_list(steps): + steps = to_list(steps) + scan = ContinuousScan(writables,readables, start, end , steps, time, relative, latency_ms, int(passes), zigzag) + + processScanPars(scan, pars) + scan.start() + return scan.getResult() + +def hscan(config, writable, readables, start, end, steps, passes=1, zigzag=False, **pars): + """Hardware Scan: values sampled by external hardware and received asynchronously. + + Args: + config(dict): Configuration of the hardware scan. The "class" key provides the implementation class. + Other keys are implementation specific. + writable(Writable): A positioner appropriated to the hardware scan type. + readables(list of Readable): Sensors appropriated to the hardware scan type. + start(float): start positions of writable. + end(float): final positions of writables. + steps(int or float): number of scan steps (int) or step size (float). + passes(int, optional): number of passes + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - after_read (function(record, scan), optional): callback on each step, after sampling. + - before_pass (function(pass_num, scan), optional): callback before each scan pass execution. + - after_pass (function(pass_num, scan), optional): callback after each scan pass execution. + - abort_on_error (bool, optional): if true then aborts scan in sensor failures. Default is false. + - monitors (list of Device, optional): device values are saved on every change event during the scan. + - snaps (list of Readable, optional): snapshot device values are saved before the scan. + - meta (dict, optional): scan metadata. + + Returns: + ScanResult. + """ + cls = Class.forName(config["class"]) + class HardwareScan(cls): + def __init__(self, config, writable, readables, start, end, stepSize, passes, zigzag): + cls.__init__(self, config, writable, readables, start, end, stepSize, passes, zigzag) + def onAfterReadout(self, record): + __after_readout(self, record) + def onBeforePass(self, num_pass): + __before_pass(self, num_pass) + def onAfterPass(self, num_pass): + __after_pass(self, num_pass) + + readables=to_list(string_to_obj(readables)) + scan = HardwareScan(config, writable,readables, start, end , steps, int(passes), zigzag) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + +def bscan(stream, records, timeout = None, passes=1, **pars): + """BS Scan: records all values in a beam synchronous stream. + + Args: + stream(Stream): stream object or list of chanel names to build stream from + records(int): number of records to store + timeout(float, optional): maximum scan time in seconds. + passes(int, optional): number of passes + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - before_read (function(positions, scan), optional): called on each step, before sampling. + - after_read (function(record, scan), optional): called on each step, after sampling. + - before_pass (function(pass_num, scan), optional): called before each pass. + - after_pass (function(pass_num, scan), optional): callback after each pass. + - monitors (list of Device, optional): device values are saved on every change event during the scan. + - snaps (list of Readable, optional): snapshot device values are saved before the scan. + - diags (list of Readable, optional): diagnostic device values are saved at each scan point. + - meta (dict, optional): scan metadata. + - Aditional arguments defined by set_exec_pars. + + Returns: + ScanResult. + """ + timeout_ms=int(timeout*1000) if ((timeout is not None) and (timeout>=0)) else -1 + if not is_list(stream): + stream=string_to_obj(stream) + scan = BsScan(stream,int(records), timeout_ms, int(passes)) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + +def tscan(readables, points, interval, passes=1, fixed_rate=True, **pars): + """Time Scan: sensors are sampled in fixed time intervals. + + Args: + readables(list of Readable): Sensors to be sampled on each step. + points(int): number of samples. + interval(float): time interval between readouts. Minimum temporization is 0.001s + passes(int, optional): number of passes + fixed_rate(bool, optional): in the case of delays in sampling: + If True tries to preserve to total scan time, accelerating following sampling. + If False preserves the interval between samples, increasing scan time. + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - before_read (function(positions, scan), optional): called on each step, before sampling. + - after_read (function(record, scan), optional): called on each step, after sampling. + - before_pass (function(pass_num, scan), optional): called before each pass. + - after_pass (function(pass_num, scan), optional): callback after each pass. + - abort_on_error (bool, optional): if true then aborts scan in sensor failures. Default is false. + - monitors (list of Device, optional): device values are saved on every change event during the scan. + - snaps (list of Readable, optional): snapshot device values are saved before the scan. + - diags (list of Readable, optional): diagnostic device values are saved at each scan point. + - meta (dict, optional): scan metadata. + - Aditional arguments defined by set_exec_pars. + + Returns: + ScanResult. + """ + interval= max(interval, 0.001) #Minimum temporization is 1ms + interval_ms=int(interval*1000) + readables=to_list(string_to_obj(readables)) + scan = TimeScan(readables, points, interval_ms, int(passes), bool(fixed_rate)) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + +def mscan(trigger, readables, points=-1, timeout=None, asynchronous=True, take_initial=False, passes=1, **pars): + """Monitor Scan: sensors are sampled when received change event of the trigger device. + + Args: + trigger(Device or list of Device): Source of the sampling triggering. + readables(list of Readable): Sensors to be sampled on each step. + If trigger has cache and is included in readables, it is not read + for each step, but the change event value is used. + points(int, optional): number of samples (-1 for undefined). + timeout(float, optional): maximum scan time in seconds (None for no timeout). + asynchronous(bool, optional): if True then records are sampled and stored on event change callback. Enforce + reading only cached values of sensors. + If False, the scan execution loop waits for trigger cache update. Do not make + cache only access, but may loose change events. + take_initial(bool, optional): if True include current values as first record (before first trigger). + passes(int, optional): number of passes + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - before_read (function(positions, scan), optional): called on each step, before sampling. + - after_read (function(record, scan), optional): called on each step, after sampling. + - before_pass (function(pass_num, scan), optional): called before each pass. + - after_pass (function(pass_num, scan), optional): callback after each pass. + - abort_on_error (bool, optional): if true then aborts scan in sensor failures. Default is false. + - monitors (list of Device, optional): device values are saved on every change event during the scan. + - snaps (list of Readable, optional): snapshot device values are saved before the scan. + - diags (list of Readable, optional): diagnostic device values are saved at each scan point. + - meta (dict, optional): scan metadata. + - Aditional arguments defined by set_exec_pars. + + Returns: + ScanResult. + """ + timeout_ms=int(timeout*1000) if ((timeout is not None) and (timeout>=0)) else -1 + trigger = string_to_obj(trigger) + readables=to_list(string_to_obj(readables)) + scan = MonitorScan(trigger, readables, points, timeout_ms, asynchronous, take_initial, int(passes)) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + +def escan(name, **pars): + """Epics Scan: execute an Epics Scan Record. + + Args: + name(str): Name of scan record. + title(str, optional): plotting window name. + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - Aditional arguments defined by set_exec_pars. + + Returns: + ScanResult. + """ + scan = EpicsScan(name) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + + +def bsearch(writables, readable, start, end, steps, maximum = True, strategy = "Normal", latency=0.0, relative=False, **pars): + """Binary search: searches writables in a binary search fashion to find a local maximum for the readable. + + Args: + writables(list of Writable): Positioners set on each step. + readable(Readable): Sensor to be sampled. + start(list of float): start positions of writables. + end(list of float): final positions of writables. + steps(float or list of float): resolution of search for each writable. + maximum (bool , optional): if True (default) search maximum, otherwise minimum. + strategy (str , optional): "Normal": starts search midway to scan range and advance in the best direction. + Uses orthogonal neighborhood (4-neighborhood for 2d) + "Boundary": starts search on scan range. + "FullNeighborhood": Uses complete neighborhood (8-neighborhood for 2d) + + latency(float, optional): settling time for each step before readout, defaults to 0.0. + relative (bool, optional): if true, start and end positions are relative to current. + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - before_read (function(positions, scan), optional): called on each step, before sampling. + - after_read (function(record, scan), optional): called on each step, after sampling. + - settle_timeout(int, optional): timeout for each positioner get to position. Default (-1) waits forever. + - parallel_positioning (bool, optional): if true (default) all positioners are set in parallel. + - abort_on_error (bool, optional): if true then aborts scan in sensor failures. Default is false. + - restore_position (bool, optional): if true (default) then restore initial position after relative scans. + - check_positions (bool, optional): if true (default) verifies if in correct positions after move finishes. + - Aditional arguments defined by set_exec_pars. + + Returns: + SearchResult. + """ + latency_ms=int(latency*1000) + writables=to_list(string_to_obj(writables)) + readable=string_to_obj(readable) + start=to_list(start) + end=to_list(end) + steps = to_list(steps) + strategy = BinarySearch.Strategy.valueOf(strategy) + scan = BinarySearch(writables,readable, start, end , steps, maximum, strategy, relative, latency_ms) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + +def hsearch(writables, readable, range_min, range_max, initial_step, resolution, filter=1, maximum=True, latency=0.0, relative=False, **pars): + """Hill Climbing search: searches writables in decreasing steps to find a local maximum for the readable. + Args: + writables(list of Writable): Positioners set on each step. + readable(Readable): Sensor to be sampled. + range_min(list of float): minimum positions of writables. + range_max(list of float): maximum positions of writables. + initial_step(float or list of float):initial step size for for each writable. + resolution(float or list of float): resolution of search for each writable (minimum step size). + filter(int): number of aditional steps to filter noise + maximum (bool , optional): if True (default) search maximum, otherwise minimum. + latency(float, optional): settling time for each step before readout, defaults to 0.0. + relative (bool, optional): if true, start and end positions are relative to current. + pars(keyworded variable length arguments, optional): scan optional named arguments: + - title(str, optional): plotting window name. + - before_read (function(positions, scan), optional): called on each step, before sampling. + - after_read (function(record, scan), optional): called on each step, after sampling. + - settle_timeout(int, optional): timeout for each positioner get to position. Default (-1) waits forever. + - parallel_positioning (bool, optional): if true (default) all positioners are set in parallel. + - abort_on_error (bool, optional): if true then aborts scan in sensor failures. Default is false. + - restore_position (bool, optional): if true (default) then restore initial position after relative scans. + - check_positions (bool, optional): if true (default) verifies if in correct positions after move finishes. + - Aditional arguments defined by set_exec_pars. + + Returns: + SearchResult. + """ + latency_ms=int(latency*1000) + writables=to_list(string_to_obj(writables)) + readable=string_to_obj(readable) + range_min=to_list(range_min) + range_max=to_list(range_max) + initial_step = to_list(initial_step) + resolution = to_list(resolution) + scan = HillClimbingSearch(writables,readable, range_min, range_max , initial_step, resolution, filter, maximum, relative, latency_ms) + processScanPars(scan, pars) + scan.start() + return scan.getResult() + + +################################################################################################### +#Data plotting +################################################################################################### + +def plot(data, name = None, xdata = None, ydata=None, title=None): + """Request one or multiple plots of user data (1d, 2d or 3d). + + Args: + data: array or list of values. For multiple plots, list of arrays. + name(str or list of str, optional): plot name. For multiple plots, list of names. + xdata: array or list of values. For multiple plots, list of arrays. + ydata: array or list of values. For multiple plots, list of arrays. + title(str, optional): plotting window name. + + Returns: + ArrayList of Plot. + """ + data = json_to_obj(data) + xdata = json_to_obj(xdata) + ydata = json_to_obj(ydata) + if is_java_instance(data, Table): + if is_list(xdata): + xdata = to_array(xdata, 'd') + return get_context().plot(data,xdata,name,title) + + if is_java_instance(data, ScanResult): + return get_context().plot(data,title) + + if (name is not None) and is_list(name): + if len(name)==0: + name=None; + else: + if (data==None): + data = [] + for n in name: + data.append([]) + plots = reflect.Array.newInstance(Class.forName("ch.psi.pshell.data.PlotDescriptor"), len(data)) + for i in range (len(data)): + plotName = None if (name is None) else name[i] + x = xdata + if is_list(x) and len(x)>0 and (is_list(x[i]) or is_java_instance(x[i] , List) or is_array(x[i])): + x = x[i] + y = ydata + if is_list(y) and len(y)>0 and (is_list(y[i]) or is_java_instance(y[i] , List) or is_array(y[i])): + y = y[i] + plots[i] = PlotDescriptor(plotName , to_array(data[i], 'd'), to_array(x, 'd'), to_array(y, 'd')) + return get_context().plot(plots,title) + else: + plot = PlotDescriptor(name, to_array(data, 'd'), to_array(xdata, 'd'), to_array(ydata, 'd')) + return get_context().plot(plot,title) + +def get_plots(title=None): + """Return all current plots in the plotting window given by 'title'. + + Args: + title(str, optional): plotting window name. + + Returns: + ArrayList of Plot. + """ + return get_context().getPlots(title) + +def get_plot_snapshots(title = None, file_type = "png", size = None, temp_path = get_context().getSetup().getContextPath()): + """Returns list with file names of plots snapshots from a plotting context. + + Args: + title(str, optional): plotting window name. + file_type(str, optional): "png", "jpg", "bmp" or "gif" + size(array, optional): [width, height] + temp_path(str, optional): path where the files will be generated. + + Returns: + list of strings + """ + time.sleep(0.1) #Give some time to plot to be finished - it is not sync with acquisition + ret = [] + if size != None: + size = Dimension(size[0], size[1]) + plots = get_plots(title) + for i in range(len(plots)): + p = plots[i] + name = p.getTitle() + if name is None or name == "": + name = str(i) + file_name = os.path.abspath(temp_path + "/" + name + "." + file_type) + p.saveSnapshot(file_name , file_type, size) + ret.append(file_name) + return ret + + +################################################################################################### +#Data access +################################################################################################### + +def load_data(path, index=0, shape=None, root=None): + """Read data from the current persistence context or from data files. + + Args: + path(str): Path to group or dataset relative to the root. + If path is in the format 'root|path', or else if 'root' is defined, then + reads from data file given by root. Otherwise uses current data persistence file. + root(str, optional): data file. + index(int or list, optional): + if integer, data depth (used for 3D datasets returning a 2d matrix) + If a list, specifies the full coordinate for multidimensional datasets. + shape(list, optional): only valid if index is a list, provides the shape of the data array. + In this case return a flattened a one-dimensional array. + + Returns: + Data array + """ + dm=get_context().getDataManager() + if index is not None and is_list(index): + slice = dm.getData(path, index, shape) if (root==None) else dm.getData(root, path, index, shape) + else: + slice = dm.getData(path, index) if (root==None) else dm.getData(root, path, index) + return slice.sliceData + +def get_attributes(path, root=None): + """Get the attributes from group or dataset. + + Args: + path(str): Path to group or dataset relative to the root. + If path is in the format 'root|path', or else if 'root' is defined, then + reads from data file given by root. Otherwise uses current data persistence file. + root(str, optional): data file. + Returns: + Dictionary + """ + if (root is None): + return get_context().getDataManager().getAttributes(path) + return get_context().getDataManager().getAttributes(root, path) + +def get_data_info(path, root=None): + """Get information about the group or dataset. + + Args: + path(str): Path to group or dataset relative to the current persistence context root. + If path is in the format 'root|path', or else if 'root' is defined, then + reads from data file given by root. Otherwise uses current data persistence file. + root(str, optional): data file. + Returns: + Dictionary + """ + if (root is None): + return get_context().getDataManager().getInfo(path) + return get_context().getDataManager().getInfo(root, path) + +def save_dataset(path, data, type='d', unsigned=False, features=None): + """Save data into a dataset within the current persistence context. + + Args: + path(str): Path to dataset relative to the current persistence context root. + type(str, optional): array type - 'd'=double (default), 'b'=byte, 'h'=short, 'i'=int, + 'l'=long, 'f'=float, 'c'=char, 's'=String, 'z'=bool, 'o'=Object + data (array or list): data to be saved + unsigned(boolean, optional): create a dataset of unsigned type. + features(dictionary, optional): See create_dataset. + + Returns: + Dictionary + """ + data = to_array(data, type) + get_context().getDataManager().setDataset(path, data, unsigned, features) + +def create_group(path): + """Create an empty dataset within the current persistence context. + + Args: + path(str): Path to group relative to the current persistence context root. + Returns: + None + """ + get_context().getDataManager().createGroup(path) + +def create_dataset(path, type, unsigned=False, dimensions=None, features=None): + """Create an empty dataset within the current persistence context. + + Args: + path(str): Path to dataset relative to the current persistence context root. + type(str): array type 'b' = byte, 'h' = short, 'i' = int, 'l' = long, 'f' = float, + 'd' = double, 'c' = char, 's' = String, 'z'=bool, 'o' = Object + unsigned(boolean, optional) + dimensions(tuple of int, optional): a 0 value means variable length in that dimension. + features(dictionary, optional): storage features for the dataset, format specific. + Keys for HDF5: "layout": "compact", "contiguous" or "chunked" + "compression": True, "max" or deflation level from 1 to 9 + "shuffle": Byte shuffle before compressing. + "chunk": tuple, setting the chunk size + Default: No compression, contiguous for fixed size arrays, chunked for variable size, compact for scalars. + Returns: + None + """ + get_context().getDataManager().createDataset(path, ScriptUtils.getType(type), unsigned, dimensions, features) + +def create_table(path, names, types=None, lengths=None, features=None): + """Create an empty table (dataset of compound type) within the current persistence context. + + Args: + path(str): Path to dataset relative to the current persistence context root. + names(list of strings): name of each column + types(array of str): 'b' = byte, 'h' = short, 'i' = int, 'l' = long, 'f' = float, + 'd' = double, 'c' = char, 's' = String, 'o' = Object + Note:A '[' prefix on type name indicates an array type. + lengths(list of int): the array length for each columns(0 for scalar types). + features(dictionary, optional): See create_dataset. + Returns: + None + """ + type_classes = [] + if (types is not None): + for i in range (len(types)): + type_classes.append(ScriptUtils.getType(types[i])) + get_context().getDataManager().createDataset(path, names, type_classes, lengths, features) + +def append_dataset(path, data, index=None, type='d', shape=None): + """Append data to dataset. + + Args: + path(str): Path to dataset relative to the current persistence context root. + data(number or array or list): name of each column. + index(int or list, optional): if set then add the data in a specific position in the dataset. + If integer is the index in an array (data must be 1 order lower than dataset) + If a list, specifies the full coordinate for multidimensional datasets. + type(str, optional): array type 'b' = byte, 'h' = short, 'i' = int, 'l' = long, 'f' = float, + 'd' = double, 'c' = char, 's' = String, 'o' = Object + default: 'd' (convert data to array of doubles) + shape(list, optional): only valid if index is a list, provides the shape of the data array. + In this case data must be a flattened one-dimensional array. + Returns: + None + """ + data = to_array(data, type) + if index is None: + get_context().getDataManager().appendItem(path, data) + else: + if is_list(index): + if shape is None: + shape = [len(index)] + get_context().getDataManager().setItem(path, data, index, shape) + else: + get_context().getDataManager().setItem(path, data, index) + +def append_table(path, data): + """Append data to a table (dataset of compound type) + + Args: + path(str): Path to dataset relative to the current persistence context root. + data(list): List of valus for each column of the table. + Returns: + None + """ + if is_list(data): + arr = reflect.Array.newInstance(Class.forName("java.lang.Object"),len(data)) + for i in range (len(data)): + if is_list(data[i]): + arr[i] = to_array(data[i], 'd') + else: + arr[i] = data[i] + data=arr + get_context().getDataManager().appendItem(path, data) + +def flush_data(): + """Flush all data files immediately. + + Args: + None + Returns: + None + """ + get_context().getDataManager().flush() + +def set_attribute(path, name, value, unsigned = False): + """Set an attribute to a group or dataset. + + Args: + path(str): Path to dataset relative to the current persistence context root. + name(str): name of the atttribute + value(Object): the attribute value + unsigned(bool, optional): if applies, indicate if value is unsigned. + Returns: + None + """ + if is_list(value): + value = Convert.toStringArray(to_array(value)) + get_context().getDataManager().setAttribute(path, name, value, unsigned) + +def log(log, data_file=None): + """Writes a log to the system log and data context - if there is an ongoing scan or script execution. + + Args: + log(str): Log string. + data_file(bool, optional): if true logs to the data file, in addiction to the system logger. + If None(default) appends to data file only if it exists. + + Returns: + None + """ + get_context().scriptingLog(str(log)) + if data_file is None: + data_file = get_exec_pars().open + if data_file: + try: + get_context().getDataManager().appendLog(str(log)) + except: + #Do not generate exception if cannot write to data file + pass + +def set_exec_pars(**args): + """ Configures the script execution parameters, overriding the system configuration. + + Args: + args(optional arguments): + name(str): value of the {name} tag. Default is the running script name. + type(str): value of the {type} tag. Default is empty. + This field can be used to store data in sub-folders of standard location. + path(str): If defined provides the full path name for data output root (overriding config)) + The tag {data} can be used to enter a path relative to the standard data folder. + layout(str): Change data layout. + format(str): Change data format. + split(scan or True): Split scan data to another table. If set to True in scan command then split every pass. + depth_dim(int): dimension of 2d-matrixes in 3d datasets. + save(bool): Change option to auto save scan data. + flush(bool): Change option to flush file on each record. + keep(bool): Change option keep scan records in memory. If false do not add records to scan result. + preserve(bool): Change option to preserve device types. If false all values are converted to double. + setpoints(bool): Save the positioner setpoints too. + verbose(bool): Enable options to save additional information (output, script). + compression(obj): True for enabling default compression, int for specifying deflation level. + Device or list of devices for specifying devices to be compressed. + shuffle(obj): True for enabling shuffling before compression. + Device or list of devices for specifying devices to be shuffled. + contiguous(obj): True for setting contiguous datasets for all devices. + Device or list of devices for specifying device datasets to be contiguous. + seq(int): Set next data file sequence number. + open(bool): If true create data output path immediately. If false closes output root, if open. + reset(bool): If true reset the scan counter - the {count} tag and set the timestamp to now. + group(str): Change layout group name for scans + tag(str): Change tag for scan names (affecting group or dataset name, according to layout) + then, then_success, then_exception(str): Sets statement to be executed on the completion of current. + defaults(bool): If true restore the original execution parameters. + + Graphical preferences: + line_plots(list): list of devices with enforced line plots. + range(str or list): "none", "auto", [min_x, max_x] or [min_x, max_x, min_y, max_y] + display(bool): if false disables scan data plotting and printing. + print_scan(bool): Enable/disables scan data printing to console. + plot_disabled(bool): Enable/disable scan plot + plot_layout (str):"Horizontal", "Vertical" or "Grid" + table_disabled(bool): Enable/disable scan table + enabled_plots (list of str or Readable): list of devices (Readables) to be plotted + plot_types(dict): Dictionary - Plot name(Readable or String) : Plot type(String or int) + auto_range(bool): If true automatic range scan plots x-axis. + manual_range(tuple): : Set range (min_x, max_x) or (min_x, max_x, min_y, max_y). None sets fixed range. + manual_range_y(tuple): Set y range (min_y, max_y). None sets fixed range. + domain_axis(str): Set the domain axis source: "Time", "Index", or a readable name. Default: first positioner. + status(str): set application status + """ + get_context().setExecutionPars(args) + +def get_exec_pars(): + """ Returns script execution parameters. + + Returns: + ExecutionParameters object. Fields: + name (str): execution name - {name} tag. + type (str): execution type - {type} tag. + path (str): output data root. + seq(int): data file sequence number. + open (bool): true if the output data root has been opened. + layout (str): data output layout. If None then using the configuration. + save (bool): auto save scan data option. + flush (bool): flush file on each record. + index (int): current scan index. + group (str): data group currently used for scan data storage. + if no ongoing scan return "/" if within a script, or else None if a console command. + scanPath (str): dataset or group corresponding to current scan. + scan (Scan): reference to current scan, if any + source (CommandSource): return the source of the script or command. + background (bool): return False if executing in main interpreter thread . + debug (bool): True if executing from statements in editor. + simulation (bool): global simulation flag. + aborted (bool): True if execution has been aborted + """ + return get_context().getExecutionPars() + + +################################################################################################### +#EPICS +################################################################################################### + +def _adjust_channel_value(value, var_type=None): + if (value is None): + return value + if (var_type is not None): + if is_list(value): + var_type = var_type.replace(',','').replace('[','') + ret = [] + for item in value: + ret.append(_adjust_channel_value(item), var_type) + value = ret + else: + var_type = var_type.lower() + if var_type=='b': + value = byte(value) + elif var_type=='i': + value = short(value) + elif var_type=='l': + value = int(value) + elif var_type=='f': + value = float(value) + elif var_type=='d': + value = float(value) + elif var_type=='s': + value = str(value) + + if isinstance(value,tuple): + value = list(value) + if isinstance(value,list): + list_type = type(value[0]) + array_types = { + int: "i", + long: "l", + float:"d", + str:Class.forName("java.lang.String"), + } + array_type = array_types.get(type(value[0]),'d') + array = PyArray(array_type) + array.fromlist(value) + value=array + return value + +def caget(name, type=None, size=None, meta = False ): + """Reads an Epics PV. + + Args: + name(str): PV name + type(str, optional): type of PV. By default gets the PV standard field type. + Scalar values: 'b', 'i', 'l', 'd', 's'. + Array values: '[b', '[i,', '[l', '[d', '[s'. + size (int, optional): for arrays, number of elements to be read. Default read all. + meta (bool, optional): if true gets channel value and metadata (timestamp, severity). + + Returns: + PV value if meta is false, otherwise a dictionary containing PV value and metadata + """ + if meta: + return Epics.getMeta(name, Epics.getChannelType(type), size) + return Epics.get(name, Epics.getChannelType(type), size) + +def cawait(name, value, timeout=None, comparator=None, type=None, size=None): + """Wait for a PV to have a given value. + + Args: + name(str): PV name + value (obj): value to compare to + timeout(float, optional): time in seconds to wait. If None, waits forever. + comparator(java.util.Comparator or float, optional): if None waits for equality. + If a numeric value is provided, waits for channel to be in range. + type(str, optional): type of PV. By default gets the PV standard field type. + Scalar values: 'b', 'i', 'l', 'd', 's'. + Array values: '[b', '[i,', '[l', '[d', '[s'. + size (int, optional): for arrays, number of elements to be read. Default read all. + + Returns: + None + """ + if (timeout is not None): + timeout = int(timeout*1000) + value = _adjust_channel_value(value) + Epics.waitValue(name, value, comparator, timeout, Epics.getChannelType(type), size) + +def caput(name, value, timeout = None): + """Writes to an Epics PV. + + Args: + name(str): PV name + value(scalar, string or array): new PV value. + timeout(int, optional): timeout in seconds to the write. If None waits forever to completion. + + Returns: + None + """ + value=_adjust_channel_value(value) + if (timeout is not None): + timeout = int(timeout*1000) + return Epics.put(name, value, timeout) + +def caputq(name, value): + """Writes to an Epics PV and does not wait. + + Args: + name(str): PV name + value(scalar, string or array): new PV value. + + Returns: + None + """ + value=_adjust_channel_value(value) + return Epics.putq(name, value) + +def camon(name, type=None, size=None, wait = sys.maxsize): + """Install a monitor to an Epics PV and print value changes. + + Args: + name(str): PV name + type(str, optional): type of PV. By default gets the PV standard field type. + Scalar values: 'b', 'i', 'l', 'd', 's'. + Array values: '[b', '[i,', '[l', '[d', '[s'. + size (int, optional): for arrays, number of elements to be read. Default read all. + wait (int, optional): blocking time for this function. By default blocks forever. + Returns: + None + """ + val = lambda x: x.tolist() if is_array(x) else x + + class MonitorListener(PropertyChangeListener): + def propertyChange(self, pce): + print (val(pce.getNewValue())) + + channel = create_channel(name, type, size) + print (val(channel.getValue())) + channel.setMonitored(True) + channel.addPropertyChangeListener(MonitorListener()) + + try: + time.sleep(wait) + finally: + Epics.closeChannel(channel) + +def create_channel_device(channel_name, type=None, size=None, device_name=None, monitored=False): + """Create a device from an EPICS PV. + + Args: + channel_name(str): PV name + type(str, optional): type of PV. By default gets the PV standard field type. + Scalar values: 'b', 'i', 'l', 'd', 's'. + Array values: '[b', '[i,', '[l', '[d', '[s'. + size (int, optional): for arrays, number of elements to be read. Default read all. + device_name (str, optional): device name (if different from hannel_name. + Returns: + None + """ + dev = Epics.newChannelDevice(channel_name if (device_name is None) else device_name , channel_name, Epics.getChannelType(type)) + if get_context().isSimulation(): + dev.setSimulated() + dev.initialize() + if (size is not None): + dev.setSize(size) + if (monitored): + dev.setMonitored(True) + return dev + + +################################################################################################### +#Concurrent execution +################################################################################################### +#TODO +""" +class Callable(concurrent.Callable): + def __init__(self, method, *args): + self.method = method + self.args = args + self.thread = Thread.currentThread() + def call(self): + try: + get_context().startedChildThread(self.thread) + return self.method(*self.args) + finally: + get_context().finishedChildThread(self.thread) +""" +def fork(*functions): + """Start execution of functions in parallel. + + Args: + *functions(function references) + + Returns: + List of callable + """ + callables = [] + for m in functions: + if is_list(m): + #callables.append(Callable(m[0],*m[1])) + callables.append(concurrent.Callable(m[0],*m[1])) + else: + #callables.append(Callable(m)) + callables.append(concurrent.Callable(m)) + return Threading.fork(callables) + +def join(futures): + """Wait parallel execution of functions. + + Args: + futures(Future or list of Future) : as returned from fork + + Returns: + None +""" + try: + futures=to_list(futures) + return Threading.join(futures) + except java.util.concurrent.ExecutionException as ex: + raise ex.getCause() + +def parallelize(*functions): + """Equivalent to fork + join + + Args: + *functions(function references) + + Returns: + None + """ + futures = fork(*functions) + return join(futures) + +def invoke(f, wait = False): + """ Execute in event thread. + + Args: + f(function reference) + wait (boolean, optional) + """ + if is_list(f): [m, a] = f; f = lambda: m(*a) + invokeAndWait(f) if wait else invokeLater(f) + + +################################################################################################### +#Background task control. +################################################################################################### + +def start_task(script, delay = 0.0, interval = -1): + """Start a background task + + Args: + script(str): Name of the script implementing the task + delay(float, optional): time in seconds for the first execution. + Default starts immediately. + interval(float, optional): time in seconds for between execution. + If negative (default), single-execution. + + Returns: + Task object. + """ + delay_ms=int(delay*1000) + interval_ms=int(interval*1000) if (interval>=0) else int(interval) + return get_context().startTask(script, delay_ms, interval_ms) + +def stop_task(script, force = False): + """Stop a background task + + Args: + script(str): Name of the script implementing the task + force(boolean, optional): interrupt current execution, if running + + Returns: + None + """ + get_context().stopTask(script, force) + + +################################################################################################### +#Versioning +################################################################################################### + +def commit(message, force = False): + """Commit the changes to the repository. + + Args: + message(str): commit message + force(bool, optional): if False, raises exception if no change detected in repo + + Returns: + None + """ + get_context().commit(message, force) + +def diff(): + """Return list of changes in the repository + + Args: + None + + Returns: + None + """ + return get_context().diff() + +def checkout_tag(tag): + """Checkout a tag name. + + Args: + tag(str): tag name. + + Returns: + None + """ + get_context().checkoutTag(tag) + +def checkout_branch(tag): + """Checkout a local branch name. + + Args: + tag(str): branch name. + + Returns: + None + """ + get_context().checkoutLocalBranch(tag) + +def pull_repository(): + """Pull from remote repository. + + """ + get_context().pullFromUpstream() + +def push_repository(all_branches=True, force=False, push_tags=False): + """Push to remote repository. + + Args: + all_branches(boolean, optional): all branches or just current. + force(boolean, optional): force flag. + push_tags(boolean, optional): push tags. + + Returns: + None + """ + get_context().pushToUpstream(all_branches, force, push_tags) + +def cleanup_repository(): + """Performs a repository cleanup. + + Args: + None + + Returns: + None + """ + get_context().cleanupRepository() + +################################################################################################### +#Device Pool +################################################################################################### + +def get_device(device_name): + """Returns a configured device (or imaging source) by its name. + + Args: + device_name(str): name of the device. + + Returns: + device + """ + return get_context().getDevicePool().getByName(device_name) + +def add_device(device, force = False): + """Add a device (or imaging source) to the device pool. + + Args: + device(Device or Source) + force(boolean, optional): if true then dispose existing device with same name. + Otherwise will fail in case of name clash. + + Returns: + True if device was added, false if was already in the pool, or exception in case of name clash. + """ + return get_context().getDevicePool().addDevice(device, force, True) + +def remove_device(device): + """Remove a device (or imaging source) from the device pool. + + Args: + device(Device or Source) + + Returns: + bool: true if device was removed. + """ + device=string_to_obj(device) + return get_context().getDevicePool().removeDevice(device) + +def set_device_alias(device, alias): + """Deprecated, use "dev.set_alias" instead. Set a device alias to be used in scans (datasets and plots). + + Args: + device(Device) + alias(str): replace device name in scans. + + Returns: + None + """ + device=string_to_obj(device) + device.setAlias(alias) + +def stop(): + """Stop all devices implementing the Stoppable interface. + + Args: + None + + Returns: + None + """ + get_context().stopAll() + +def update(): + """Update all devices. + + Args: + None + + Returns: + None + """ + get_context().updateAll() + +def reinit(dev = None): + """Re-initialize devices. + + Args: + dev(Device, optional): Device to be re-initialized (if None, all devices not yet initialized) + + Returns: + List with devices not initialized. + """ + if dev is not None: + dev=string_to_obj(dev) + return get_context().reinit(dev) + return to_list(get_context().reinit()) + +def create_device(url, parent=None): + """Create a device form a definition string(see InlineDevice) + + Args: + url(str or list of string): the device definition string (or list of strings) + parent(bool, optional): parent device + + Returns: + The created device (or list of devices) + """ + if parent is not None: + parent=string_to_obj(parent) + return InlineDevice.create(url, parent) + + +def create_averager(dev, count, interval=0.0, name = None, monitored = False): + """Creates and initializes and averager for dev. + + Args: + dev(Device): the source device + count(int): number of samples + interval(float, optional): sampling interval(s). If negative sampling is made on data change event. + name(str, optional): sets the name of the device (default is: averager) + monitored (bool, optional): if true then averager processes asynchronously. + + Returns: + Averager device + """ + dev = string_to_obj(dev) + if is_java_instance(dev, ReadableArray): + av = ArrayAverager(dev, count, int(interval*1000)) if (name is None) else ArrayAverager(name, dev, count, int(interval*1000)) + else: + av = Averager(dev, count, int(interval*1000)) if (name is None) else Averager(name, dev, count, int(interval*1000)) + av.initialize() + if (monitored): + av.monitored = True + return av + +def tweak(dev, step, is2d=False): + """Move one or more positioners in steps using the arrow keys. + Steps are increased/decreased using the shift and control keys. + + Args: + dev(Positioner or List): the device or list of devices to move. + step(float or List): step size or list of step sizes + is2d(bool, optional): if true moves second motor with up/down arrows. + """ + if (get_exec_pars().isBackground()): return + dev,step = to_list(string_to_obj(dev)),to_list(step) + while (True): + key=get_context().waitKey(0) + for i in range(len(dev)): + if not is2d or i==0: + if key == 0x25: dev[i].moveRel(-step[i]) #Left + elif key == 0x27: dev[i].moveRel(step[i]) #Right + if key in (0x10, 0x11): + step[i] = step[i]*2 if key == 0x10 else step[i]/2 + print ("Tweak step for " + dev[i].getName() + " set to: "+str(step[i])) + if is2d and len(dev)>1: + if key == 0x26: dev[1].moveRel(step[1]) #Top + elif key == 0x28: dev[1].moveRel(-step[1]) #Bottom + + +################################################################################################### +#Maths +################################################################################################### + +def arrmul(a, b): + """Multiply 2 series of the same size. + + Args: + + a(subscriptable) + b(subscriptable) + + Returns: + List + """ + return map(mul, a, b) + +def arrdiv(a, b): + """Divide 2 series of the same size. + + Args: + + a(subscriptable) + b(subscriptable) + + Returns: + List + """ + return map(truediv, a, b) + +def arradd(a, b): + """Add 2 series of the same size. + + Args: + + a(subscriptable) + b(subscriptable) + + Returns: + List + """ + return map(add, a, b) + +def arrsub(a, b): + """Subtract 2 series of the same size. + + Args: + + a(subscriptable) + b(subscriptable) + + Returns: + List + """ + return map(sub, a, b) + +def arrabs(a): + """Returns the absolute of all elements in series. + + Args: + + a(subscriptable) + + Returns: + List + """ + return map(abs, a) + +def arroff(a, value = "mean"): + """Subtract offset to all elemets in series. + + Args: + + a(subscriptable) + type(int or str, optional): value to subtract from the array, or "mean" or "min". + + Returns: + List + """ + if value=="mean": + value = mean(a) + elif value=="min": + value = min(a) + return [x-value for x in a] + +def mean(data): + """Calculate the mean of a sequence. + + Args: + data(subscriptable) + + Returns: + Mean of the elements in the object. + """ + return reduce(lambda x, y: x + y, data) / len(data) + +def variance(data): + """Calculate the variance of a sequence. + + Args: + data(subscriptable) + + Returns: + Variance of the elements in the object. + """ + c = mean(data) + ss = sum((x-c)**2 for x in data) + return ss/len(data) + +def stdev(data): + """Calculate the standard deviation of a sequence. + + Args: + data(subscriptable) + + Returns: + Standard deviation of the elements in the object. + """ + return variance(data)**0.5 + + +def center_of_mass(data, x = None): + """Calculate the center of mass of a series, and its rms. + + Args: + + data(subscriptable) + x(list, tuple, array ..., optional): x coordinates + + Returns: + Tuple (com, rms) + """ + if x is None: + x = Arr.indexesDouble(len(data)) + data_sum = sum(data) + if (data_sum==0): + return float('nan') + xmd = arrmul( x, data) + com = sum(xmd) / data_sum + xmd2 = arrmul( x, xmd) + com2 = sum(xmd2) / data_sum + rms = math.sqrt(abs(com2 - com * com)) + return (com, rms) + +def poly(val, coefs): + """Evaluates a polinomial: (coefs[0] + coefs[1]*val + coefs[2]*val^2... + + Args: + val(float): value + coefs (list of loats): polinomial coefficients + Returns: + Evaluated function for val + """ + r = 0 + p = 0 + for c in coefs: + r = r + c * math.pow(val, p) + p = p + 1 + return r + +def histogram(data, range_min = None, range_max = None, bin = 1.0): + """Creates histogram on data. + + Args: + data (tuple, array, ArrayList or Array): input data can be multi-dimensional or nested. + range_min (int, optional): minimum histogram value. Default is floor(min(data)) + range_max (int, optional): maximul histogram value. Default is ceil(max(data)) + bin(int or float, optional): if int means number of bins. If float means bin size. Default = 1.0. + Returns: + tuple: (ydata, xdata) + """ + if range_min is None: range_min = math.floor(min(flatten(data))) + if range_max is None: range_max = math.ceil(max(flatten(data))) + if type(bin) is float: + bin_size = bin + n_bin = int(math.ceil(float(range_max - range_min)/bin_size)) + else: + n_bin = bin + bin_size = float(range_max - range_min)/bin + + result = [0] * n_bin + for d in flatten(data): + b = int( float(d - range_min) / bin_size) + if (b >=0) and (b < n_bin): + result[b] = result[b] + 1 + return (result, frange(range_min, range_max, bin_size)) + +def _turn(p, q, r): + return cmp((q[0] - p[0])*(r[1] - p[1]) - (r[0] - p[0])*(q[1] - p[1]), 0) + +def _keep(hull, r): + while len(hull) > 1 and _turn(hull[-2], hull[-1], r) != 1: + hull.pop() + return (not len(hull) or hull[-1] != r) and hull.append(r) or hull + +def convex_hull(point_list=None, x=None, y=None): + """Returns the convex hull from a list of points. Either point_list or x,y is provided. + (Alhorithm taken from http://tomswitzer.net/2010/03/graham-scan/) + Args: + point_list (array of tuples, optional): arrays of the points + x (array of float, optional): array with x coords of points + y (array of float, optional): array with y coords of points + Returns: + Array of points or (x,y) + """ + is_point_list = point_list is not None + if not point_list: + point_list=[] + for i in range(len(x)): + if((x[i] is not None) and (y[i] is not None)): point_list.append((x[i], y[i])) + point_list.sort() + lh,uh = reduce(_keep, point_list, []), reduce(_keep, reversed(point_list), []) + ret = lh.extend(uh[i] for i in xrange(1, len(uh) - 1)) or lh + if not is_point_list: + x, y = [], [] + for i in range(len(ret)): + x.append(ret[i][0]) + y.append(ret[i][1]) + return (x,y) + return ret + +################################################################################################### +#Utilities +################################################################################################### + +def get_setting(name=None): + """Get a persisted script setting value. + + Args: + name (str): name of the setting. + Returns: + String with setting value or None if setting is undefined. + If name is None then returns map with all settings. + """ + return get_context().getSettings() if (name is None) else get_context().getSetting(name) + +def set_setting(name, value): + """Set a persisted script setting value. + + Args: + name (str): name of the setting. + value (obj): value for the setting, converted to string (if None then remove the setting). + Returns: + None. + """ + get_context().setSetting(name, value) + +def exec_cmd(cmd, stderr_raise_ex = True): + """Executes a shell command. If errors happens raises an exception. + + Args: + cmd (str): command process input. If stderr_raise_ex is set then raise exception if stderr is not null. + Returns: + Output of command process. + """ + import subprocess + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE if stderr_raise_ex else subprocess.STDOUT, shell=True) + (ret, err) = proc.communicate() + if stderr_raise_ex and (err is not None) and err!="": + raise Exception(err) + return ret + +def bsget(channel, modulo=1, offset=0, timeout = 5.0): + """Reads an values a bsread stream, using the default provider. + + Args: + channel(str or list of str): channel name(s) + module(int, optional): stream modulo + offset(int, optional): stream offset + timeout(float, optional): stream timeout in secs + Returns: + BS value or list of values + """ + channels = to_list(channel) + ret = Stream.readChannels(channels, modulo, offset, int(timeout * 1000)) + if is_string(channel): + return ret[0] + return ret + +def flatten(data): + """Flattens multi-dimentional or nested data. + + Args: + data (tuple, array, ArrayList or Array): input data + Returns: + Iterator on the flattened data. + """ + if is_array(data): + if not data.typecode.startswith('['): + return data + + import itertools + return itertools.chain(*data) + +def frange_gen(start, finish, step): + while ((step >= 0.0) and (start <= finish)) or ((step < 0.0) and (start >= finish)): + yield start + start += step + +def frange(start, finish, step, enforce_finish = False, inclusive_finish = False): + """Create a list with a range of float values (a float equivalent to "range"). + + Args: + start(float): start of range. + finish(float): end of range. + step(float): step size. + enforce_finish(boolean, optional): adds the final element even if range was not exact. + inclusive_finish(boolean, optional): if false finish is exclusive (like in "range"). + + Returns: + list + """ + step = float(step) + ret = list(frange_gen(start, finish, step)) + if len(ret) > 0: + if inclusive_finish == False: + if ret[-1]==finish: + del ret[-1] + if enforce_finish and ret[-1]!=finish: + ret.append(finish) + return ret + +def notify(subject, text, attachments = None, to=None): + """Send email message. + + Args: + subject(str): Message subject. + text(str): Message body. + attachments(list of str, optional): list of files to be attached (expansion tokens are allowed). + to (list ofd str, optional): recipients. If None uses the recipients defined in mail.properties. + Returns: + None + """ + get_context().notify(subject, text, to_list(attachments), to_list(to)) + +def expand_path(path, timestamp=-1): + """Expand path containing tokens. + + Args: + path(str): path name. + timestamp(int): If not defined(-1), uses now. + Returns: + Expanded path name. + """ + + return get_context().getSetup().expandPath(path, timestamp) + +################################################################################################### +#UI +################################################################################################### + +def set_status(status): + """Set the application status. + + Args: + status(str): new status. + + Returns: + None + """ + set_preference(Preference.STATUS, status) + +def setup_plotting( enable_plots=None, enable_table=None,plot_list=None, line_plots=None, range=None, domain=None, defaults=None): + if defaults == True: set_preference(Preference.DEFAULTS, True) + if enable_plots is not None: set_preference(Preference.PLOT_DISABLED, not enable_plots) + if enable_table is not None: set_preference(Preference.TABLE_DISABLED, not enable_table) + if plot_list is not None: set_preference(Preference.ENABLED_PLOTS, None if plot_list == "all" else plot_list) + if line_plots is not None: + plots = None + if line_plots != "none": + plots = {} + for p in line_plots: plots[p]=1 + set_preference(Preference.PLOT_TYPES, plots) + if range is not None: + if range == "none": set_preference(Preference.AUTO_RANGE, None) + elif range == "auto": set_preference(Preference.AUTO_RANGE, True) + else: set_preference(Preference.MANUAL_RANGE, range) + if domain is not None: set_preference(Preference.DOMAIN_AXIS, domain) + +def set_preference(preference, value): + """Hints to graphical layer: + + Args: + preference(Preference): Enum of preference types: + PLOT_DISABLED: enable/disable scan plot (True/False) + PLOT_LAYOUT: "Horizontal", "Vertical" or "Grid" + TABLE_DISABLED: enable/disable scan table (True/False) + ENABLED_PLOTS: select Readables to be plotted (list of Readable or String (names)) + PLOT_TYPES: Dictionary - Plot name(Readable or String) : Plot type(String or int) + PRINT_SCAN: Print scan records to console + AUTO_RANGE: Automatic range scan plots x-axis + MANUAL_RANGE: Manually set scan plots x-axis + MANUAL_RANGE_Y: Manually set scan plots y-axis + DOMAIN_AXIS: Set the domain axis source: "Time", "Index", or a readable name. + Default(None): first positioner + STATUS: set application status + value(object): preference value + + Returns: + None + """ + value = to_array(value, 'o') #If list then convert to Object array + get_context().setPreference(preference, value) + +def get_string(msg, default = None, alternatives = None, password = False): + """ + Reads a string from UI + Args: + msg(str): display message. + default(str, optional): value displayed when window is shown. + alternatives(list of str, optional): if provided presents a combo box instead of an editing field. + password(boolean, optional): if True hides entered characters. + + Returns: + String entered of null if canceled + """ + if password : + return get_context().getPassword(msg, None) + return get_context().getString(msg, str(default) if (default is not None) else None, alternatives) + +def get_option(msg, type = "YesNoCancel"): + """ + Gets an option from UI + Args: + msg(str): display message. + type(str, optional): 'YesNo','YesNoCancel' or 'OkCancel' + + Returns: + 'Yes', 'No', 'Cancel' + """ + return get_context().getOption(msg, type) + +def show_message(msg, title=None, blocking = True): + """ + Pops a blocking message to UI + + Args: + msg(str): display message. + title(str, optional): dialog title + """ + get_context().showMessage(msg, title, blocking) + +def show_panel(device, title=None): + """ + Show, if exists, the panel relative to this device. + + Args: + device(Device or str or BufferedImage): device + title only apply to BufferedImage objects. For devices the title is the device name. + """ + if type(device) is BufferedImage: + device = DirectSource(title, device) + device.initialize() + if is_string(device): + device = get_device(device) + return get_context().showPanel(device) + + + +################################################################################################### +#Executed on startup +################################################################################################### + +if __name__ == "___main__": + ca_channel_path=os.path.join(get_context().setup.getStandardLibraryPath(), "epics") + sys.path.append(ca_channel_path) + #This is to destroy previous context of _ca (it is not shared with PShell) + if run_count > 0: + if sys.modules.has_key("_ca"): + print("") + import _ca + _ca.initialize() diff --git a/script/cpy/testJepScan.py b/script/cpy/testJepScan.py new file mode 100644 index 0000000..73bc2a8 --- /dev/null +++ b/script/cpy/testJepScan.py @@ -0,0 +1,30 @@ + + +#r = tscan((sin,out), 100, 0.01) +#vector = [ 1, 3, 5, 10, 25, 40, 45, 47, 49] +#r = vscan(pv,(sin,out),vector,False, 0.5, title = "1D Vector") +#r = mscan(sin,(sin,out),-1, 3,0) +#r = rscan(pv,(sin,out) , [(0.0,5.0,1.0), (10.0,15.0,0.1), (20.0,25.0,1.0)] , 0.01) +#r = cscan(motor, (sin,out), 0.0, 2.0 , steps=10.0, time=4.) + +print (get_exec_pars().getPath()) + +def before_pass(pass_num): + print ("Starting pass: " , pass_num) +def after_pass(pass_num): + print ("Finished pass: " , pass_num) + +#set_exec_pars(layout="sf") + +ret= lscan(inp, (sin,out), 0, 40, 50, 0.2, passes = 1, before_pass = before_pass, after_pass=after_pass,title = "Test") +#ret= lscan(inp, (sin,out), 0, 40, 50, 0.2) + +#set_exec_pars(then="run('test/test3.py)") +#set_return([1.0, 3, [1,2,3,4]]) +#1/0 +#set_return("T\"es\"t") +#set_return([3.0,2]) +set_return(ret) + + + \ No newline at end of file diff --git a/script/cpy/xxx.py b/script/cpy/xxx.py new file mode 100644 index 0000000..4997861 --- /dev/null +++ b/script/cpy/xxx.py @@ -0,0 +1,115 @@ +################################################################################################### +# This moddule is called by demo scripts to execute and embed CPython. +# Must be put in the scripts folder, or else in the python path. +################################################################################################### +import matplotlib +""" +['GTK3Agg', 'GTK3Cairo', 'MacOSX', 'nbAgg', 'Qt4Agg', 'Qt4Cairo', 'Qt5Agg', 'Qt5Cairo', 'TkAgg', 'TkCairo', +'WebAgg', 'WX', 'WXAgg', 'WXCairo', 'agg', 'cairo', 'pdf', 'pgf', 'ps', 'svg', 'template'] +""" +matplotlib.use('Qt5Agg') + +import sys +import os + +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt + +try: + import tkinter as tk +except: + import Tkinter as tk + + +def calc(array): + return np.transpose(array + array) + + +def test_pandas(): + s = pd.Series([1,3,5,np.nan,6,8]) + print (s) + dates = pd.date_range('20130101', periods=6) + print (dates) + df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD')) + print (df) + df2 = pd.DataFrame({ 'A' : 1., + 'B' : pd.Timestamp('20130102'), + 'C' : pd.Series(1,index=list(range(4)),dtype='float32'), + 'D' : np.array([3] * 4,dtype='int32'), + 'E' : pd.Categorical(["test","train","test","train"]), + 'F' : 'foo' }) + print (df2) + print (df2.dtypes) + print (df.head()) + print (df.tail(3)) + print (df.values) + print (df.describe()) + print (df.T) + print (df.sort_index(axis=1, ascending=False)) + #print (df.sort_values(by='B')) + print (df['A']) + print (df[0:3]) + print (df.mean()) + return str(df.mean()) + + +def test_tkinter(): + root = tk.Tk() + listb = tk.Listbox(root) + for item in ["Hello", "World"]: + listb.insert(0,item) + listb.pack() + root.mainloop() + +print ("OK") + +def test_matplotlib(start,stop,step): + import threading + x = np.arange(start,stop,step) + y = np.exp(-x) + + # example variable error bar values + yerr = 0.1 + 0.2*np.sqrt(x) + xerr = 0.1 + yerr + + # First illustrate basic pyplot interface, using defaults where possible. + plt.figure() + plt.errorbar(x, y, xerr=0.2, yerr=0.4) + plt.title("Simplest errorbars, 0.2 in x, 0.4 in y") + + # Now switch to a more OO interface to exercise more features. + fig, axs = plt.subplots(nrows=2, ncols=2, sharex=True) + ax = axs[0,0] + ax.errorbar(x, y, yerr=yerr, fmt='o') + ax.set_title('Vert. symmetric') + + # With 4 subplots, reduce the number of axis ticks to avoid crowding. + ax.locator_params(nbins=4) + + ax = axs[0,1] + ax.errorbar(x, y, xerr=xerr, fmt='o') + ax.set_title('Hor. symmetric') + + ax = axs[1,0] + ax.errorbar(x, y, yerr=[yerr, 2*yerr], xerr=[xerr, 2*xerr], fmt='--o') + ax.set_title('H, V asymmetric') + + ax = axs[1,1] + ax.set_yscale('log') + # Here we have to be careful to keep all y values positive: + ylower = np.maximum(1e-2, y - yerr) + yerr_lower = y - ylower + + ax.errorbar(x, y, yerr=[yerr_lower, 2*yerr], xerr=xerr, + fmt='o', ecolor='g', capthick=2) + ax.set_title('Mixed sym., log y') + + fig.suptitle('Variable errorbars') + + plt.show() + return [start,stop,step] + + +test_pandas() +test_matplotlib(0,100,100) \ No newline at end of file diff --git a/script/cpython/gfitoff.py b/script/cpython/gfitoff.py new file mode 100644 index 0000000..31a1e1b --- /dev/null +++ b/script/cpython/gfitoff.py @@ -0,0 +1,30 @@ +import numpy as np +import scipy.optimize + + +def gfitoff(x, y, off=None, amp=None, com=None, sigma=None): + if off is None: + off = y.min() # good enough starting point for offset + + if com is None: + com = x[y.argmax()] + + if amp is None: + amp = y.max() - off + + # For normalised gauss curve sigma=1/(amp*sqrt(2*pi)) + if sigma is None: + surface = np.trapz((y-off), x=x) + sigma = surface / (amp * np.sqrt(2 * np.pi)) + try: + popt, pcov = scipy.optimize.curve_fit(gauss_fn, x, y, p0=[off, amp, com, sigma], method='lm') + popt[3] = abs(popt[3]) # sigma should be returned as positive + except Exception as e: + print("Gauss fitting not successful.\n" + str(e)) + popt = [off, amp, com, abs(sigma)] + + return popt + + +def gauss_fn(x, a, b, c, d): + return a + b * np.exp(-(np.power((x - c), 2) / (2 * np.power(d, 2)))) \ No newline at end of file diff --git a/script/cpython/linfit.py b/script/cpython/linfit.py new file mode 100644 index 0000000..01644b1 --- /dev/null +++ b/script/cpython/linfit.py @@ -0,0 +1,32 @@ +import numpy as np + +def linfit(x, y): + """ + Return linear fit + """ + p = np.polyfit(x, y, 1) + f = np.poly1d(p) + x_fit = np.linspace(min(x), max(x), 100) + y_fit = f(x_fit) + yhat = f(x) + ybar = np.sum(y)/len(y) + ssreg = np.sum((yhat - ybar)**2) + sstot = np.sum((y - ybar)**2) + R2 = ssreg / sstot + return (p, x_fit, y_fit, R2) + +def test(): + return np.ones(5) + + +def test2(name, x=None, y=None): + print (name,x,y) + ret = y*x + print (ret) + return ret + +def add(x,y,z): + return x+y+z + +def read_dev(dev): + return dev.read() \ No newline at end of file diff --git a/script/cpython/test.py b/script/cpython/test.py new file mode 100644 index 0000000..dde8d55 --- /dev/null +++ b/script/cpython/test.py @@ -0,0 +1,34 @@ +from jeputils import import_py + +import_py("cpython/linfit", "linfit") +import_py("cpython/gfitoff", "gfitoff") +import_py("CPython/linfit", "add") +import_py("CPython/linfit", "test") +import_py("CPython/linfit", "test2") +import_py("CPython/linfit", "read_dev") + +print read_dev(sin) + + +a,b,c =to_array([0,1,2,3,4],'d'), to_array([5,6,7,8,9],'d'), to_array([10, 11, 12, 13, 14],'d') +print test() +print test2("x", x=a,y=b) +print add(a,b,c) + +x=[0,1,2,3,4,5,6,7,8,9] +y=[1,2,3,6,9,6,3,2,1,0] +(p, x_fit, y_fit, R2) = linfit(x,y) +#print "Fit: ", (p, x_fit, y_fit, R2) +plot((y,y_fit), name=("data", "fit"),xdata=(x,x_fit)) + +time.sleep(2.0) +from mathutils import Gaussian +x=to_array([-200.30429237268825, -200.2650700434188, -200.22115208318002, -199.9457671375377, -199.86345548879072, -199.85213073174933, -199.35687977133284, -199.13811861090275, -197.97304970346386, -197.2952215624348, -195.09076092936948, -192.92276048970703, -191.96871876227698, -189.49577852322938, -187.9652790409825, -183.63756456925222, -180.04899765472996, -178.43839623242422, -174.07311671294445, -172.0410133577918, -165.90824309893102, -160.99771795989466, -159.30176653939253, -154.27688897558514, -152.0854103810786, -145.75652847587313, -140.80843828908465, -139.23982133191495, -134.27073891256106, -132.12649284133064, -125.95947209775511, -121.00309550337462, -119.26736932643232, -114.2706655484383, -112.07393889578914, -105.72295990367157, -100.8088439880125, -99.2034906238494, -94.30042325164636, -92.15010048151461, -85.92203653534293, -81.03913275494665, -79.27412793784428, -74.33487658582118, -72.06274362408762, -65.76562628131825, -60.91255356825276, -59.20334389560392, -54.33286972659312, -52.19387171350535, -45.94978737932291, -41.03014719193582, -39.301602568238906, -34.35572209014114, -32.04464301272608, -25.8221033382824, -20.922074315528747, -19.21590299233186, -14.31090212502093, -12.217203140101386, -5.9283722049240435, -0.9863587170369246, 0.7408048387279834, 5.71126832601389, 7.972628957879352, 14.204559894256546, 19.11839959633025, 20.8218087836657, 25.678748486941828, 27.822718344586864, 34.062659474970715, 38.9745656819391, 40.77409719734158, 45.72080631619803, 47.974156754056835, 54.23453768983539, 59.12020360609568, 60.77306570712026, 65.70734521458867, 67.8344660434617, 74.03187028154134, 78.96532114824849, 80.76070945985495, 85.74802197591286, 87.9140889204674, 94.18082276873524, 99.25790470037091, 100.68454787413205, 105.7213026221542, 107.79483801526698, 113.99555681638138, 119.0707052529143, 120.72715813056156, 125.77551384921307, 127.91257836719551, 134.2011330887875, 139.23043006997628, 140.71673537840158, 145.76288138835983, 147.80216629676042, 154.06420451405637, 159.0846626604798, 160.76183155710717, 165.73699067536242, 167.9265357747636, 173.96705069576544, 178.2522282751915, 179.9042617354548, 183.54586165856657, 185.23269803071796, 189.41678143751972, 191.87149157986588, 192.8741468985015, 195.0241934550453, 195.966634211846, 197.9821647518146, 198.99006812859284, 199.33202054855676, 199.91897441965887, 200.11536227958896, 200.22280936469997, 200.25181179127208],'d') +y=to_array([11.0, 6.0, 8.0, 5.0, 11.0, 7.0, 18.0, 11.0, 12.0, 10.0, 8.0, 6.0, 16.0, 4.0, 12.0, 9.0, 15.0, 14.0, 8.0, 20.0, 15.0, 8.0, 9.0, 11.0, 13.0, 12.0, 13.0, 15.0, 13.0, 20.0, 10.0, 7.0, 17.0, 11.0, 20.0, 13.0, 13.0, 23.0, 14.0, 10.0, 17.0, 15.0, 20.0, 16.0, 14.0, 13.0, 18.0, 22.0, 9.0, 20.0, 12.0, 14.0, 17.0, 19.0, 14.0, 14.0, 23.0, 19.0, 15.0, 20.0, 20.0, 21.0, 20.0, 23.0, 22.0, 15.0, 10.0, 17.0, 21.0, 15.0, 23.0, 23.0, 25.0, 18.0, 16.0, 21.0, 22.0, 16.0, 16.0, 14.0, 19.0, 20.0, 18.0, 20.0, 23.0, 13.0, 16.0, 20.0, 25.0, 15.0, 15.0, 17.0, 22.0, 26.0, 19.0, 30.0, 25.0, 17.0, 17.0, 23.0, 16.0, 27.0, 21.0, 21.0, 26.0, 27.0, 21.0, 17.0, 20.0, 20.0, 21.0, 19.0, 25.0, 19.0, 13.0, 23.0, 20.0, 20.0, 18.0, 20.0, 19.0, 25.0],'d') +[off, amp, com, sigma] = gfitoff(x, y, off=None, amp=None, com=None, sigma=None) +#print "Fit: ", [off, amp, com, sigma] +g = Gaussian(amp, com, sigma) +plot([y, [g.value(i)+off for i in x]], ["data", "fit"], xdata = x) + + + diff --git a/script/cpython/test2.py b/script/cpython/test2.py new file mode 100644 index 0000000..b65d4c7 --- /dev/null +++ b/script/cpython/test2.py @@ -0,0 +1,14 @@ +from jeputils import import_py + +import_py("cpython/gfitoff", "gfitoff") + +from mathutils import Gaussian +x=to_array([-200.30429237268825, -200.2650700434188, -200.22115208318002, -199.9457671375377, -199.86345548879072, -199.85213073174933, -199.35687977133284, -199.13811861090275, -197.97304970346386, -197.2952215624348, -195.09076092936948, -192.92276048970703, -191.96871876227698, -189.49577852322938, -187.9652790409825, -183.63756456925222, -180.04899765472996, -178.43839623242422, -174.07311671294445, -172.0410133577918, -165.90824309893102, -160.99771795989466, -159.30176653939253, -154.27688897558514, -152.0854103810786, -145.75652847587313, -140.80843828908465, -139.23982133191495, -134.27073891256106, -132.12649284133064, -125.95947209775511, -121.00309550337462, -119.26736932643232, -114.2706655484383, -112.07393889578914, -105.72295990367157, -100.8088439880125, -99.2034906238494, -94.30042325164636, -92.15010048151461, -85.92203653534293, -81.03913275494665, -79.27412793784428, -74.33487658582118, -72.06274362408762, -65.76562628131825, -60.91255356825276, -59.20334389560392, -54.33286972659312, -52.19387171350535, -45.94978737932291, -41.03014719193582, -39.301602568238906, -34.35572209014114, -32.04464301272608, -25.8221033382824, -20.922074315528747, -19.21590299233186, -14.31090212502093, -12.217203140101386, -5.9283722049240435, -0.9863587170369246, 0.7408048387279834, 5.71126832601389, 7.972628957879352, 14.204559894256546, 19.11839959633025, 20.8218087836657, 25.678748486941828, 27.822718344586864, 34.062659474970715, 38.9745656819391, 40.77409719734158, 45.72080631619803, 47.974156754056835, 54.23453768983539, 59.12020360609568, 60.77306570712026, 65.70734521458867, 67.8344660434617, 74.03187028154134, 78.96532114824849, 80.76070945985495, 85.74802197591286, 87.9140889204674, 94.18082276873524, 99.25790470037091, 100.68454787413205, 105.7213026221542, 107.79483801526698, 113.99555681638138, 119.0707052529143, 120.72715813056156, 125.77551384921307, 127.91257836719551, 134.2011330887875, 139.23043006997628, 140.71673537840158, 145.76288138835983, 147.80216629676042, 154.06420451405637, 159.0846626604798, 160.76183155710717, 165.73699067536242, 167.9265357747636, 173.96705069576544, 178.2522282751915, 179.9042617354548, 183.54586165856657, 185.23269803071796, 189.41678143751972, 191.87149157986588, 192.8741468985015, 195.0241934550453, 195.966634211846, 197.9821647518146, 198.99006812859284, 199.33202054855676, 199.91897441965887, 200.11536227958896, 200.22280936469997, 200.25181179127208],'d') +y=to_array([11.0, 6.0, 8.0, 5.0, 11.0, 7.0, 18.0, 11.0, 12.0, 10.0, 8.0, 6.0, 16.0, 4.0, 12.0, 9.0, 15.0, 14.0, 8.0, 20.0, 15.0, 8.0, 9.0, 11.0, 13.0, 12.0, 13.0, 15.0, 13.0, 20.0, 10.0, 7.0, 17.0, 11.0, 20.0, 13.0, 13.0, 23.0, 14.0, 10.0, 17.0, 15.0, 20.0, 16.0, 14.0, 13.0, 18.0, 22.0, 9.0, 20.0, 12.0, 14.0, 17.0, 19.0, 14.0, 14.0, 23.0, 19.0, 15.0, 20.0, 20.0, 21.0, 20.0, 23.0, 22.0, 15.0, 10.0, 17.0, 21.0, 15.0, 23.0, 23.0, 25.0, 18.0, 16.0, 21.0, 22.0, 16.0, 16.0, 14.0, 19.0, 20.0, 18.0, 20.0, 23.0, 13.0, 16.0, 20.0, 25.0, 15.0, 15.0, 17.0, 22.0, 26.0, 19.0, 30.0, 25.0, 17.0, 17.0, 23.0, 16.0, 27.0, 21.0, 21.0, 26.0, 27.0, 21.0, 17.0, 20.0, 20.0, 21.0, 19.0, 25.0, 19.0, 13.0, 23.0, 20.0, 20.0, 18.0, 20.0, 19.0, 25.0],'d') +[off, amp, com, sigma] = gfitoff(x, y, off=None, amp=None, com=None, sigma=None) +print "Fit: ", [off, amp, com, sigma] +g = Gaussian(amp, com, sigma) +plot([y, [g.value(i)+off for i in x]], ["data", "fit"], xdata = x) + + + diff --git a/script/diffcalc_test/.DS_Store b/script/diffcalc_test/.DS_Store new file mode 100644 index 0000000..55cae50 Binary files /dev/null and b/script/diffcalc_test/.DS_Store differ diff --git a/script/eiger.py b/script/eiger.py new file mode 100644 index 0000000..a900be7 --- /dev/null +++ b/script/eiger.py @@ -0,0 +1,323 @@ +from ijutils import * +from ch.psi.pshell.imaging.Overlays import * +from ch.psi.pshell.imaging.Utils import * +import ch.psi.pshell.imaging.Pen as Pen +import java.awt.Rectangle as Rectangle +import ch.psi.pshell.imaging.Data as Data +import ch.psi.pshell.device.Camera.DataType as DataType +import ch.psi.utils.Chrono as Chrono +import subprocess +import java.util.Arrays as Arrays + +#GRAB_MIN_TIME = 1000 +CONTINOUS_MODE_MIN_TIME = 4000 +############################################################################### +# ROI Integration +############################################################################### + + +def start_eiger_ioc(): + print "IOC started" + + + +def stop_eiger_ioc(): + print "IOC stopped" + + +def integrate_roi(source, x,y, w, h): + if source.data is None: + source.update() + rect = Rectangle(x,y, w, h) + roi = source.data.getRoi(rect) + + outliers_mask = get_outliers_mask() + if outliers_mask is not None: + mask = outliers_mask.getRoi(rect) + roi.mult(mask) + + outliers_threshold = get_outliers_threshold() + if outliers_threshold>0: + roi.threshold(outliers_threshold, False, 0.0) + + return roi.integrate(False) + + +class RoiIntensitySourceListener (ImageListener): + def __init__(self, parent): + self.parent = parent + def onImage(self, origin, image, data): + self.parent.update() + def onError(self, origin, ex): + pass + + +class RoiIntensity(ReadonlyRegisterBase): + def __init__(self, name, source, x,y, w, h): + ReadonlyRegisterBase.__init__(self, name) + self.source=source + self.roi = x,y, w, h + self.source_listener = RoiIntensitySourceListener(self) + + def doRead(self): + x,y, w, h = self.roi + + ret= integrate_roi(self.source, x,y, w, h) + print "Read " + self.name + " -> " + str(ret) + return ret + + def doSetMonitored(self, value): + if value: + self.source.addListener(self.source_listener) + else: + self.source.removeListener(self.source_listener) + + def doClose(self): + self.source.removeListener(self.source_listener) + +def create_roi_devices(roi_list, add = True): + rois = [] + for r in roi_list: + roi = RoiIntensity(r, image, roi_list[r][0], roi_list[r][1], roi_list[r][2], roi_list[r][3]) + if add: + add_device(roi, True) + rois.append(roi) + return rois + +############################################################################### +# Frame integration +############################################################################### +#chrono_grab= Chrono() +def grab_frame(source, roi=None, wait_next=False, outliers_threshold=None, outliers_mask=None, retries=None, timeout=None): + global eiger_averaging_number_of_samples #, chrono_grab + + #chrono_grab.waitTimeout(GRAB_MIN_TIME) + if outliers_threshold is None: + outliers_threshold = get_outliers_threshold() + if outliers_mask is None: + outliers_mask = get_outliers_mask() + if wait_next: + if retries is None: + retries = 3 + if timeout is None: + timeout=10.0 + exposures = 1 if (eiger_averaging_number_of_samples is None) else eiger_averaging_number_of_samples + retries=max(retries,1) + timeout = 5000 + for try_count in range(retries): + try: + start =time.time() + id = image.take() + print "Waiting next " + source.waitNext(timeout) + #det.update() + #time.sleep(1) + print "Waiting done ", str(time.time()-start), " ", str(id), "->", str(image.take()) + break + except java.util.concurrent.TimeoutException: + if try_count == (retries-1): + raise + msg = "Eiger timeout - retrying #" + str(try_count) + print msg + log(msg) + + #ret = load_image(Utils.grayscale(source.output, Rectangle(roi[0], roi[1], roi[2], roi[3]) if (roi is not None) else None)) + time.sleep(0.01) + data=source.data + if roi is not None: + data = data.getRoi(Rectangle(roi[0], roi[1], roi[2], roi[3])) + #ret = load_image(img) + if outliers_mask is not None: + data.mult(outliers_mask) + if outliers_threshold>0: + data.threshold(outliers_threshold, False, None) + #chrono_grab = Chrono() + return data + +def grab_frames(source, samples, roi=None, wait_next=False, sleep=0, outliers_threshold=None, outliers_mask=None, retries=None, timeout=None): + frames = [] + for i in range(samples): + if (i>0) and (sleep>0): + time.sleep(sleep) + aux = grab_frame(source, roi, wait_next, outliers_threshold, outliers_mask, retries, timeout) + frames.append(aux) + return frames + +def integrate_frames(frames): + if frames is None or (len(frames)==0): + return None + ret = frames[0].copy() + for data in frames[1:]: + ret.sum(data) + return ret + +f,f1,f2=None, None, None +def average_frames(frames): + global f,f1,f2 + f1,f2 = frames + ret = integrate_frames(frames) + if ret is not None: + ret.div(len(frames)) + f=ret + return ret + + +def _timestamp(prec=0): + t = time.time() + s = time.strftime("%y/%m/%d %H:%M:%S", time.localtime(t)) + if prec > 0: + s += ("%.9f" % (t % 1,))[1:2+prec] + return s + +def _save_as_tiff(data, filename, check=False, show = False, metadata={}): + if type(data) == Data: + ip = load_array(data.matrix) + else: + ip = data + #info = "Timestamp: " + _timestamp(3) + #for key,val in metadata.items(): + # info = info + "\n" + str(key) + ": " + str(val) + #print "Info:" ,info + #ip.setProperty("Info", info) + metadata["Timestamp"] = time.strftime("%y/%m/%d %H:%M:%S",time.localtime()) + if not os.path.exists(os.path.dirname(filename)): + os.makedirs(os.path.dirname(filename)) + save_image(ip, filename,"tiff", metadata) + + #finfo = open(filename + ".info", "w") + #for k, v in metadata.items(): + # finfo.write(str(k) + ': '+ str(v) + '\n') + #info.close() + + if check: + data = get_ip_array(ip) + + ip=open_image(filename) + read = get_ip_array(ip) + if not Arrays.deepEquals(read, data): + print "Error checking array" + +def save_as_tiff(data, filename, check=False, show = False, parallel=True, metadata={}): + if parallel: + return fork((_save_as_tiff,(data, filename, check, show, metadata)),) + else: + _save_as_tiff(data, filename, check, show, metadata) + +def trigger_eiger(wait=True): + if wait: + image.waitNext(20000) + +def get_eiger_exposure_readback(): + return 1.0 + +def set_exposure_time(value, check = True, retries=5): + pass + +def get_eiger_number_of_frames(): + return 1 + +def set_eiger_number_of_frames(value, check = True): + pass + + #Wait for channel to chenge + +def stop_eiger(): + pass + +chrono_eiger = Chrono() + +def init_eiger(exposure=None, check=True, retries=2): + """ + Set Eiger scan mode + """ + pass + +def restore_eiger(check=True, retries=2, exposure_time = 0.2): + """ + Set Eiger default mode + """ + pass + +def is_averaging_detector(): + return False + +eiger_averaging_number_of_samples=None + +def apply_averaging_detector(value): + pass + + +def average_eiger_frames(samples, roi=None, wait_next=False, sleep=0, outliers_threshold=None, outliers_mask=None, retries=None, timeout=None): + global eiger_averaging_number_of_samples #, chrono_eiger + sample = int(samples) + ret = grab_frames(image, samples, roi, wait_next, sleep, outliers_threshold, outliers_mask, retries, timeout) + #print "Averaging frames " + str(len(ret)) + " " + str(ret[0].integrate(False)) + " " + str(ret[1].integrate(False)) + " " + str(ret[0].equals(ret[1])) + print "Averaging frames " + + av = average_frames(ret) if samples > 1 else ret[0] + """ + for name,r in ROI.items(): + s, s1, s2 =0.0, 0.0, 0.0 + for i in range(r[2]): + for j in range(r[3]): + #s = s + d[r[0]+i][r[1]+j] + s = s + av.getElement(r[0]+i, r[1]+j, False) + s1 = s1 + ret[0].getElement(r[0]+i, r[1]+j, False) + s2 = s2 + ret[1].getElement(r[0]+i, r[1]+j, False) + + print "- ", name, s, s1,s2 + """ + return av + + +_outliers_mask_timestamp = 0 +_outliers_mask = None + +def get_outliers_mask(data_type='f'): + global _outliers_mask_timestamp, _outliers_mask + + if get_exec_pars().start == _outliers_mask_timestamp: + return _outliers_mask + _outliers_mask_timestamp = get_exec_pars().start + try: + _outliers_mask = None + filename = get_outliers_mask_file() + if filename: + ip=open_image(filename) + + #TRANSPOSE - ImageJ stores the data transposed + ip.getProcessor().rotate(-90) + ip.getProcessor().flipVertical() + + array = get_ip_array(ip) + array = Convert.toPrimitiveArray(array, ScriptUtils.getType(data_type)) + _outliers_mask = Data(array) + print "Generated outliers mask" + except: + pass + return _outliers_mask + + + + +if False: + integrate_roi(image, 10, 5, 20, 10) + + add_device(RoiIntensity("Region1", image, 10, 5, 20, 10), True) + add_device(RoiIntensity("Region2", image, 10, 5, 40, 20), True) + + + import ch.psi.pshell.data.ProviderCSV as ProviderCSV + ProviderCSV.setDefaultItemSeparator(" ") + tscan((Region1, Region2), 10, 0.1, layout="table", provider = "csv") + + ret = grab_frames(image, 10, sleep=0.1) + av = integrate_frames(ret) + save_as_tiff(av,"{images}/data.tif", True) + + + print "Success" + + + + diff --git a/script/imaging/sim.py b/script/imaging/sim.py new file mode 100644 index 0000000..fa56b15 --- /dev/null +++ b/script/imaging/sim.py @@ -0,0 +1,642 @@ +from ijutils import * +import java.lang.reflect +import flanagan.complex.ComplexMatrix as ComplexMatrix +import flanagan.math.Matrix as Matrix +import flanagan.complex.Complex as Complex +import org.jtransforms.fft.DoubleFFT_2D as DoubleFFT_2D +import math +from startup import ScriptUtils +import ij.plugin.filter.PlugInFilterRunner as PlugInFilterRunner +import ij.plugin.filter.ExtendedPlugInFilter as ExtendedPlugInFilter +import ij.plugin.filter.ExtendedPlugInFilter as ExtendedPlugInFilter +import java.lang.Thread as Thread + + +def new_array(type, *dimensions): + return java.lang.reflect.Array.newInstance(ScriptUtils.getPrimitiveType(type), *dimensions) + +def load_stack(title, file_list, show=False): + ip_list = [] + for f in file_list: + ip_list.append(open_image(expand_path(f))) + stack = create_stack(ip_list, title=title) + if show: + stack.show() + return stack + +def load_test_stack(title="Test", show=False, size=9): + file_list = [] + for index in range(40, 40+size): + file_list.append("{images}/TestObjAligner/i210517_0" + str(index) + "#001.tif") + return load_stack(title, file_list, show) + +def load_corr_stack(title="Corr", show=False): + file_list = [] + for index in range(40, 49): + file_list.append("{images}/TestObjAligner_corr/i210517_0" + str(index) + "#001.tif") + return load_stack(title, file_list, show) + +def complex_edge_filtering(imp, complex=True, g_sigma=3.0, g_resolution=1e-4, show=False, java_code=False): + if java_code: + get_context().getPluginManager().loadInitializePlugin("Align_ComplexEdgeFiltering.java") + complex_edge_filter = get_context().getClassByName("Align_ComplexEdgeFiltering").newInstance() + complex_edge_filter.setup(str(g_sigma)+","+str(complex)+","+str(show), imp) #Gaussian blur radius, Complex (True) or Real (False), show dialog = False + complex_edge_filter.run(imp.getProcessor()) + return complex_edge_filter.output + + gb = GaussianBlur() + sobel_r = [1, 0, -1, 2, 0, -2, 1, 0, -1] + sobel_i = [1, 2, 1, 0, 0, 0, -1, -2, -1] + + imp_r = imp.createImagePlus() + stack_r = ImageStack(imp.getWidth(), imp.getHeight()) + + if (complex): + imp_i = imp.createImagePlus() + stack_i = ImageStack(imp.getWidth(), imp.getHeight()) + for i in range(1, imp.getImageStackSize() + 1): + ip_r = imp.getStack().getProcessor(i).duplicate().convertToFloat() + # Gaussian blurring + gb.blurGaussian(ip_r, g_sigma, g_sigma, g_resolution) + ip_i = ip_r.duplicate() + # Sobel edge filtering + ip_r.convolve3x3(sobel_r) + ip_i.convolve3x3(sobel_i) + + stack_r.addSlice(imp.getStack().getSliceLabel(i), ip_r) + stack_i.addSlice(imp.getStack().getSliceLabel(i), ip_i) + IJ.showProgress(i, imp.getImageStackSize()) + + # imag + imp_i.setStack("EdgeImag_" + imp.getTitle(), stack_i); + imp_i.resetDisplayRange() + if show: + imp_i.show() + imp_i.updateAndDraw() + else: + imp_i = None + for i in range(1, imp.getImageStackSize() + 1): + ip_r = imp.getStack().getProcessor(i).duplicate().convertToFloat() + # Gaussian blurring + gb.blurGaussian(ip_r, g_sigma, g_sigma, g_resolution) + # Sobel edge filtering + ip_r.filter(ImageProcessor.FIND_EDGES) + stack_r.addSlice(imp.getStack().getSliceLabel(i), ip_r) + IJ.showProgress(i, imp.getImageStackSize()) + + # real + imp_r.setStack("EdgeReal_" + imp.getTitle(), stack_r) + imp_r.resetDisplayRange() + if show: + imp_r.show() + imp_r.updateAndDraw() + return [imp_r, imp_i] + +class TranslationFilter(ExtendedPlugInFilter): + def __init__(self): + self.shifts=None + self.flags = (self.DOES_ALL-self.DOES_RGB)|self.DOES_STACKS|self.NO_CHANGES|self.FINAL_PROCESSING + self.imp=None + self.output = None + self.translated = None + self.pifr = None + self.nbslices = 0 + self.processed = 0 + + def setup(self, arg, imp): + if "final"==arg: + self.output.setStack("REG_" + self.imp.getTitle(), self.translated) + return self.DONE + else: + if self.imp is None: + self.imp = imp; + return self.flags; + + def showDialog(self,imp, command, pfr): + self.pifr = pfr + return flags + + # Called by ImageJ to set the number of calls to run(ip) corresponding to 100% of the progress bar + def setNPasses(self, nPasses): + self.nbslices = nPasses; + self.output = self.imp.createImagePlus(); + self.translated = ImageStack(self.imp.getWidth(), self.imp.getHeight(), self.nbslices) + + #Process a FloatProcessor (with the CONVERT_TO_FLOAT flag, ImageJ does the conversion to float). + # Called by ImageJ for each stack slice (when processing a full stack); for RGB also called once for each color. */ + def run(self, ip): + if Thread.currentThread().isInterrupted(): + return + thisone = self.pifr.getSliceNumber() + + nip = ip.duplicate().convertToFloat() + nip.setInterpolationMethod(ImageProcessor.BICUBIC) + if len(self.shifts) != self.nbslices: + xoff, yoff = self.shifts[1][3], self.shifts[1][2] # translate all the frame by the same shifts + else: + xoff, yoff = self.shifts[thisone-1][3], self.shifts[thisone-1][2] + nip.translate(xoff, yoff) + + lbl = self.imp.getStack().getSliceLabel(thisone) + if lbl != None: + self.translated.addSlice(lbl, nip, thisone - 1) + else: + self.translated.addSlice("" + thisone, nip, thisone - 1) + + self.translated.deleteSlice(thisone + 1) + + self.processed+=1 + IJ.showProgress(self.processed, self.nbslices); + +def translate(stack, shifts, show=False, java_code=False): + WindowManager.setTempCurrentImage(stack) + if java_code: + get_context().getPluginManager().loadInitializePlugin("Align_TranslationFilter.java") + translation_filter = get_context().getClassByName("Align_TranslationFilter").newInstance() + translation_filter.imp = imp + translation_filter.shifts = shifts + pfr = PlugInFilterRunner(translation_filter, "", "" ) + ret = translation_filter.output + else: + translation_filter = TranslationFilter() + translation_filter.shifts = shifts + translation_filter.imp = stack + pfr = PlugInFilterRunner(translation_filter, "", "" ) + ret = translation_filter.output + if show: + ret.show() + ret.updateAndDraw() + return ret + + +def load_shifts(filename): + get_context().getPluginManager().loadInitializePlugin("ShiftsIO.java") + sio = get_context().getClassByName("ShiftsIO").newInstance() + return sio.load(expand_path(filename), "directshifts") + +def save_shifts(filename, shifts): + get_context().getPluginManager().loadInitializePlugin("ShiftsIO.java") + sio = get_context().getClassByName("ShiftsIO").newInstance() + sio.save(expand_path(filename), shifts, "directshifts") + + +def ip_to_fft_array_2d(ip): + pixels = ip.getPixels() + w = ip.getWidth() + h = ip.getHeight() + data = new_array('d', h, w) # new double[h][w] + for j in range(h): # (int j = 0; j < h; j++) + for i in range(w): # for (int i = 0; i < w; i++) + data[j][i] = pixels[j * w + i] + return data + + +def ip_to_fft_complex_array_2d(ip_r, ip_i): + pixels_r = ip_r.getPixels() + pixels_i = ip_i.getPixels() + w = ip_r.getWidth() + h = ip_r.getHeight() + data = new_array('d', h, 2 * w) # new double[h][2*w]; + for j in range(h): # (int j = 0; j < h; j++) + for i in range(w): # for (int i = 0; i < w; i++) + data[j][2 * i] = pixels_r[j * w + i] + data[j][2 * i + 1] = pixels_i[j * w + i]; + return data + +def fft_array_2d_to_complex_matrix(data, h, w): + m = ComplexMatrix(h,w) + for j in range(h): #for (int j = 0; j < h; j++) { + for i in range(w/2): # for (int i = 0; i <= w/2; i++) { + if (j > 0) and (i > 0) and (i < w/2): + m.setElement(j, i, Complex(data[j][2*i], data[j][2*i+1])) + m.setElement(h-j, w-i, Complex(data[j][2*i], -data[j][2*i+1])) + if (j == 0) and (i > 0) and (i < w/2): + m.setElement(0, i, Complex(data[0][2*i], data[0][2*i+1])) + m.setElement(0, w-i, Complex(data[0][2*i], -data[0][2*i+1])) + if (i == 0) and (j > 0) and (j < h/2): + m.setElement(j,0, Complex(data[j][0], data[j][1])) + m.setElement(h-j, 0, Complex(data[j][0], -data[j][1])) + m.setElement(j, w/2, Complex(data[h-j][1], -data[h-j][0])) + m.setElement(h-j, w/2, Complex(data[h-j][1], data[h-j][0])) + if (j == 0) and (i == 0): + m.setElement(0, 0, Complex(data[0][0], 0)); + if (j == 0) and (i == w/2): + m.setElement(0, w/2, Complex(data[0][1], 0)); + if (j == h/2) and (i == 0): + m.setElement(h/2, 0, Complex(data[h/2][0], 0)); + if (j == h/2) and (i == w/2): + m.setElement(h/2, w/2, Complex(data[h/2][1], 0)); + return m + + +def fft_complex_array_2d_to_complex_matrix(data, h, w): + m = ComplexMatrix(h,w); + for j in range(h): #for (int j = 0; j < h; j++) { + for i in range(w): # for (int i = 0; i < w; i++) { + m.setElement(j,i, Complex(data[j][2*i], data[j][2*i+1])) + return m + +def complex_matrix_to_fft_array_2d(m): + w = m.getNcol() + h = m.getNrow() + data = new_array('d', h,w) #new double[h][w]; + for j in range(h): #for (int j = 0; j < h; j++) { + for i in range(w): #for (int i = 0; i <= w/2; i++) { + if (j > 0) and (i > 0) and (i < w/2): + data[j][2*i] = m.getElementReference(j,i).getReal() + data[j][2*i+1] = m.getElementReference(j,i).getImag() + if (j == 0) and (i > 0) and (i < w/2): + data[0][2*i] = m.getElementReference(0,i).getReal() + data[0][2*i+1] = m.getEementReference(0,i).getImag() + if (i == 0) and (j > 0) and (j < h/2): + data[j][0] = m.getElementReference(j,0).getReal() + data[j][1] = m.getElementReference(j,0).getImag() + data[h-j][1] = m.getElementReference(j,w/2).getReal() + data[h-j][0] = m.getElementReference(h-j,w/2).getImag() + if (j == 0) and (i == 0): + data[0][0] = m.getElementReference(0,0).getReal() + if (j == 0) and (i == w/2): + data[0][1] = m.getElementReference(0,w/2).getReal() + if (j == h/2) and (i == 0): + data[h/2][0] = m.getElementReference(h/2,0).getReal() + if (j == h/2) and ( i == w/2): + data[h/2][1] = m.getElementReference(h/2,w/2).getReal() + return data + + +# convert a Complex Matrix into an 2d real part array data[0][][] and 2d imaginary part data[1][][] +def complex_matrix_to_real_array_2d(m): + w = m.getNcol() + h = m.getNrow() + data = new_array('d', 2,h,w) #new double[2][h][w]; + for j in range(h): #for (int j = 0; j < h; j++) { + for i in range(w): #for (int i = 0; i < w; i++) { + data[0][j][i] = m.getElementReference(j,i).getReal() + data[1][j][i] = m.getElementReference(j,i).getImag() + return data; + + +def compute_fft(imp_r, imp_i, roi): + slices = imp_r.getStackSize() + ffts = java.lang.reflect.Array.newInstance(ComplexMatrix, slices) # new ComplexMatrix[slices] + for i in range(1, slices + 1): + if imp_i is None: + ip = imp_r.getStack().getProcessor(i) + ip.setRoi(roi) + curr = ip.crop().convertToFloat(); + data = ip_to_fft_array_2d(curr) + ffts[i - 1] = fft2(data) + else: + ip1 = imp_r.getStack().getProcessor(i) + ip1.setRoi(roi) + curr_r = ip1.crop().convertToFloat() + ip2 = imp_i.getStack().getProcessor(i) + ip2.setRoi(roi) + curr_i = ip2.crop().convertToFloat() + data = ip_to_fft_complex_array_2d(curr_r, curr_i) + ffts[i - 1] = cfft2(data) + IJ.showProgress(i, slices) + return ffts + + +def element_product(a, b): + nr = a.getNrow() + nc = a.getNcol() + res = ComplexMatrix(nr, nc) + for j in range(nr): # (int j = 0; j < nr; j++) { + for i in range(nc): # (int i = 0; i < nc; i++) { + res.setElement(j, i, a.getElementReference(j, i).times(b.getElementReference(j, i))) + return res; + + +def fft_shift(complex_matrix): + nc = complex_matrix.getNcol() + nr = complex_matrix.getNrow() + out = ComplexMatrix(nr, nc) + midi = int(math.floor(nc / 2.0)) + offi = int(math.ceil(nc / 2.0)) + midj = int(math.floor(nr / 2.0)) + offj = int(math.ceil(nr / 2.0)) + for j in range(nr): # for (int j = 0; j < nr; j ++){ + for i in range(nc): # for (int i = 0; i < nc; i++) { + if j < midj: + if i < midi: + out.setElement(j, i, complex_matrix.getElementReference(j + offj, i + offi)) + else: + out.setElement(j, i, complex_matrix.getElementReference(j + offj, i - midi)) + else: + if i < midi: + out.setElement(j, i, complex_matrix.getElementReference(j - midj, i + offi)) + else: + out.setElement(j, i, complex_matrix.getElementReference(j - midj, i - midi)) + return out + + +def ifft_shift(complex_matrix): + nc = complex_matrix.getNcol() + nr = complex_matrix.getNrow() + out = ComplexMatrix(nr, nc) + midi = int(math.ceil(nc / 2.0)) + offi = int(math.floor(nc / 2.0)) + midj = int(math.ceil(nr / 2.0)) + offj = int(math.floor(nr / 2.0)) + + for j in range(nr): # (int j = 0; j < nr; j ++){ + for i in range(nc): # for (int i = 0; i < nc; i++) { + if j < midj: + if i < midi: + out.setElement(j, i, complex_matrix.getElementReference(j + offj, i + offi)) + else: + out.setElement(j, i, complex_matrix.getElementReference(j + offj, i - midi)) + else: + if i < midi: + out.setElement(j, i, complex_matrix.getElementReference(j - midj, i + offi)) + else: + out.setElement(j, i, complex_matrix.getElementReference(j - midj, i - midi)) + return out; + + +def ifft_shift_real(matrix): + nc = matrix.getNcol() + nr = matrix.getNrow() + out = Matrix (nr, nc) + + midi = int(math.ceil(nc/2.0)) + offi = int(math.floor(nc/2.0)) + midj = int(math.ceil(nr/2.0)) + offj = int(math.floor(nr/2.0)) + + for j in range(nr): # for (int j = 0; j < nr; j ++){ + for i in range(nc): #for (int i = 0; i < nc; i++) { + if j < midj: + if i < midi: + out.setElement(j, i, matrix.getElement(j+offj, i+offi)) + else: + out.setElement(j, i, matrix.getElement(j+offj, i-midi)) + else: + if i < midi: + out.setElement(j, i, matrix.getElement(j-midj, i+offi)) + else: + out.setElement(j, i, matrix.getElement(j-midj, i-midi)) + return out + + + +# compute 2D fft from an image +def fft2(data): + h =len(data) + w = len(data[0]) + fft = DoubleFFT_2D(h, w) + fft.realForward(data) + return fft_array_2d_to_complex_matrix(data, h, w) + +# compute complex 2D fft from an image +def cfft2(data): + h = len(data) + w = len(data[0]) + fft = DoubleFFT_2D(h, w/2) + fft.complexForward(data) + return fft_complex_array_2d_to_complex_matrix(data, h, w/2) +# compute inverse 2D fft from a complex matrix +def ifft2(m): + w = m.getNcol() + h = m.getNrow() + fft = DoubleFFT_2D(h, w) + data = complex_matrix_to_fft_array_2d(m) + fft.realInverse(data, True) + return data + +# compute complex inverse 2D fft from a complex matrix +def cifft2(m): + w = m.getNcol() + h = m.getNrow() + fft = DoubleFFT_2D(h, w) + data = new_array('d', h, 2 * w) # new double[h][2*w]; + for j in range(h): # for (int j=0; j max: + max = m.getElementReference(j, i).abs() + realmax = m.getElementReference(j, i).getReal() + imagmax = m.getElementReference(j, i).getImag() + rmax = j + cmax = i + res = new_array("d", 5) + res[0] = math.sqrt(realmax * realmax + imagmax * imagmax) + res[1] = rmax + res[2] = cmax + res[3] = realmax + res[4] = imagmax + return res; + + +def sum_square_abs(m): + s = 0.0 + for j in range(m.getNrow()): # (int j = 0; j < m.getNrow(); j ++): + for i in range(m.getNcol()): # for (int i = 0; i < m.getNcol(); i++): + s += m.getElementReference(j, i).squareAbs(); + return s; + + +def dftups(complex_matrix, nor, noc, roff, coff, usfac): + # function out=dftups(in,nor,noc,usfac,roff,coff); + # Upsampled DFT by matrix multiplies, can compute an upsampled DFT in justa small region. + # usfac Upsampling factor (default usfac = 1) + # [nor,noc] Number of pixels in the output upsampled DFT, in + # units of upsampled pixels (default = size(in)) + # roff, coff Row and column offsets, allow to shift the output array to + # a region of interest on the DFT (default = 0) + # Recieves DC in upper left corner, image center must be in (1,1) + # Loic Le Guyader - Jun 11, 2011 Java version for ImageJ plugin + # Manuel Guizar - Dec 13, 2007 + # Modified from dftus, by J.R. Fienup 7/31/06 + + # This code is intended to provide the same result as if the following + # operations were performed + # - Embed the array "in" in an array that is usfac times larger in each + # dimension. ifftshift to bring the center of the image to (1,1). + # - Take the FFT of the larger array + # - Extract an [nor, noc] region of the result. Starting with the + # [roff+1 coff+1] element. + + # It achieves this result by computing the DFT in the output array without + # the need to zeropad. Much faster and memory efficient than the + # zero-padded FFT approach if [nor noc] are much smaller than [nr*usfac nc*usfac] + + nr = complex_matrix.getNrow() + nc = complex_matrix.getNcol() + # Compute kernels and obtain DFT by matrix products + amplitude = -2.0 * math.pi / (nc * usfac) + nor,noc=int(nor),int(noc) + u = Matrix(nc, 1) + for i in range(nc): # (int i = 0; i < nc; i++) { + u.setElement(i, 0, i - math.floor(nc / 2.0)) + u = ifft_shift_real(u) + + v = Matrix(1, noc) + for i in range(noc): # for (int i = 0; i < noc; i++) { + v.setElement(0, i, i - coff) + + phase = u.times(v) + kernc = ComplexMatrix(nc, noc) + for j in range(nc): # for (int j = 0; j < nc; j++) { + for i in range(noc): # for (int i = 0; i < noc; i++) { + t = Complex() + t.polar(1.0, amplitude * phase.getElement(j, i)); + kernc.setElement(j, i, t) + + # ComplexMatrixPrint(kernc) + amplitude = -2.0 * math.pi / (nr * usfac) + + w = Matrix(nor, 1) + for i in range(nor): # for (int i = 0; i < nor; i++) { + w.setElement(i, 0, i - roff) + + x = Matrix(1, nr) + for i in range(nr): # for (int i = 0; i < nr; i++) { + x.setElement(0, i, i - math.floor(nr / 2.0)) + x = ifft_shift_real(x) + + nphase = w.times(x); + kernr = ComplexMatrix(nor, nr) + for j in range(nor): # for (int j = 0; j < nor; j++) { + for i in range(nr): # for (int i = 0; i < nr; i++) { + t = Complex(); + t.polar(1.0, amplitude * nphase.getElement(j, i)) + kernr.setElement(j, i, t) + # ComplexMatrixPrint(kernr); + return kernr.times(complex_matrix.times(kernc)) + +def dft_registration(ref, drifted, usfac): + m = ref.getNrow() + n = ref.getNcol() + output = new_array('d', 4) # new double[4] + + # First upsample by a factor of 2 to obtain initial estimate + # Embed Fourier data in a 2x larger array + mlarge = m * 2 + nlarge = n * 2 + large = ComplexMatrix(mlarge, nlarge) + c = fft_shift(element_product(ref, drifted.conjugate())) + + for j in range(m): # (int j = 0; j < m; j++): + for i in range(n): # (int i = 0; i < n; i++): + large.setElement(int(j + m - math.floor(m / 2.0)), int(i + n - math.floor(n / 2.0)), c.getElementReference(j, i)) + + # Compute crosscorrelation and locate the peak + CC = cifft2(ifft_shift(large)); + peak = c_find_peak(CC); # max, r, c, max_r, max_c + # Obtain shift in original pixel grid from the position of the + # crosscorrelation peak + if peak[1] > m: + peak[1] = peak[1] - mlarge; + if peak[2] > n: + peak[2] = peak[2] - nlarge; + # If upsampling > 2, then refine estimate with matrix multiply DFT + if usfac > 2: + # DFT computation + # Initial shift estimate in upsampled grid + row_shift = round(peak[1] / 2.0 * usfac) / usfac + col_shift = round(peak[2] / 2.0 * usfac) / usfac + dftshift = math.floor(math.ceil(usfac * 1.5) / 2) # Center of output array at dftshift+1 + # Matrix multiply DFT around the current shift estimate + cm = element_product(drifted, ref.conjugate()) + nCC = dftups(cm, math.ceil(usfac * 1.5), math.ceil(usfac * 1.5), \ + dftshift - row_shift * usfac, dftshift - col_shift * usfac, usfac) + nCC = nCC.times(1.0 / (m * n * usfac * usfac)).conjugate() + # Locate maximum and map back to original pixel grid + npeak = c_find_peak(nCC) # max_r, max_i, r, c + mrg00 = dftups(element_product(ref, ref.conjugate()), 1, 1, 0, 0, usfac) + rg00 = mrg00.getElementReference(0, 0).abs() / (m * n * usfac * usfac) + mrf00 = dftups(element_product(drifted, drifted.conjugate()), 1, 1, 0, 0, usfac) + rf00 = mrf00.getElementReference(0, 0).abs() / (m * n * usfac * usfac) + npeak[1] = npeak[1] - dftshift + npeak[2] = npeak[2] - dftshift + output[0] = math.sqrt(abs(1.0 - npeak[0] * npeak[0] / (rg00 * rf00))) # error + output[1] = math.atan2(npeak[4], npeak[3]) # diffphase + output[2] = row_shift + npeak[1] / usfac # delta row + output[3] = col_shift + npeak[2] / usfac # delta col + else: + # If upsampling = 2, no additional pixel shift refinement + rg00 = sum_square_abs(ref) / (mlarge * nlarge) + rf00 = sum_square_abs(drifted) / (mlarge * nlarge) + output[0] = math.sqrt(abs(1.0 - peak[0] * peak[0] / (rg00 * rf00))) # error + output[1] = math.atan2(peak[4], peak[3]) # diffphase + output[2] = peak[1] / 2.0 # delta row + output[3] = peak[2] / 2.0 # delta col + return output + + +def calculate_shifts(imp_r, imp_i, roi, upscale_factor=100, reference_slide=1, java_code=False): + if roi is None or roi.bounds.minX <0 or roi.bounds.minY<0 or roi.bounds.maxX>=imp_r.width or roi.bounds.maxY>=imp_r.height: + raise Exception("Invalid roi: " + str(roi)) + if java_code: + get_context().getPluginManager().loadInitializePlugin("Align_ComputeShifts2.java") + compute_shifts_filter = get_context().getClassByName("Align_ComputeShifts2").newInstance() + compute_shifts_filter.setup(upscale_factor, False, imp_r, imp_i, 1, roi) + compute_shifts_filter.run(None) + return compute_shifts_filter.shifts + + IJ.showStatus("1/2 Perform FFT of each slice") + ffts = compute_fft(imp_r, imp_i, roi) + + # calculate shifts + IJ.showStatus("2/2 Calculate shifts between slices") + + shifts = new_array('d', len(ffts), 6) # new double[ffts.length][6]; + for i in range(len(ffts)): # (int i = 0; i < ffts.length; i++): + shifts[i][0] = reference_slide + shifts[i][1] = i + 1 + temp = dft_registration(ffts[reference_slide - 1], ffts[i], upscale_factor) + shifts[i][2] = temp[2] + shifts[i][3] = temp[3] + shifts[i][4] = temp[0] + shifts[i][5] = temp[1] + IJ.showProgress(i + 1, len(ffts))\ + return shifts # [ref, drifted, dr, dc, error, diffphase] + +def to_ip(obj): + if is_string(obj): + obj = open_image(obj) + else: + if type(obj) == Data: + obj = obj.toBufferedImage(False) + if type(obj) == BufferedImage: + obj = load_image(obj) + return obj + +def calculate_shift(ref,img, roi, g_sigma=3.0, upscale_factor=100): + ref = to_ip(ref) + img = to_ip(img) + stack = create_stack([ref,img]) + ipr, ipi = complex_edge_filtering(stack, g_sigma=g_sigma, show=False) + shifts = calculate_shifts(ipr, ipi, roi, upscale_factor=upscale_factor, java_code=True) + xoff, yoff = shifts[1][3], shifts[1][2] + error, diffphase = shifts[1][4], shifts[1][5] + return xoff, yoff, error, diffphase + + +roi=Roi(256,0,128,128) +stack = load_test_stack(show=False, size=9) +ipr, ipi = complex_edge_filtering(stack, show=False) +shifts = calculate_shifts(ipr, ipi, roi, java_code=True) +#shifts= load_shifts("{images}/TestObjAligner/shifts.mat") +#stack = load_test_stack(show=True) +r=translate(stack, shifts, show=True) \ No newline at end of file diff --git a/script/jep/testdevs.py b/script/jep/testdevs.py new file mode 100644 index 0000000..195d2a5 --- /dev/null +++ b/script/jep/testdevs.py @@ -0,0 +1,45 @@ +from jep import jproxy +import random + +class WritableScalar(): + def write(self, value): + print ("Write: ", value) + +class ReadableScalar(): + def read(self): + print ("Read") + return random.random() + + +class ReadableWaveform(): + def getSize(self): + return 20 + + def read(self): + ret = [] + for i in range (self.getSize()): + ret.append(random.random()) + return ret + +class ReadableImage(): + def read(self): + ret = [] + for i in range (self.getHeight()): + ret.append([random.random()] * self.getWidth()) + return to_array(ret, 'd') + + def getWidth(self): + return 80 + + def getHeight(self): + return 40 + + + +ws1 = jproxy(WritableScalar(), ['ch.psi.pshell.device.Writable']) +rs1 = jproxy(ReadableScalar(), ['ch.psi.pshell.device.Readable']) +rw1 = jproxy(ReadableWaveform(), ['ch.psi.pshell.device.Readable$ReadableArray']) +ri1 = jproxy(ReadableImage(),['ch.psi.pshell.device.Readable$ReadableMatrix']) + +tscan(rs1, 10, 0.1) +lscan(ws1, rs1, 0.0, 10.0, 10) \ No newline at end of file diff --git a/script/local.py b/script/local.py index 5581d57..67abb6c 100755 --- a/script/local.py +++ b/script/local.py @@ -1,10 +1,45 @@ +# TESTIOC:TESTSINUS:SinCalc +# TESTIOC:TESTWF2:MyWF +# TESTIOC:TESTCALCOUT:Input +# TESTIOC:TESTCALCOUT:Output #get_context().dataManager.provider.embeddedAtributes = False #get_context().dataManager.provider.ADD_ATTRIBUTE_FILE_TIMESTAMP = True ################################################################################################### # EPICS utilities -################################################################################################### +############## +##################################################################################### + +if get_context().getScriptType()==ScriptType.cpy: + def on_ctrl_cmd(cmd): + global RE + print ("Control command: ", cmd) + if cmd=="abort": + if "RE" in globals(): + if RE.state not in ['idle','paused', 'pausing']: + print ("Run Engine pause request") + RE.request_pause() + abort() + +def otf(mode="ENERGY", e1=None, e2=None, beta1=None, beta2=None, theta1=None, theta2=None, \ + time=1.0, modulo=1, turn_off_beam=False): + """ + mode: "ENERGY" or "AMNGLE" + """ + run("otf", {"E1":450.0, "E2":460.0}) + run("otf", { + "MODE":mode, \ + "E1":float(e1) if e1 is not None else None, \ + "E2":float(e2) if e2 is not None else None, \ + "BETA1":float(beta1) if beta1 is not None else None, \ + "BETA2":float(beta2) if beta2 is not None else None, \ + "THETA1":float(theta1) if theta1 is not None else None, \ + "THETA2":float(theta2) if theta2 is not None else None, \ + "TIME":float(time), \ + "MODULO":int(modulo), \ + "ENDSCAN":turn_off_beam, \ + }) def caget_str(ch): return ''.join((chr(i) if i else "") for i in caget(ch)) @@ -73,17 +108,47 @@ def on_command_started(info): def on_command_finished(info): pass #print "Finished: " + str(info.script) + " Error: " + str(info.error) def on_change_data_path(path): - print "Data path: " + str(path) + #print "Data path: " + str(path) + pass def on_session_started(id): - print "Start session: ", id + #print "Start session: ", id get_context().sessionManager.setMetadata("beamlineState", {"sin": sin.take(), "inp": inp.take()}) get_context().sessionManager.setMetadata("beamlineState2", {"sin": sin.take(), "inp": inp.take()}) def on_session_finished(id): - print "Stop session: ", id + #print "Stop session: ", id get_context().sessionManager.setMetadata("scientificMetadata",SCI_METADATA) get_context().sessionManager.setMetadata("scientificMetadata2",SCI_METADATA) + + +################################################################################################### +# Image filters +################################################################################################### + +class DataFilter(Filter.DataFilter): + def process(self, data): + data=data.copy() + data.mult(2.0) + return data + +data_filter = DataFilter("filter") +image.addListener(data_filter) +proc_data=ColormapAdapter("proc_data", data_filter) +add_device(proc_data, True) + + +class ImageFilter(Filter.ImageFilter): + def process(self, img): + return ImagingUtils.transpose(img) + +image_filter = ImageFilter("filter") +image.addListener(image_filter) +#proc_image=ColormapAdapter("proc_image", image_filter) +add_device(image_filter, True) + +image.refresh() + @@ -144,6 +209,7 @@ import random #State listener: cleanup can be made at end of execution def onStateChange(state, former, script): + #print state if state == State.Closing: #print "Closing the app" pass @@ -180,20 +246,26 @@ class SimulatedOutput(Writable): def write(self, value): pass + def getName(self): + return "sout" -class SimulatedInput(Readable): +#class SimulatedInput(Readable): +class SimulatedInput(ReadonlyRegisterBase): def __init__(self): self.x = 0.0 - def read(self): + #def read(self): + def doRead(self): self.x = self.x + 0.1 noise = (random.random() - 0.5) / 20.0 return math.sin(self.x) + noise - + def getName(self): + return "sinp" + sout = SimulatedOutput() sinp = SimulatedInput() - +add_device(sinp, True) #for m in mu, delta, gamma, eta, chi, phi: # m.setSpeed(m.config.defaultSpeed) #Controler Evenrt Listener @@ -632,6 +704,9 @@ scan_val.set([0.0,] * MAX_ARRAY_DEV_SIZE ) #cas6= CAS("PSHELL:var",sin) """ +#show_panel(master) + + def plot_numpy_array(na, title = None): plot( Convert.reshape(na.getData(),na.getDimensions()),title=title) @@ -646,7 +721,6 @@ def run_fda(file_name, arguments={}): - #Convex hull plots def clear_convex_hull_plot(title): plots = get_plots(title = title) @@ -893,4 +967,132 @@ class Counter(ReadonlyRegisterBase): add_device(Counter("counter"), True) - \ No newline at end of file + + +def trigger_scienta(): + """ + Trigger new acquisition + """ + scienta.start() + #scienta.waitNewImage(-1) + + + +################################################################################################### +# Handlig diagnostics +################################################################################################### + +################################################################################################### +# Handlig diagnostics +################################################################################################### + +class AcquisitionMode(Readable.ReadableString): + def read(self): + return str(scienta.getAcquisitionMode()) +_acquisition_mode=AcquisitionMode() + +class EnergyMode(Readable.ReadableString): + def read(self): + return str(scienta.getEnergyMode()) +_energy_mode=EnergyMode() + +class LensMode(Readable.ReadableString): + def read(self): + return str(scienta.getLensMode()) +_lens_mode=LensMode() + +class DetectorMode(Readable.ReadableString): + def read(self): + return str(scienta.getDetectorMode()) +_detector_mode=DetectorMode() + +class PassEnergy(Readable): + def read(self): + return scienta.getPassEnergy() +_pass_energy=PassEnergy() + +class ElementSet(Readable.ReadableString): + def read(self): + return str(scienta.getElementSet()) +_element_set=ElementSet() + +diag_channels = [] + +diag_channels.append(scienta.lowEnergy) +diag_channels.append(scienta.centerEnergy) +diag_channels.append(scienta.highEnergy) +diag_channels.append(scienta.energyWidth) + +diag_channels.append(_acquisition_mode) +diag_channels.append(_energy_mode) +diag_channels.append(_lens_mode) +diag_channels.append(_detector_mode) +diag_channels.append(_pass_energy) +diag_channels.append(_element_set) + + +diag_channels = sorted(diag_channels, key=lambda channel: channel.name) + +def get_diag_name(diag): + return ch.psi.utils.Str.toTitleCase(diag.getName()).replace(" ", "").replace("Readback", "") + +def print_diag(): + for f in diag_channels: + print "%-25s %s" % (get_diag_name(f) , str(f.read())) + +def create_diag_datasets(parent = None): + if parent is None: + parent = get_exec_pars().group + group = parent + "attrs/" + for f in diag_channels: + create_dataset(group+get_diag_name(f) , 's' if (issubclass(type(f), Readable.ReadableString)) else 'd') + +def append_diag_datasets(parent = None): + if parent is None: + parent = get_exec_pars().group + group = parent + "attrs/" + for f in diag_channels: + try: + x = f.read() + if x is None: + x = '' if (type(f) is ch.psi.pshell.epics.ChannelString) else float('nan') + append_dataset(group+get_diag_name(f), x) + except: + log("Error sampling " + str(get_diag_name(f)) + ": " + str(sys.exc_info()[1])) + + +def handle_diagnostics(rec): + #if beam_ok: + if get_exec_pars().save: + #Saving only once the diag data + if rec.index == 0: + create_diag_datasets() + append_diag_datasets() + + +def scan_2d(range_x, range_y, steps_x, steps_y, exposures=None, settling_time=0.1, zigzag=True, compression=False, dry_run=False): + if type(range_x)==float: range_x =[-range_x, range_x] + if type(range_y)==float: range_y =[-range_y, range_y] + return run("templates/Scan2D", { \ + "DRY_RUN": dry_run, \ + "RANGE_X": range_x, \ + "RANGE_Y": range_y, \ + "STEPS": [steps_x, steps_y], \ + "EXPOSURES": exposures, \ + "SETTLING_TIME": settling_time, \ + "ZIGZAG": zigzag, \ + "COMPRESSION": compression + }) + + +""" +add_device(PipelineStream("p","localhost:8889", "simulation_sp"), True) +p.monitored=True + +s=p.createSubsampled(1.0) +#show_panel(s) +show_panel(p) +""" + +print "Finished initialization" + \ No newline at end of file diff --git a/script/otf.py b/script/otf.py new file mode 100644 index 0000000..9f6dbf4 --- /dev/null +++ b/script/otf.py @@ -0,0 +1,103 @@ +#Debugging +if get_exec_pars().innerArgs is None: + E1 = 975 + E2 = 985 + TIME = 1 #min + DELAY = 0.0 #s + MODE = None #'LINEAR' #'CIRC +' + OFFSET = None + NAME = 'predefined' + ALPHA= None #0 + + + +print "\nStart energy scan..." +print E1,"eV ->",E2,"eV,",TIME,"min duration,",DELAY,"sec delay,",str(MODE),(str(ALPHA)+"deg") if (MODE=="LINEAR") else "" + +set_exec_pars(reset=True, name= NAME) + + + +call_mscan=True +move_mono=False # if true, X-Tremeo runs, if false channel defiend under Ch runs + + +#Scan +print "Start OTF" +scan_completed = False + +try: + while True: + waiting = True + + class Time(Readable): + def __init__(self): + self.start = time.time() + def read(self): + return time.time()-self.start + tm = Time() + + class norm_tey(Readable): + def read(self): + return float(cadc1.take())/float(cadc2.take()) + + class norm_diode(Readable): + def read(self): + return float(cadc3.take())/float(cadc2.take()) + # define channels for PGM paramters + + position=sin + + + snaps = () + diags = () #Must use cache because mscan evensts are called from monitor callback tread (or else async=False). Sensors are automatically handled. + sensors = [position,out] + + def monitoring_task(): + global scan_completed + time.sleep(3.0) + + scan_completed = True + print('Scan completed ' + str(get_exec_pars().currentScan)) + global scans + scans.append(get_exec_pars().currentScan) + get_exec_pars().currentScan.abort() + print('after abort ') + + def before_pass(pass_num, scan): + print "Starting scan: " + str(scan) + + monitoring_future = fork(monitoring_task)[0] + + print("Scanning...\n") + try: + if call_mscan==True: + print('call mscan ') + mscan( position, sensors, -1, None, \ + range="auto",domain_axis=position.name, + snaps=snaps, diags=diags, before_pass=before_pass) + else: + print('-------------------------------------') + print('DO NOT CALL mscan ') + print('-------------------------------------') + #endelse + finally: + print('.....mscan done ') + if not scan_completed: + print('... cancel monitoring_future..') + monitoring_future.cancel(True) + print('monitoring is done',monitoring_future.isDone()) + print "Finished Energy scan." + if after_sample(): #Repeat if id error and not ABORT_ON_ID_ERROR: + break + +except: + if not scan_completed: + print sys.exc_info() + raise + #endif +#endexcept +print('-------DONE --------------') +# Finally, if mon is not use +# return to initial position + diff --git a/script/outupdate.py b/script/outupdate.py index 7808f16..f9058a2 100644 --- a/script/outupdate.py +++ b/script/outupdate.py @@ -1,5 +1,5 @@ -for i in range(100): +for i in range(20): out.write(i) time.sleep(0.1) \ No newline at end of file diff --git a/script/queues/mxas.que b/script/queues/mxas.que new file mode 100644 index 0000000..c2ccf2a --- /dev/null +++ b/script/queues/mxas.que @@ -0,0 +1 @@ +[ [ [ false, "/sls/X05LA/Data1/x05laop/2021_10/20211024/ScanX_vsAngle_Energy1_XRF_NoMythen_10s_60deg_AudioTape_x5_vXX.xml", "", "Resume", "Aborted" ], [ false, "/sls/X05LA/Data1/x05laop/2021_10/20211024/ScanX_vsAngle_Energy2_XRF_NoMythen_10s_60deg_AudioTape_x5_vXX.xml", "", "Resume", "" ], [ false, "/sls/X05LA/Data1/x05laop/2021_10/20211024/ScanX_vsAngle_Energy1_XRF_WithMythen_10s_60deg_AudioTape_x5_vXX.xml", "", "Resume", "" ], [ false, "/sls/X05LA/Data1/x05laop/2021_10/20211024/ScanX_vsAngle_Energy2_XRF_WithMythen_10s_60deg_AudioTape_x5_vXX.xml", "", "Resume", "" ], [ false, "/sls/X05LA/Data1/x05laop/2021_10/20211024/ScanX_vsAngle_Energy1_XRF_WithMythen_10s_60deg_AudioTape_x5_vXX.xml", "", "Resume", "" ], [ false, "/sls/X05LA/Data1/x05laop/2021_10/20211027/XRD_XRF_otf_200ms_17995eV_XY_LYPC.xml", "", "Resume", "" ], [ false, "/sls/X05LA/Data1/x05laop/2021_10/20211027/XRD_XRF_otf_200ms_17995eV_XY_LYPC.xml", "", "Resume", "" ], [ true, "/sls/X05LA/Data1/x05laop/2021_10/20211027/XRD_XRF_otf_200ms_17995eV_XY_LYPC.xml", "", "Resume", "" ] ] ] \ No newline at end of file diff --git a/script/queues/q5.que b/script/queues/q5.que new file mode 100644 index 0000000..d8df839 --- /dev/null +++ b/script/queues/q5.que @@ -0,0 +1 @@ +[ [ [ true, "", "print 1", "Resume", "Success" ], [ true, "queues/q4.que", "", "Resume", "Success" ], [ true, "Test.xml", "", "Resume", "Success" ], [ true, "test/test0.py", "", "Resume", "Failure" ], [ true, "test/test1.py", "", "Resume", "Success" ], [ true, "", "sleep(5.0)", "Resume", "Success" ], [ true, "", "print 2", "Resume", "Success" ], [ true, "", "sleep(0.5)", "Resume", "Success" ], [ true, "", "print 3", "Resume", "Success" ], [ true, "", "sleep(0.5)", "Resume", "Success" ], [ true, "", "print 4", "Resume", "Success" ], [ true, "", "sleep(0.5)", "Resume", "Success" ], [ true, "", "print 5", "Resume", "Success" ], [ true, "", "i=0", "Resume", "Success" ], [ true, "queues/q6.que", "", "Resume", "Success" ], [ false, "queues/q6.que", "", "Resume", "Disabled" ], [ false, "queues/q6.que", "", "Resume", "Disabled" ], [ false, "queues/q6.que", "", "Resume", "Disabled" ] ] ] \ No newline at end of file diff --git a/script/queues/q6.que b/script/queues/q6.que new file mode 100644 index 0000000..8164f36 --- /dev/null +++ b/script/queues/q6.que @@ -0,0 +1 @@ +[ [ [ true, "", "i=i+1", "Resume", "" ], [ true, "", "print \"###>\"+str(i)", "Resume", "" ], [ true, "", "print 10", "Resume", "" ], [ true, "", "sleep(0.25)", "Resume", "" ], [ true, "", "print 20", "Resume", "" ], [ true, "", "sleep(0.25)", "Resume", "" ], [ true, "", "print 30", "Resume", "" ], [ true, "", "sleep(0.25)", "Resume", "" ], [ true, "", "print 40", "Resume", "" ], [ true, "", "sleep(0.25)", "Resume", "" ], [ true, "", "print 50", "Resume", "" ], [ true, "", "sleep(0.25)", "Resume", "" ], [ true, "", "print 60", "Resume", "" ], [ true, "", "print \"--->\"+str(i)", "Resume", "" ] ] ] \ No newline at end of file diff --git a/script/queues/qt.que b/script/queues/qt.que new file mode 100644 index 0000000..d52d895 --- /dev/null +++ b/script/queues/qt.que @@ -0,0 +1 @@ +[ [ [ true, "test/test1.py", "", "Abort", "Success", "00:00:01" ], [ true, "test/test3.py", "", "Resume", "Aborted", "00:00:02" ], [ true, "test/test3.py", "", "Resume", "", "00:00:03" ] ] ] \ No newline at end of file diff --git a/script/queues/tst.que b/script/queues/tst.que new file mode 100644 index 0000000..fae509c --- /dev/null +++ b/script/queues/tst.que @@ -0,0 +1 @@ +[ [ [ false, "test_manip.xml", "", "Resume", "" ], [ false, "test_function_script.xml", "", "Resume", "" ], [ true, "BugSuperXAS.xml", "", "Resume", "" ], [ false, "testy.xml", "", "Resume", "" ], [ false, "xxx.xml", "", "Resume", "" ], [ false, "test/BugPhenix.xml", "", "Resume", "" ], [ false, "test/test_manip.xml", "", "Resume", "" ], [ false, "test/test_function_script.xml", "", "Resume", "" ], [ true, "test/BugSuperXAS.xml", "", "Resume", "" ], [ false, "test/testy.xml", "", "Resume", "" ], [ false, "test/xxx.xml", "", "Resume", "" ], [ false, "test/BugPhenix.xml", "", "Resume", "" ] ] ] \ No newline at end of file diff --git a/script/runotf.py b/script/runotf.py new file mode 100644 index 0000000..8ea1206 --- /dev/null +++ b/script/runotf.py @@ -0,0 +1,30 @@ +import traceback +import imp +import os +import time +import string +import sys +import json + + +def otf(start, end, time, delay=0.0, mode = None, offset = None, alpha = None, name = None): + """ + """ + # print('in otf',name) + + if name is None: + name = get_exec_pars().name + + if len(name)> 38: + name = name[:38] + print('WARNING: Sample name too long. Name has been truncated.') + + #print('in otf, call run \n') + run("otf", {"E1":start, "E2":end, "TIME":time, "DELAY":float(delay), "MODE":mode, "OFFSET":(offset), "NAME":name, "ALPHA":float(alpha) if alpha is not None else None}) + print('in otf, after run \n') + + + +for i in range(5): + print "----- RUN " + str(i) + otf(i, i+1, 3, delay=0.0, mode = None, offset = None, alpha = None, name = "scan"+str(i)) \ No newline at end of file diff --git a/script/scitest/.DS_Store b/script/scitest/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/script/scitest/.DS_Store differ diff --git a/script/templates/Scan2D.py b/script/templates/Scan2D.py new file mode 100644 index 0000000..6b9810b --- /dev/null +++ b/script/templates/Scan2D.py @@ -0,0 +1,70 @@ +""" +Arguments: +DRY_RUN = True +RANGE_X (tuple (min, max)) +RANGE_Y (tuple (min, max)) +STEPS (tuple (x, y)) +EXPOSURES (list or None) +SETTLING_TIME (double) +ZIGZAG (BOOLEAN) +COMPRESSION (BOOLEAN) +""" + +#Deug +if (get_exec_pars().args is None) and (get_exec_pars().script=="Scan2D"): + DRY_RUN = True + RANGE_X = [-10.0,10.0] + RANGE_Y = [-10.0,10.0] + EXPOSURES = None # [0.1, 0.5, 1.0] + STEPS = [5, 5] #Integers = number of steps, Float = stepoSize + SETTLING_TIME = 0.1 + ZIGZAG = True + COMPRESSION = False + +print DRY_RUN + +SENSORS = [sin, scienta.dataMatrix] +MOTORS = [m1, m2] +RELATIVE = True +START = [RANGE_X[0], RANGE_Y[0]] +STOP = [RANGE_X[1], RANGE_Y[1]] +ENABLED_PLOTS= [sin, scienta.dataMatrix] +CUSTOM_PLOT_TYPES = {scienta.dataMatrix:"ch.psi.pshell.plot.MatrixPlotRenderer"} + + + +if EXPOSURES: + class exposure_index (Writable, Readable): + def __init__(self): + self.pos=0.0 + + def read(self): + return self.pos + + def write(self, value): + scienta.setExposure(EXPOSURES[int(value)]) + self.pos = value + + class exposure (Readable): + def read(self): + return scienta.exposure + + POSITIONERS = MOTORS + [exposure_index()] + _SENSORS = SENSORS + [exposure()] + START = START + [0.0] + STOP = STOP + [float(len(POSITIONERS)-1)] + + + + +if EXPOSURES: + r = ascan(POSITIONERS, _SENSORS , START, STOP, STEPS + [1.0], \ + SETTLING_TIME, RELATIVE, zigzag = ZIGZAG, \ + compression = COMPRESSION, enabled_plots=ENABLED_PLOTS, \ + save=False,keep=False, check_positions=False, plot_types=CUSTOM_PLOT_TYPES) +else: + r = ascan(MOTORS, SENSORS , START, STOP, STEPS, \ + SETTLING_TIME, RELATIVE, zigzag = ZIGZAG, \ + compression = COMPRESSION, enabled_plots=ENABLED_PLOTS, \ + save=False,keep=False, check_positions=False, plot_types=CUSTOM_PLOT_TYPES) +set_return(t) diff --git a/script/test/.DS_Store b/script/test/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/script/test/.DS_Store differ diff --git a/script/test/2022_0812_092647_XAS_V_L1677_CN.xml b/script/test/2022_0812_092647_XAS_V_L1677_CN.xml new file mode 100644 index 0000000..2e5d808 --- /dev/null +++ b/script/test/2022_0812_092647_XAS_V_L1677_CN.xml @@ -0,0 +1,759 @@ + + + + + + + + + + + + + + + + + + + + + + + 5365.0 + 5460.0 + 2.0 + + + + 5461.0 + 5520.0 + 0.3 + + + + 3.83209893521 + 15.0 + 0.05 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -9.705 + + + -21.5176 + + + 1.0 + + + 1.0 + + + 70.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/script/test/BugJep2.py b/script/test/BugJep2.py new file mode 100644 index 0000000..08cf484 --- /dev/null +++ b/script/test/BugJep2.py @@ -0,0 +1,22 @@ +writables=inp +readables= (sin,out) +start = 0 +end =40 +steps =50 +latency=0.2 +relative=False +passes=1 +zigzag=False + +latency_ms=int(latency*1000) +writables=to_list(string_to_obj(writables)) +readables=to_list(string_to_obj(readables)) +#start=to_list(start) +#end=to_list(end) +if type(steps) is float or is_list(steps): + steps = to_list(steps) +scan = scans.LineScan(writables,readables, start, end , steps, relative, latency_ms, int(passes), zigzag) +processScanPars(scan, pars) +scan.start() +ret= scan.getResult() + diff --git a/script/test/BugPhenix.xml b/script/test/BugPhenix.xml new file mode 100644 index 0000000..b162062 --- /dev/null +++ b/script/test/BugPhenix.xml @@ -0,0 +1,733 @@ + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 2.0 + 0.2 + + + + 2.0 + 3.0 + 0.3 + + + 4.0 + 5.0 + 0.4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + + + 1.0 + + + 1.0 + + + 1.0 + + + 1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/script/test/BugSuperXAS.xml b/script/test/BugSuperXAS.xml new file mode 100644 index 0000000..2bf4c79 --- /dev/null +++ b/script/test/BugSuperXAS.xml @@ -0,0 +1,249 @@ + + + + + + + + + + + + + -8.0 + 0.0 + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/script/test/BugSuperXASOrig.xml b/script/test/BugSuperXASOrig.xml new file mode 100644 index 0000000..c396d94 --- /dev/null +++ b/script/test/BugSuperXASOrig.xml @@ -0,0 +1,250 @@ + + + + + + + + + + + + + -8.0 + 0.0 + 0.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/script/test/DirectCamserverStream.py b/script/test/DirectCamserverStream.py new file mode 100644 index 0000000..1d7df36 --- /dev/null +++ b/script/test/DirectCamserverStream.py @@ -0,0 +1,6 @@ +st= Stream("st", "tcp://localhost:5554", SocketType.SUB) +m=st.addMatrix("image") +st.initialize() +st.start(True) + +show_panel(m) \ No newline at end of file diff --git a/script/test/LoadIJStack.py b/script/test/LoadIJStack.py new file mode 100644 index 0000000..f02cf59 --- /dev/null +++ b/script/test/LoadIJStack.py @@ -0,0 +1,8 @@ +from ijutils import * + + +ip_list = [] +for index in range(40,49): + ip_list.append(open_image(expand_path("{images}/TestObjAligner/i210517_0" + str(index) + "#001.tif"))) + +stack = create_stack(ip_list, title = "Test") diff --git a/script/test/TSTIMGSIM3.py b/script/test/TSTIMGSIM3.py new file mode 100644 index 0000000..3a41179 --- /dev/null +++ b/script/test/TSTIMGSIM3.py @@ -0,0 +1,32 @@ +import traceback +run ("imaging/sim") + +show=True + + + +stack = load_test_stack(show=False) +shifts= load_shifts("{images}/TestObjAligner/shifts.mat") + + +if show: + ret.show() + ret.updateAndDraw() +#stack = load_test_stack(show=True) +#get_context().getPluginManager().loadInitializePlugin("Align_TranslationFilter.java") +#translation_filter = get_context().getClassByName("Align_TranslationFilter").newInstance() +#shifts= load_shifts("{images}/TestObjAligner/shifts.mat") + +""" +translation_filter.shifts = shifts +pfr = PlugInFilterRunner(translation_filter, "", "" ) +ret = translation_filter.output +if show: + ret.show() + ret.updateAndDraw() +#stack = load_test_stack(show=False) +#r=translate(stack, shifts, True, java_code=True) +""" + + +#translate(stack, shifts, show=True, java_code=True) \ No newline at end of file diff --git a/script/test/Test2DCont.py b/script/test/Test2DCont.py new file mode 100644 index 0000000..8215643 --- /dev/null +++ b/script/test/Test2DCont.py @@ -0,0 +1,14 @@ +STEPS = 10 + +class Line(ReadonlyRegisterBase): + def doRead(self): + r1 = cscan(m1, (ai1), 0.0, 1.0 , steps=STEPS, save=False) + return r1[ai1] + + def getSize(self): + return STEPS+1 + +line=Line() + +lscan(ai2, line, 0, 10, 1.0) + diff --git a/script/test/TestArrayTestStats.py b/script/test/TestArrayTestStats.py new file mode 100644 index 0000000..61f178c --- /dev/null +++ b/script/test/TestArrayTestStats.py @@ -0,0 +1,24 @@ +#av=create_averager(arr,1,) +#print av.sum.read() +#tscan(av.sum, 10,0.1) + + + +#CHANNEL_NAME= "TESTIOC:TESTWF2:MyWF" +#tscan("ca://" + CHANNEL_NAME + "?op=sum", 10, 1.0) + + + +#av=create_averager(arr,1,) +#print av.sum.read() +#tscan(av.sum, 10,0.1) + + + +s = ArrayRegisterStats(arr.cache).sum +s.asyncUpdate=True +tscan((arr,s), 10,1.0) + + +#plot(ars.sum.read()) + diff --git a/script/test/TestAthosCamerasChannel.py b/script/test/TestAthosCamerasChannel.py new file mode 100644 index 0000000..0956e50 --- /dev/null +++ b/script/test/TestAthosCamerasChannel.py @@ -0,0 +1,10 @@ +class StringChannel(RegisterBase): + def doRead(self): + return self.val if hasattr(self, 'val') else "" + def doWrite(self, val): + self.val = val + + +reg=StringChannel() +reg.initialize() +cas3 = CAS("TESTCAS:CH", reg, 'string') \ No newline at end of file diff --git a/script/test/TestCPython.py b/script/test/TestCPython.py new file mode 100644 index 0000000..a04d851 --- /dev/null +++ b/script/test/TestCPython.py @@ -0,0 +1,47 @@ +run("CPython/wrapper") + +x=[0,1,2,3,4,5,6,7,8,9] +y=[1,2,3,6,9,6,3,2,1,0] +#(p, x_fit, y_fit, R2) = linfit(x,y) +#plot((y,y_fit), name=("data", "fit"),xdata=(x,x_fit)) + + +#x=to_array(x,'f') +#y=to_array(y,'f') + +def _from_npa(obj): + if isinstance(obj, jep.NDArray): + ret = obj.data + if len(obj.dimensions)>1: + ret=Convert.reshape(ret, obj.dimensions) + return ret + if isinstance(obj, java.util.List) or isinstance(obj,tuple) or isinstance(obj,list): + ret=[] + for i in range(len(obj)): + ret.append(_from_npa(obj[i])) + if isinstance(obj,tuple): + return type(ret) + return ret + return obj + +def _to_npa(obj): + if isinstance(obj, PyArray): + return to_npa(obj, dimensions = Arr.getShape(obj)) + if isinstance(obj, java.util.List) or isinstance(obj,tuple) or isinstance(obj,list): + ret=[] + for i in range(len(obj)): + ret.append(_to_npa(obj[i])) + if isinstance(obj,tuple): + return tuple(ret) + return ret + return obj + +def call_py(module, function, *args): + print _to_npa(args) + ret = call_jep(module, function, _to_npa(args)) + return _from_npa(ret) + +#ret = call_py("CPython/linfit", "linfit",x,y) +(p, x_fit, y_fit, R2) = call_py("CPython/linfit", "linfit",x,y) +#(p, x_fit, y_fit, R2) = linfit(x,y) +plot((y,y_fit), name=("data", "fit"),xdata=(x,x_fit)) \ No newline at end of file diff --git a/script/test/TestCmd.py b/script/test/TestCmd.py new file mode 100644 index 0000000..71d4fd6 --- /dev/null +++ b/script/test/TestCmd.py @@ -0,0 +1 @@ +exec_cmd("ls") \ No newline at end of file diff --git a/script/test/TestCompositeScan.py b/script/test/TestCompositeScan.py new file mode 100644 index 0000000..391021c --- /dev/null +++ b/script/test/TestCompositeScan.py @@ -0,0 +1,31 @@ +################################################################################################### +# This is an option to implement a 2D continuous scan +################################################################################################### + +STEPS_M1 = 10 +STEPS_M2 = 5 + +class Sensor(ReadableArray): + def read(self): + r1 = cscan(m1, (ai1), 0.0, 1.0 , steps=STEPS_M1, save=False, display=False) + return r1[ai1] + + def getSize(self): + return STEPS_M1+1 + + def getName(self): + return "sensor" + +""" +p = plot(None, title="2d Plot")[0] +def after_read(record, scan): + if record.setpoints[1] == scan.getStart()[1]: + p.addSeries(LinePlotSeries(str(record[ao1]))) + p.getSeries(p.numberOfSeries-1).appendData(record[ao2], record[ai1]) +""" + +set_exec_pars(print_scan=True) + +#lscan(m2, Sensor(), 0, 1.0, STEPS_M2, after_read=after_read) +s1=Sensor() +lscan(m2, s1, 0, 1.0, STEPS_M2) \ No newline at end of file diff --git a/script/test/TestConfig.py b/script/test/TestConfig.py new file mode 100644 index 0000000..0f06ac8 --- /dev/null +++ b/script/test/TestConfig.py @@ -0,0 +1,24 @@ +#Jython BUG: Sometimes getConfig(self) won'' override ProcessVariableBase.getConfig. +#E.g.: energy.getUnit() fails (calls getConfig) +#But energy.getConfig() works + + +class Energy(ControlledVariableBase): + def __init__(self, name): + ControlledVariableBase.__init__(self, name, None) + self.setReadback(phi.readback) + + def doRead(self): + return phi.read() + + def doWrite(self, val): + print "Do something" + phi.write(val) + + def getConfig(self): + print "Get" + return phi.getConfig() + + + +add_device(Energy("energy",), True) \ No newline at end of file diff --git a/script/test/TestData.py b/script/test/TestData.py index 578093b..f4d13e7 100644 --- a/script/test/TestData.py +++ b/script/test/TestData.py @@ -4,7 +4,7 @@ #Creating a 1D dataset from an array -path="group/data1" +path="data1" data1d = [1.0, 2.0, 3.0, 4.0, 5.0] save_dataset(path, data1d) #Reading ii back @@ -15,7 +15,7 @@ plot(read) #Creating a 2D dataset from an array with some attributes data2d = [ [1.0, 2.0, 3.0, 4.0, 5.0], [2.0, 3.0, 4.0, 5.0, 6.0, ], [3.0, 4.0, 5.0, 6.0, 7.0]] -path="group/data2" +path="data2" save_dataset(path, data2d) set_attribute(path, "AttrString", "Value") set_attribute(path, "AttrInteger", 1) @@ -28,7 +28,7 @@ plot(read) #Creating a 3D dataset from an array data3d = [ [ [1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7]], [ [3,2,3,4,5], [4,3,4,5,6], [5,4,5,6,7]]] -path="group/data3" +path="data3" save_dataset(path, data3d) #Reading it back read =load_data(path,0) @@ -37,28 +37,28 @@ read =load_data(path,1) print read.tolist() #Creating a INT dataset adding elements one by one -path = "group/data4" +path = "data4" create_dataset(path, 'i') for i in range(10): append_dataset(path,i) #Creating a 2D data FLOAT dataset adding lines one by one -path = "group/data5" +path = "data5" create_dataset(path, 'd', False, (0,0)) for row in data2d: append_dataset(path, row) #Creating a Table (compund type) -path = "group/data6" +path = "data6" names = ["a", "b", "c", "d"] -types = ["d", "d", "d", "[d"] +table_types = ["d", "d", "d", "[d"] lenghts = [0,0,0,5] table = [ [1,2,3,[0,1,2,3,4]], [2,3,4,[3,4,5,6,7]], [3,4,5,[6,7,8,9,4]] ] -create_table(path, names, types, lenghts) +create_table(path, names, table_types, lenghts) for row in table: append_table(path, row) flush_data() @@ -68,11 +68,11 @@ print read #Writing scalars (datasets with rank 0) -save_dataset("group/val1", 1) -save_dataset("group/val2", 3.14) -save_dataset("group/val3", "test") -print load_data("group/val1") -print load_data("group/val2") -print load_data("group/val3") +save_dataset("val1", 1) +save_dataset("val2", 3.14) +save_dataset("val3", "test") +print load_data("val1") +print load_data("val2") +print load_data("val3") diff --git a/script/test/TestDataToImage.py b/script/test/TestDataToImage.py new file mode 100644 index 0000000..d1cfe08 --- /dev/null +++ b/script/test/TestDataToImage.py @@ -0,0 +1,14 @@ +scale_min=100 +scale_max=150 +colormap = Colormap.Temperature #Colormap.Grayscale + + +while(True): + try: + i=image.data.toBufferedImage(scale_min, scale_max, colormap, False) + show_panel(i) + except: + print sys.exc_info()[2] + break + time.sleep(1.0) + \ No newline at end of file diff --git a/script/test/TestDiscretePositionerSelector.py b/script/test/TestDiscretePositionerSelector.py new file mode 100644 index 0000000..09d07ae --- /dev/null +++ b/script/test/TestDiscretePositionerSelector.py @@ -0,0 +1,24 @@ +import ch.psi.utils.swing.SwingUtils as SwingUtils +import ch.psi.pshell.swing.DiscretePositionerPanel as DiscretePositionerPanel +import ch.psi.pshell.swing.DiscretePositionerSelector as DiscretePositionerSelector +import ch.psi.pshell.swing.RegisterPanel as RegisterPanel + +""" +setp = scienta.getChannelCtrl()+":LENS_MODE" +rbck = scienta.getChannelCtrl()+":LENS_MODE_RBV" + +dp = DiscretePositioner("lens_mode", setp, rbck) +dp.monitored=True +add_device(dp, True) + + +pn=DiscretePositionerSelector() +pn.setDevice(dp) +SwingUtils.showDialog(App.getInstance().mainFrame, dp.name, None, pn) + +show_panel(dp) +""" +reg=sin #scienta.getEnergyStepSize() +rp=RegisterPanel() +rp.setDevice(None) +SwingUtils.showDialog(App.getInstance().mainFrame, reg.name, None, rp) diff --git a/script/test/TestImgMeasure.py b/script/test/TestImgMeasure.py new file mode 100644 index 0000000..5f60bd6 --- /dev/null +++ b/script/test/TestImgMeasure.py @@ -0,0 +1,6 @@ +class Measurement (ImageMeasurement): + def calc(self, data): + return data.getRoi(Rectangle(10,10,20,20)).integrate(False) + + +tscan(Measurement(src2, "roi"), 10, 0.2) \ No newline at end of file diff --git a/script/test/TestIndexReadback.py b/script/test/TestIndexReadback.py new file mode 100644 index 0000000..edec291 --- /dev/null +++ b/script/test/TestIndexReadback.py @@ -0,0 +1,31 @@ + + +def after_read(rec,scan): + print rec[energy], rec[sin] + + + +#r = mscan(energy, sin.cache, after_read=after_read) + + +#Execute the scan: sample undefined number of samples until a condition is met, with auto range +scan_completed=False +def after_read(record, scan): + global scan_completed + print record[sin] + if motor.isReady(): + scan_completed=True + scan.abort() + +motor.move(0.0) +motor.moveAsync(3.0) +try: + r = mscan(motor.readback, [motor.readback, sin.cache], after_read=after_read, range=[0.0, 3.0], domain_axis=motor.readback.name) +except ScanAbortedException as ex: + if not scan_completed: raise +motor.moveAsync(0.0) + +print r[sin] + +#print r[0][sin] +print r[0][motor.readback] \ No newline at end of file diff --git a/script/test/TestJEP.py b/script/test/TestJEP.py new file mode 100644 index 0000000..b39f6af --- /dev/null +++ b/script/test/TestJEP.py @@ -0,0 +1,21 @@ +from jeputils import import_py + +import_py("CPython/linfit", "linfit") +import_py("CPython/gfitoff", "gfitoff") + +x=[0,1,2,3,4,5,6,7,8,9] +y=[1,2,3,6,9,6,3,2,1,0] +(p, x_fit, y_fit, R2) = linfit(x,y) +#print "Fit: ", (p, x_fit, y_fit, R2) +plot((y,y_fit), name=("data", "fit"),xdata=(x,x_fit)) + + +from mathutils import Gaussian +x=to_array([-200.30429237268825, -200.2650700434188, -200.22115208318002, -199.9457671375377, -199.86345548879072, -199.85213073174933, -199.35687977133284, -199.13811861090275, -197.97304970346386, -197.2952215624348, -195.09076092936948, -192.92276048970703, -191.96871876227698, -189.49577852322938, -187.9652790409825, -183.63756456925222, -180.04899765472996, -178.43839623242422, -174.07311671294445, -172.0410133577918, -165.90824309893102, -160.99771795989466, -159.30176653939253, -154.27688897558514, -152.0854103810786, -145.75652847587313, -140.80843828908465, -139.23982133191495, -134.27073891256106, -132.12649284133064, -125.95947209775511, -121.00309550337462, -119.26736932643232, -114.2706655484383, -112.07393889578914, -105.72295990367157, -100.8088439880125, -99.2034906238494, -94.30042325164636, -92.15010048151461, -85.92203653534293, -81.03913275494665, -79.27412793784428, -74.33487658582118, -72.06274362408762, -65.76562628131825, -60.91255356825276, -59.20334389560392, -54.33286972659312, -52.19387171350535, -45.94978737932291, -41.03014719193582, -39.301602568238906, -34.35572209014114, -32.04464301272608, -25.8221033382824, -20.922074315528747, -19.21590299233186, -14.31090212502093, -12.217203140101386, -5.9283722049240435, -0.9863587170369246, 0.7408048387279834, 5.71126832601389, 7.972628957879352, 14.204559894256546, 19.11839959633025, 20.8218087836657, 25.678748486941828, 27.822718344586864, 34.062659474970715, 38.9745656819391, 40.77409719734158, 45.72080631619803, 47.974156754056835, 54.23453768983539, 59.12020360609568, 60.77306570712026, 65.70734521458867, 67.8344660434617, 74.03187028154134, 78.96532114824849, 80.76070945985495, 85.74802197591286, 87.9140889204674, 94.18082276873524, 99.25790470037091, 100.68454787413205, 105.7213026221542, 107.79483801526698, 113.99555681638138, 119.0707052529143, 120.72715813056156, 125.77551384921307, 127.91257836719551, 134.2011330887875, 139.23043006997628, 140.71673537840158, 145.76288138835983, 147.80216629676042, 154.06420451405637, 159.0846626604798, 160.76183155710717, 165.73699067536242, 167.9265357747636, 173.96705069576544, 178.2522282751915, 179.9042617354548, 183.54586165856657, 185.23269803071796, 189.41678143751972, 191.87149157986588, 192.8741468985015, 195.0241934550453, 195.966634211846, 197.9821647518146, 198.99006812859284, 199.33202054855676, 199.91897441965887, 200.11536227958896, 200.22280936469997, 200.25181179127208],'d') +y=to_array([11.0, 6.0, 8.0, 5.0, 11.0, 7.0, 18.0, 11.0, 12.0, 10.0, 8.0, 6.0, 16.0, 4.0, 12.0, 9.0, 15.0, 14.0, 8.0, 20.0, 15.0, 8.0, 9.0, 11.0, 13.0, 12.0, 13.0, 15.0, 13.0, 20.0, 10.0, 7.0, 17.0, 11.0, 20.0, 13.0, 13.0, 23.0, 14.0, 10.0, 17.0, 15.0, 20.0, 16.0, 14.0, 13.0, 18.0, 22.0, 9.0, 20.0, 12.0, 14.0, 17.0, 19.0, 14.0, 14.0, 23.0, 19.0, 15.0, 20.0, 20.0, 21.0, 20.0, 23.0, 22.0, 15.0, 10.0, 17.0, 21.0, 15.0, 23.0, 23.0, 25.0, 18.0, 16.0, 21.0, 22.0, 16.0, 16.0, 14.0, 19.0, 20.0, 18.0, 20.0, 23.0, 13.0, 16.0, 20.0, 25.0, 15.0, 15.0, 17.0, 22.0, 26.0, 19.0, 30.0, 25.0, 17.0, 17.0, 23.0, 16.0, 27.0, 21.0, 21.0, 26.0, 27.0, 21.0, 17.0, 20.0, 20.0, 21.0, 19.0, 25.0, 19.0, 13.0, 23.0, 20.0, 20.0, 18.0, 20.0, 19.0, 25.0],'d') +[off, amp, com, sigma] = gfitoff(x, y, off=None, amp=None, com=None, sigma=None) +#print "Fit: ", [off, amp, com, sigma] +g = Gaussian(amp, com, sigma) +plot([y, [g.value(i)+off for i in x]], ["data", "fit"], xdata = x) + + diff --git a/script/test/TestLayout.py b/script/test/TestLayout.py index c9dec89..3228bf7 100755 --- a/script/test/TestLayout.py +++ b/script/test/TestLayout.py @@ -1,39 +1,16 @@ -tutorial_path = "src/main/assembly/help/Tutorial_py/" -run(tutorial_path+"SimulatedDevices") - import ch.psi.pshell.data.LayoutDefault -class LayoutParallelScan(ch.psi.pshell.data.LayoutDefault): +class MyLayout(ch.psi.pshell.data.LayoutDefault): def getDefaultGroup(self, scan): - return scan.readables[0].name + return str("test") +get_context().dataManager.setLayout(MyLayout()) -#get_context().pluginManager.addDynamicClass(LayoutParallel().getClass()) +tscan (sin,10,0.1) +writer = get_context().dataManager.provider.writer +o=writer.object() +o.createSoftLink("/test/sin", "/data/data1") +o.createHardLink("/test/sin", "/data/data2") - -#Does not work -#lay = LayoutParallelScan().getClass() -##print lay -#cls = Class.forName(lay.getCanonicalName(), True, lay.getClassLoader()) -#3print cls -#set_exec_pars(layout = "org.python.proxies.__main__$LayoutParallelScan$25") - - - -#Must restore the layout -#get_context().dataManager.setLayout(LayoutParallelScan()) - -set_exec_pars(layout = "Table") - - - -def scan1(): - print "scan1" - return lscan(ao1, ai1, 0, 40, 20, 0.1, title = "scan1") - -def scan2(): - print "scan2" - return lscan(ao2, ai2, 0, 40, 20, 0.1, title = "scan2") - - -parallelize(scan1, scan2) +o.createSoftLink("/test", "/link1") #Not supported +o.createHardLink("/test", "/link2") \ No newline at end of file diff --git a/script/test/TestMaster.py b/script/test/TestMaster.py new file mode 100644 index 0000000..8711801 --- /dev/null +++ b/script/test/TestMaster.py @@ -0,0 +1,7 @@ +master = MasterPositioner("master",mu, delta, gamma, eta) + +add_device(master, True) + +add_device(master.motorGroup, True) +show_panel(master) +show_panel(master.motorGroup) \ No newline at end of file diff --git a/script/test/TestMaster2.py b/script/test/TestMaster2.py new file mode 100644 index 0000000..f84ec66 --- /dev/null +++ b/script/test/TestMaster2.py @@ -0,0 +1,3 @@ +for i in frange(0.0, 1.0, 0.1): + master.move(i) + print mu.take(), delta.take(), gamma.take(), eta.take() diff --git a/script/test/TestMatrixPlotRenderer.py b/script/test/TestMatrixPlotRenderer.py new file mode 100644 index 0000000..29ab89e --- /dev/null +++ b/script/test/TestMatrixPlotRenderer.py @@ -0,0 +1,4 @@ + +def before_read(): + time.sleep(1.0) +tscan((sin,scienta.dataMatrix, det.dataMatrix), 5, 0.1, before_read=before_read, save=False, plot_types={scienta.dataMatrix:"ch.psi.pshell.plot.MatrixPlotRenderer"}) \ No newline at end of file diff --git a/script/test/TestMonit.py b/script/test/TestMonit.py new file mode 100644 index 0000000..e6dcadf --- /dev/null +++ b/script/test/TestMonit.py @@ -0,0 +1,23 @@ +def after_read(rec, scan): + if rec[sin] < 19.0: + rec.invalidate() + time.sleep(0.05) + print "Refused " + str(rec["sin"]) + " at " + str (time.time()- start) + else: + print "Acccepted " + str(rec["sin"]) + " at " + str (time.time()- start) + + +start= time.time() +r1 = mscan(sin, [sin, out],-1, 3, async=False, after_read=after_read) +print r1.getSize() +r2 = mscan(sin, [sin, out],-1, 3, async=True, after_read=after_read) +print r2.getSize() +r3 = mscan(sin, [sin, out],10, 4, async=False, after_read=after_read) +print r3.getSize() +r4 = mscan(sin, [sin, out],10, 4, async=True, after_read=after_read) +print r4.getSize() + +#r1 = lscan(energy, [sin],0, 1, 10, 0.1, after_read=after_read) + + +#r1 = tscan(sin, 50, 0.1, fixed_rate = True, domain_axis="Time", after_read=after_read) \ No newline at end of file diff --git a/script/test/TestMonit.txt b/script/test/TestMonit.txt new file mode 100644 index 0000000..a4d69ee --- /dev/null +++ b/script/test/TestMonit.txt @@ -0,0 +1,9 @@ +def after_read(rec, scan): + if rec["sin"] < 15.0: + rec.invalidate() + time.sleep(0.1) + + + + +r1 = mscan(sin, [sin], 25, after_read=after_read) \ No newline at end of file diff --git a/script/test/TestMonitor.py b/script/test/TestMonitor.py new file mode 100644 index 0000000..6cd67c6 --- /dev/null +++ b/script/test/TestMonitor.py @@ -0,0 +1,125 @@ +################################################################################################### +# Example of saving diagostics and snapshots during a scan +################################################################################################### + +DIAGS = [ai2] +SNAPS = [ai3, wf1] + +ret = lscan(m1, ai1, 0.0, 1.0, 4, diags=DIAGS, snaps=SNAPS) + +plot(ret.getSnap(wf1)) +plot(ret.getDiag(ai2)) + +#All devices can be directly indexd +for dev in [m1, ai1, ai2, wf1, ai3]: + print dev.name, " -> ", ret[dev] + + + +#Changing default folders +LayoutBase.PATH_SNAPS = "initial/" +LayoutBase.PATH_DIAGS = "status/" +LayoutBase.PATH_MONITORS = "events/" +LayoutBase.PATH_LOGS = "logbook/" + +ret = lscan(m1, ai1, 0.0, 1.0, 4, diags=DIAGS, snaps=SNAPS) + + + +ret = tscan(out, 10, 0.2, diags=[inp, arr], monitors=[inp, sin], snapshots=[inp, motor]) +#set_exec_pars(flush=True) +#print ret[out] +print ret[sin] +print ret["arr"] +print ret[motor] + + +#print ret.getDiag(sin) +#print ret.getDiag(arr) +#ret = tscan(out, 10, 0.2, monitors=[sin, arr]) +#plot(ret[sin][1], xdata=ret[sin][0]) +#plot(ret[out], xdata=ret.timestamps) + + + + +""" +class OtfValue(ReadonlyAsyncRegisterBase): + def __init__(self, name): + ReadonlyAsyncRegisterBase.__init__(self, name) + + def setValue(self, value,timestamp): + self.setCache(value,timestamp) + +class OTF(Otf): + def __init__(self, name): + Otf.__init__(self, name) + self.addComponent(OtfValue("Channel1")) + self.addComponent(OtfValue("Channel2")) + self.components[0].setValue(float("NaN"), long(time.time()*10e6)) + self.components[1].setValue(-1, long(time.time()*10e6)) + self.initialize() + self.interrupted = False + + def task(self): + start = time.time() + finished=False + while not self.interrupted and not finished: + time.sleep(0.1) + self.components[0].setValue(time.time(), long(time.time()*10e6)) + finished = (time.time()-start)> 5.0 + if not self.interrupted: + for i in range(20): + self.components[1].setValue(i, long(time.time()*10e6)) + self.getLogger().info("Finished OTF") + self.state=State.Ready + + def start(self): + self.state=State.Busy + self.interrupted = False + self.thread = fork(self.task) + + def abort(self): + self.interrupted = True + self.getLogger().info("Interrupting OTF thread") + join(self.thread) + +add_device(OTF("otf"), True) + +ret = tscan(out, 10, 0.2, monitors=[otf]) +""" +""" +class OTF(Otf): + def __init__(self, name): + Otf.__init__(self, name) + self.setCache(float("NaN"), long(time.time()*10e6)) + self.initialize() + self.interrupted = False + + def task(self): + start = time.time() + finished=False + while not self.interrupted and not finished: + time.sleep(0.1) + self.setCache(time.time(), long(time.time()*10e6)) + finished = (time.time()-start)> 5.0 + self.getLogger().info("Finished OTF") + self.state=State.Ready + + def start(self): + self.state=State.Busy + self.interrupted = False + self.thread = fork(self.task) + + def abort(self): + self.interrupted = True + self.getLogger().info("Interrupting OTF thread") + join(self.thread) + +add_device(OTF("otf"), True) + +ret = tscan(out, 10, 0.2, monitors=[otf]) +plot(ret[otf][1], xdata=ret[otf][0]) +""" + +set_return(None) \ No newline at end of file diff --git a/script/test/TestMultiDimens.py b/script/test/TestMultiDimens.py new file mode 100644 index 0000000..13bf768 --- /dev/null +++ b/script/test/TestMultiDimens.py @@ -0,0 +1,44 @@ +def append_dataset(path, data, index=None, type='d', shape=None): + """Append data to dataset. + + Args: + path(str): Path to dataset relative to the current persistence context root. + data(number or array or list): name of each column. + index(int or list, optional): if set then add the data in a specific position in the dataset. + If integer is the index in an array (data must be 1 order lower than dataset) + If a list, specifies the full coordinate for multidimensional datasets. + type(str, optional): array type 'b' = byte, 'h' = short, 'i' = int, 'l' = long, 'f' = float, + 'd' = double, 'c' = char, 's' = String, 'o' = Object + default: 'd' (convert data to array of doubles) + shape(list, optional): only valid if index is a list, provides the shape of the data array. + In this case data must be a flattened one-dimensional array. + Returns: + None + """ + data = to_array(data, type) + + if index is None: + get_context().dataManager.appendItem(path, data) + else: + if is_list(index): + if shape is None: + shape = [len(index)] + get_context().dataManager.setItem(path, data, index, shape) + else: + get_context().dataManager.setItem(path, data, index) + + +path = "data/data4d" +data3d = [ [ [1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7], [4,5,6,7,8]], + [ [2,2,3,4,5], [3,3,4,5,6], [5,4,5,6,7], [7,5,6,7,8]], + [ [3,2,3,4,5], [4,3,4,5,6], [6,4,5,6,7], [8,5,6,7,8]] ] + +plot(data3d) + +data = flatten(to_array(data3d,'i)) + + + +#save_dataset(path, data4d) +create_dataset(path, 'i', dimensions = [2, 3, 4, 5]) +append_dataset(path, data, index = [0,0,0,0], type = 'i', shape=[1, 3, 4, 5]) \ No newline at end of file diff --git a/script/test/TestParallelJEP.py b/script/test/TestParallelJEP.py new file mode 100644 index 0000000..bf577c7 --- /dev/null +++ b/script/test/TestParallelJEP.py @@ -0,0 +1,30 @@ +from jeputils import import_py +from mathutils import Gaussian +import traceback + +import_py("CPython/linfit", "linfit") +import_py("CPython/gfitoff", "gfitoff") + + +def task(index): + try: + print index + x=[0,1,2,3,4,5,6,7,8,9] + y=[1,2,3,6,9,6,3,2,1,0] + (p, x_fit, y_fit, R2) = linfit(x,y) + #print "Fit: ", (p, x_fit, y_fit, R2) + plot((y,y_fit), name=("data", "fit"),xdata=(x,x_fit), title=str(index)) + + + + x=to_array([-200.30429237268825, -200.2650700434188, -200.22115208318002, -199.9457671375377, -199.86345548879072, -199.85213073174933, -199.35687977133284, -199.13811861090275, -197.97304970346386, -197.2952215624348, -195.09076092936948, -192.92276048970703, -191.96871876227698, -189.49577852322938, -187.9652790409825, -183.63756456925222, -180.04899765472996, -178.43839623242422, -174.07311671294445, -172.0410133577918, -165.90824309893102, -160.99771795989466, -159.30176653939253, -154.27688897558514, -152.0854103810786, -145.75652847587313, -140.80843828908465, -139.23982133191495, -134.27073891256106, -132.12649284133064, -125.95947209775511, -121.00309550337462, -119.26736932643232, -114.2706655484383, -112.07393889578914, -105.72295990367157, -100.8088439880125, -99.2034906238494, -94.30042325164636, -92.15010048151461, -85.92203653534293, -81.03913275494665, -79.27412793784428, -74.33487658582118, -72.06274362408762, -65.76562628131825, -60.91255356825276, -59.20334389560392, -54.33286972659312, -52.19387171350535, -45.94978737932291, -41.03014719193582, -39.301602568238906, -34.35572209014114, -32.04464301272608, -25.8221033382824, -20.922074315528747, -19.21590299233186, -14.31090212502093, -12.217203140101386, -5.9283722049240435, -0.9863587170369246, 0.7408048387279834, 5.71126832601389, 7.972628957879352, 14.204559894256546, 19.11839959633025, 20.8218087836657, 25.678748486941828, 27.822718344586864, 34.062659474970715, 38.9745656819391, 40.77409719734158, 45.72080631619803, 47.974156754056835, 54.23453768983539, 59.12020360609568, 60.77306570712026, 65.70734521458867, 67.8344660434617, 74.03187028154134, 78.96532114824849, 80.76070945985495, 85.74802197591286, 87.9140889204674, 94.18082276873524, 99.25790470037091, 100.68454787413205, 105.7213026221542, 107.79483801526698, 113.99555681638138, 119.0707052529143, 120.72715813056156, 125.77551384921307, 127.91257836719551, 134.2011330887875, 139.23043006997628, 140.71673537840158, 145.76288138835983, 147.80216629676042, 154.06420451405637, 159.0846626604798, 160.76183155710717, 165.73699067536242, 167.9265357747636, 173.96705069576544, 178.2522282751915, 179.9042617354548, 183.54586165856657, 185.23269803071796, 189.41678143751972, 191.87149157986588, 192.8741468985015, 195.0241934550453, 195.966634211846, 197.9821647518146, 198.99006812859284, 199.33202054855676, 199.91897441965887, 200.11536227958896, 200.22280936469997, 200.25181179127208],'d') + y=to_array([11.0, 6.0, 8.0, 5.0, 11.0, 7.0, 18.0, 11.0, 12.0, 10.0, 8.0, 6.0, 16.0, 4.0, 12.0, 9.0, 15.0, 14.0, 8.0, 20.0, 15.0, 8.0, 9.0, 11.0, 13.0, 12.0, 13.0, 15.0, 13.0, 20.0, 10.0, 7.0, 17.0, 11.0, 20.0, 13.0, 13.0, 23.0, 14.0, 10.0, 17.0, 15.0, 20.0, 16.0, 14.0, 13.0, 18.0, 22.0, 9.0, 20.0, 12.0, 14.0, 17.0, 19.0, 14.0, 14.0, 23.0, 19.0, 15.0, 20.0, 20.0, 21.0, 20.0, 23.0, 22.0, 15.0, 10.0, 17.0, 21.0, 15.0, 23.0, 23.0, 25.0, 18.0, 16.0, 21.0, 22.0, 16.0, 16.0, 14.0, 19.0, 20.0, 18.0, 20.0, 23.0, 13.0, 16.0, 20.0, 25.0, 15.0, 15.0, 17.0, 22.0, 26.0, 19.0, 30.0, 25.0, 17.0, 17.0, 23.0, 16.0, 27.0, 21.0, 21.0, 26.0, 27.0, 21.0, 17.0, 20.0, 20.0, 21.0, 19.0, 25.0, 19.0, 13.0, 23.0, 20.0, 20.0, 18.0, 20.0, 19.0, 25.0],'d') + [off, amp, com, sigma] = gfitoff(x, y, off=None, amp=None, com=None, sigma=None) + #print "Fit: ", [off, amp, com, sigma] + g = Gaussian(amp, com, sigma) + plot([y, [g.value(i)+off for i in x]], ["data", "fit"], xdata = x, title=str(index)) + except: + traceback.print_exc() +task(0) +for i in range(3): + fork((task,(i+1,))) \ No newline at end of file diff --git a/script/test/TestPipelineStream.py b/script/test/TestPipelineStream.py new file mode 100644 index 0000000..8004ee3 --- /dev/null +++ b/script/test/TestPipelineStream.py @@ -0,0 +1,32 @@ +add_device(PipelineStream("p","localhost:8889", "simulation_sp"), True) +set_exec_pars(save=False) +#tscan(p.channels,10,0.1) + + +#Sync with stopped stream +p.update() #First update to create children devices +x_profile= p.getChannel("x_profile") +tscan((p,x_profile),3,0.1) + + + +#Async on running stream +p.monitored=True +p.stream.waitValueChange(-1) + + +class StreamImage(ReadableMatrix): + def read(self): + return Convert.reshape(p.getValue("image") , (self.getHeight(), self.getWidth())) + + def getWidth(self): + return p.getValue("width") + + def getHeight(self): + return p.getValue("height") + +mscan(p, StreamImage(), 5) + + +#Sync on running stream +tscan(p.channels,5,0.5) \ No newline at end of file diff --git a/script/test/TestSnapArray.py b/script/test/TestSnapArray.py new file mode 100644 index 0000000..3602282 --- /dev/null +++ b/script/test/TestSnapArray.py @@ -0,0 +1,8 @@ + +DIAGS = [wf1,im1] +SNAPS = [wf1,im1] + +ret = lscan(m1, ai1, 0.0, 1.0, 4, diags=DIAGS, snaps=SNAPS) + +plot(ret.getSnap(wf1)) +plot(ret.getDiag(im1)) diff --git a/script/test/TestSpectrum.py b/script/test/TestSpectrum.py new file mode 100644 index 0000000..229e20f --- /dev/null +++ b/script/test/TestSpectrum.py @@ -0,0 +1,149 @@ +#If running from editor +if (get_exec_pars().source == CommandSource.ui): + ROI = {"Region1": [10,5,20, 10], "Region2": [60,60,40, 40]} + SAVE_SPECTRUM = True + SAVE_IMAGES = True + WITH_I0 = False + SWITCH_POL = False + EXPOSURE = 1.0 + AVERAGE = 2 + NUMBER_SCANS =1 + RANGES = [[500.0, 1000.0, 100.0]] + +print "Starting AbsSpec: ",SAVE_SPECTRUM, SAVE_IMAGES, WITH_I0, SWITCH_POL, EXPOSURE, AVERAGE, NUMBER_SCANS, RANGES + +run("eiger") +machine_cur=sin +Keithley_1_raw = cv +def get_dry_run(): + return True +def set_outliers_threshold(value): + set_setting("OUTLIERS_THRESHOLD", int(value)) +def get_outliers_threshold(): + try: + return int(get_setting("OUTLIERS_THRESHOLD")) + except: + return 0 +def get_outliers_mask_file(): + return get_setting("OUTLIERS_MASK_FILE") + +if SWITCH_POL: + init_pol_switch("Normal") + + +log("ROIs: " + str(ROI)) + +if len(RANGES) == 0: + raise Exception("No scan range defined") + +start = time.time() + +init_eiger(exposure=EXPOSURE) + +set_exec_pars(name="AbsortionSpectrum", format="csv", layout="table") +tag= "AbsortionSpectrum_{seq}%03d_{count}%02d" + +rois = create_roi_devices(ROI) + +if AVERAGE>1: + for i in range(len(rois)): + rois[i].monitored = True + rois[i] = create_averager(rois[i], AVERAGE, -1) + rois[i].monitored = True + + +frames=[] + + +class SyncEnergy(Writable): + def write(self,pos): + if not get_dry_run(): + put_energy(pos) + else: + print "Energy=" + str(pos) +sync_energy=SyncEnergy() +set_device_alias(sync_energy, "Energy") #Set display name + +sensors = rois + [machine_cur] +if WITH_I0: + sensors = sensors + [Keithley_1_raw] + + +#### +def __save_as_tiff(index, data, filename,metadata={}): + if type(data) == Data: + ip = load_array(data.matrix) + else: + ip = data + + metadata["Timestamp"] = time.strftime("%y/%m/%d %H:%M:%S",time.localtime()) + if not os.path.exists(os.path.dirname(filename)): + os.makedirs(os.path.dirname(filename)) + save_image(ip, filename,"tiff", metadata) + + d = get_ip_array(ip) + import java.util.Arrays as Arrays + ip=open_image(filename) + read = get_ip_array(ip) + if not Arrays.deepEquals(read, d): + print "Error reading array" + print index, filename + index=0 + for name,r in ROI.items(): + s=0.0 + for i in range(r[2]): + for j in range(r[3]): + #s = s + d[r[0]+i][r[1]+j] + el=data.getElement(r[0]+i, r[1]+j, False) + s = s + (0 if (math.isnan(el)) else el) + roi = data.getRoi(Rectangle(r[0],r[1], r[2], r[3])) + + print name, s, rois[index].take(), roi.integrate(False) + index=index+1 + + +#### + + +av=None +def grab_image(position, scan): + global av + av = average_eiger_frames(AVERAGE, roi=None, wait_next=True) + + if SAVE_IMAGES: + filename = get_exec_pars().path + "/" + str(scan.currentPass) + "/s" + "{seq}%03d" + "_" + ("%03d.tif" % scan.recordIndex) + filename = get_context().setup.expandPath(filename) + #print filename + #save_as_tiff(av, filename, metadata={}) + #fork((__save_as_tiff,(scan.recordIndex, av, filename)),) + __save_as_tiff(scan.recordIndex, av, filename) +class Average(ReadableMatrix): + def read(self): + return av.matrix + def getWidth(self): + return image.getData().getWidth() + def getHeight(self): + return image.getData().getHeight() +averager=Average() +set_device_alias(averager, "Image") #Set display name +sensors.append(averager) + +#Initialize vartiables +if not get_dry_run() and str(get_setting("AUTO_SWITCH_VALVE")).lower() == "true": + open_vg10() + + +def after_pass(pass_number, scan): + if SWITCH_POL: + if pass_number1: + for i in range(len(rois)): + rois[i].parent.monitored = False # Remove listeners on the image + if not get_dry_run() and str(get_setting("AUTO_SWITCH_VALVE")).lower() == "true": + close_vg10() + restore_eiger() + print "Running time: " + str(time.time() - start) \ No newline at end of file diff --git a/script/test/TestStreamDemo.py b/script/test/TestStreamDemo.py new file mode 100644 index 0000000..542531a --- /dev/null +++ b/script/test/TestStreamDemo.py @@ -0,0 +1,15 @@ +STREAM_URL="tcp://localhost:5552" + + + +st1=Stream("st1", STREAM_URL, SocketType.SUB) +st1.createMatrix = True +st1.initialize() +st1.start() +st1.waitCacheChange(2000) + + +show_panel(st1) + + +#bscan(st1, 10, -1) \ No newline at end of file diff --git a/script/test/TestStreamNotFixed.py b/script/test/TestStreamNotFixed.py index 47d8e76..392454c 100644 --- a/script/test/TestStreamNotFixed.py +++ b/script/test/TestStreamNotFixed.py @@ -2,22 +2,33 @@ import ch.psi.pshell.bs.Provider as Provider url="tcp://localhost:9999" url="tcp://SFTEST-CVME-DBPM1:9001" #url= "tcp://SIN-CVME-DBPM0421:9000" -p=Provider("provider", url, True) -p.config.keepListeningOnStop = True -p.config.parallelHandlerProcessing = False -p.config.byteBufferAllocator = True -st1 = Stream("st1", p) +url="tcp://localhost:5553" +#url="tcp://localhost:10101" +#p=Provider("provider", url, False) +#p.config.keepListeningOnStop = True +#p.config.parallelHandlerProcessing = False +#p.config.byteBufferAllocator = True +#st1 = + +st1=Stream("st1", url, SocketType.SUB) +#st1.addScalar("scalar") +#st1.addMatrix("img") +#st1.addScalar("str") +#st1.addWaveform("waveform") + st1.initialize() st1.start() -st1.waitCacheChange(20000) +st1.waitCacheChange(2000) - -#try: -# bscan (st1, 5, 5, save=False) -#finally: -# st1.close() +""" +try: + bscan (st1, 5, 5, save=False) +finally: + st1.close() try: print st1.getValues() finally: st1.close() + +""" diff --git a/script/test/TestStrip.py b/script/test/TestStrip.py new file mode 100644 index 0000000..4956aab --- /dev/null +++ b/script/test/TestStrip.py @@ -0,0 +1,21 @@ +import random + +#################################################################################################### +# Simulated Devices +#################################################################################################### + +class AnalogInput(ReadonlyRegisterBase): + def doRead(self): + time.sleep(0.001) + self.val = to_array(self.calc(), 'd') + return self.val + +class Random(AnalogInput): + def calc(self): + return random.random() + + +for i in range(20): + r=Random("r"+str(i)) + add_device(r, True) + r.polling=5 diff --git a/script/test/TestTablePlot.py b/script/test/TestTablePlot.py new file mode 100644 index 0000000..7fb2d3d --- /dev/null +++ b/script/test/TestTablePlot.py @@ -0,0 +1,2 @@ +CUSTOM_PLOT_TYPES = {scienta.dataMatrix:"ch.psi.pshell.plot.TablePlot"} +tscan(scienta.dataMatrix, 5, 0.1, save=False, plot_types=CUSTOM_PLOT_TYPES) \ No newline at end of file diff --git a/script/test/TestTerminal.py b/script/test/TestTerminal.py new file mode 100644 index 0000000..7a07fb0 --- /dev/null +++ b/script/test/TestTerminal.py @@ -0,0 +1,24 @@ +import ch.psi.utils.swing.Terminal as Terminal +import ch.psi.utils.swing.SwingUtils as SwingUtils +terminal=None +view=App.getInstance().getMainFrame() +tabStatus=view.getStatusTab() + +def showTerminal(): + global terminal + terminal = Terminal(".", 13) + tabStatus.addTab("T", terminal) + index = tabStatus.getTabCount() - 1 + SwingUtils.setTabClosable(tabStatus, index) + tabStatus.setSelectedComponent(terminal) + +def hideTerminal(): + global terminal + if terminal is not None: + tabStatus.remove(terminal) + terminal = None + +for i in range (100): + showTerminal() + hideTerminal() + \ No newline at end of file diff --git a/script/test/TestVscan.py b/script/test/TestVscan.py new file mode 100644 index 0000000..268e80b --- /dev/null +++ b/script/test/TestVscan.py @@ -0,0 +1,2 @@ +vector = [ 1, 3, 5, 10, 25, 40, 45, 47, 49] +r1 = vscan(motor,(sin),vector,False, 0.5, relative=True,title = "1D Vector", before_read=None, after_read=None) \ No newline at end of file diff --git a/script/test/TstImgSim.py b/script/test/TstImgSim.py new file mode 100644 index 0000000..afbd596 --- /dev/null +++ b/script/test/TstImgSim.py @@ -0,0 +1,43 @@ +run ("imaging/sim") + +stack = load_test_stack(show=True) +ipr, ipi = complex_edge_filtering(stack, complex=True, g_sigma = 3.0, show=False) + + +#complex_edge_filter = get_context().getClassByName("Align_ComplexEdgeFiltering").newInstance() +#translation_filter = get_context().getClassByName("Align_TranslationFilter2").newInstance() +#compute_shifts_filter = get_context().getClassByName("Align_ComputeShifts2").newInstance() + +""" +ip_list = [] +for index in range(40,49): + ip_list.append(open_image(expand_path("{images}/TestObjAligner/i210517_0" + str(index) + "#001.tif"))) +stack = create_stack(ip_list, title = "Test") +stack.show() + +complex_edge_filter.setup("2,True,False", stack) #Gaussian blur radius, Complex (True) or Real (False), show dialog = False +complex_edge_filter.r"un(stack.getProcessor()) +imp_r, imp_i = complex_edge_filter.output + +#imp_r.show() +#imp_i.show() +roi=Roi(258,0,256,256) +compute_shifts_filter.setup(10, False, ipr, ipi, 1, roi) +compute_shifts_filter.run(None) +shifts = compute_shifts_filter.shifts + +translation_filter.shifts = shifts +translation_filter.setup("",stack) +translation_filter.run(stack.getProcessor()) + +translation_filter.registred.show(); +translation_filter.registred.updateAndDraw(); + +""" + +roi=Roi(258,0,256,256) +shifts = calculate_shifts(ipr, ipi, roi, 2) +r=translate(stack, shifts, True) + + + diff --git a/script/test/TstImgSim2.py b/script/test/TstImgSim2.py new file mode 100644 index 0000000..92676d8 --- /dev/null +++ b/script/test/TstImgSim2.py @@ -0,0 +1,44 @@ +from ijutils import Roi +#from sim import * +import traceback +run ("imaging/sim") + +roi=Roi(0,0,128,128) + +""" +stack = load_test_stack(show=True, size=2) +ipr, ipi = complex_edge_filtering(stack, show=False) +shifts = calculate_shifts(ipr, ipi, roi, java_code=True) +#shifts= load_shifts("{images}/TestObjAligner/shifts.mat") +#stack = load_test_stack(show=True) +r=translate(stack, shifts, show=True) +""" + + + + +ref = "{images}/TestObjAligner/i210517_040#001.tif" +img = "{images}/TestObjAligner/i210517_041#001.tif" + +ref = open_image(ref) +img = open_image(img) +#ref=ref.getBufferedImage() +#img=img.getBufferedImage() +#ref=ca.data +img=grayscale(to_ip(ca.data)) +ref = grayscale(ref.crop([Roi(0,0,452,452)])[0]) + +def calculate_shift(ref,img, roi, upscale_factor=100, reference_slide=1): + ref = to_ip(ref) + img = to_ip(img) + stack = create_stack([ref,img]) + stack.show() + ipr, ipi = complex_edge_filtering(stack, show=False) + shifts = calculate_shifts(ipr, ipi, roi, java_code=True) + xoff, yoff = shifts[1][3], shifts[1][2] + error, diffphase = shifts[1][4], shifts[1][5] + r=translate(stack, shifts, show=True) + return xoff, yoff,error, diffphase + + +print calculate_shift(ref,img, roi) diff --git a/script/test/VERSI_BEAMSTOP_SCAN.xml b/script/test/VERSI_BEAMSTOP_SCAN.xml new file mode 100644 index 0000000..5e483e7 --- /dev/null +++ b/script/test/VERSI_BEAMSTOP_SCAN.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + -2.0 + 2.0 + 0.1 + 0.2 + 0.25 + + + + + + + + + + + 0.0 + 2.0 + 0.1 + X_INIT + X_FINAL + + + + + + + + + + + + + + diff --git a/script/test/calc.py b/script/test/calc.py index 7d85119..988c123 100755 --- a/script/test/calc.py +++ b/script/test/calc.py @@ -1,3 +1,4 @@ def calc(a): return a*4 +print calc(10) \ No newline at end of file diff --git a/script/test/inspect.py b/script/test/inspect.py new file mode 100644 index 0000000..adf0653 --- /dev/null +++ b/script/test/inspect.py @@ -0,0 +1,3128 @@ +"""Get useful information from live Python objects. + +This module encapsulates the interface provided by the internal special +attributes (co_*, im_*, tb_*, etc.) in a friendlier fashion. +It also provides some help for examining source code and class layout. + +Here are some of the useful functions provided by this module: + + ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(), + isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(), + isroutine() - check object types + getmembers() - get members of an object that satisfy a given condition + + getfile(), getsourcefile(), getsource() - find an object's source code + getdoc(), getcomments() - get documentation on an object + getmodule() - determine the module that an object came from + getclasstree() - arrange classes so as to represent their hierarchy + + getargvalues(), getcallargs() - get info about function arguments + getfullargspec() - same, with support for Python 3 features + formatargspec(), formatargvalues() - format an argument spec + getouterframes(), getinnerframes() - get info about frames + currentframe() - get the current stack frame + stack(), trace() - get info about frames on the stack or in a traceback + + signature() - get a Signature object for the callable +""" + +# This module is in the public domain. No warranties. + +__author__ = ('Ka-Ping Yee ', + 'Yury Selivanov ') + +import abc +import ast +import dis +import collections.abc +import enum +import importlib.machinery +import itertools +import linecache +import os +import re +import sys +import tokenize +import token +import types +import warnings +import functools +import builtins +from operator import attrgetter +from collections import namedtuple, OrderedDict + +# Create constants for the compiler flags in Include/code.h +# We try to get them from dis to avoid duplication +mod_dict = globals() +for k, v in dis.COMPILER_FLAG_NAMES.items(): + mod_dict["CO_" + v] = k + +# See Include/object.h +TPFLAGS_IS_ABSTRACT = 1 << 20 + +# ----------------------------------------------------------- type-checking +def ismodule(object): + """Return true if the object is a module. + + Module objects provide these attributes: + __cached__ pathname to byte compiled file + __doc__ documentation string + __file__ filename (missing for built-in modules)""" + return isinstance(object, types.ModuleType) + +def isclass(object): + """Return true if the object is a class. + + Class objects provide these attributes: + __doc__ documentation string + __module__ name of module in which this class was defined""" + return isinstance(object, type) + +def ismethod(object): + """Return true if the object is an instance method. + + Instance method objects provide these attributes: + __doc__ documentation string + __name__ name with which this method was defined + __func__ function object containing implementation of method + __self__ instance to which this method is bound""" + return isinstance(object, types.MethodType) + +def ismethoddescriptor(object): + """Return true if the object is a method descriptor. + + But not if ismethod() or isclass() or isfunction() are true. + + This is new in Python 2.2, and, for example, is true of int.__add__. + An object passing this test has a __get__ attribute but not a __set__ + attribute, but beyond that the set of attributes varies. __name__ is + usually sensible, and __doc__ often is. + + Methods implemented via descriptors that also pass one of the other + tests return false from the ismethoddescriptor() test, simply because + the other tests promise more -- you can, e.g., count on having the + __func__ attribute (etc) when an object passes ismethod().""" + if isclass(object) or ismethod(object) or isfunction(object): + # mutual exclusion + return False + tp = type(object) + return hasattr(tp, "__get__") and not hasattr(tp, "__set__") + +def isdatadescriptor(object): + """Return true if the object is a data descriptor. + + Data descriptors have both a __get__ and a __set__ attribute. Examples are + properties (defined in Python) and getsets and members (defined in C). + Typically, data descriptors will also have __name__ and __doc__ attributes + (properties, getsets, and members have both of these attributes), but this + is not guaranteed.""" + if isclass(object) or ismethod(object) or isfunction(object): + # mutual exclusion + return False + tp = type(object) + return hasattr(tp, "__set__") and hasattr(tp, "__get__") + +if hasattr(types, 'MemberDescriptorType'): + # CPython and equivalent + def ismemberdescriptor(object): + """Return true if the object is a member descriptor. + + Member descriptors are specialized descriptors defined in extension + modules.""" + return isinstance(object, types.MemberDescriptorType) +else: + # Other implementations + def ismemberdescriptor(object): + """Return true if the object is a member descriptor. + + Member descriptors are specialized descriptors defined in extension + modules.""" + return False + +if hasattr(types, 'GetSetDescriptorType'): + # CPython and equivalent + def isgetsetdescriptor(object): + """Return true if the object is a getset descriptor. + + getset descriptors are specialized descriptors defined in extension + modules.""" + return isinstance(object, types.GetSetDescriptorType) +else: + # Other implementations + def isgetsetdescriptor(object): + """Return true if the object is a getset descriptor. + + getset descriptors are specialized descriptors defined in extension + modules.""" + return False + +def isfunction(object): + """Return true if the object is a user-defined function. + + Function objects provide these attributes: + __doc__ documentation string + __name__ name with which this function was defined + __code__ code object containing compiled function bytecode + __defaults__ tuple of any default values for arguments + __globals__ global namespace in which this function was defined + __annotations__ dict of parameter annotations + __kwdefaults__ dict of keyword only parameters with defaults""" + return isinstance(object, types.FunctionType) + +def isgeneratorfunction(object): + """Return true if the object is a user-defined generator function. + + Generator function objects provide the same attributes as functions. + See help(isfunction) for a list of attributes.""" + return bool((isfunction(object) or ismethod(object)) and + object.__code__.co_flags & CO_GENERATOR) + +def iscoroutinefunction(object): + """Return true if the object is a coroutine function. + + Coroutine functions are defined with "async def" syntax. + """ + return bool((isfunction(object) or ismethod(object)) and + object.__code__.co_flags & CO_COROUTINE) + +def isasyncgenfunction(object): + """Return true if the object is an asynchronous generator function. + + Asynchronous generator functions are defined with "async def" + syntax and have "yield" expressions in their body. + """ + return bool((isfunction(object) or ismethod(object)) and + object.__code__.co_flags & CO_ASYNC_GENERATOR) + +def isasyncgen(object): + """Return true if the object is an asynchronous generator.""" + return isinstance(object, types.AsyncGeneratorType) + +def isgenerator(object): + """Return true if the object is a generator. + + Generator objects provide these attributes: + __iter__ defined to support iteration over container + close raises a new GeneratorExit exception inside the + generator to terminate the iteration + gi_code code object + gi_frame frame object or possibly None once the generator has + been exhausted + gi_running set to 1 when generator is executing, 0 otherwise + next return the next item from the container + send resumes the generator and "sends" a value that becomes + the result of the current yield-expression + throw used to raise an exception inside the generator""" + return isinstance(object, types.GeneratorType) + +def iscoroutine(object): + """Return true if the object is a coroutine.""" + return isinstance(object, types.CoroutineType) + +def isawaitable(object): + """Return true if object can be passed to an ``await`` expression.""" + return (isinstance(object, types.CoroutineType) or + isinstance(object, types.GeneratorType) and + bool(object.gi_code.co_flags & CO_ITERABLE_COROUTINE) or + isinstance(object, collections.abc.Awaitable)) + +def istraceback(object): + """Return true if the object is a traceback. + + Traceback objects provide these attributes: + tb_frame frame object at this level + tb_lasti index of last attempted instruction in bytecode + tb_lineno current line number in Python source code + tb_next next inner traceback object (called by this level)""" + return isinstance(object, types.TracebackType) + +def isframe(object): + """Return true if the object is a frame object. + + Frame objects provide these attributes: + f_back next outer frame object (this frame's caller) + f_builtins built-in namespace seen by this frame + f_code code object being executed in this frame + f_globals global namespace seen by this frame + f_lasti index of last attempted instruction in bytecode + f_lineno current line number in Python source code + f_locals local namespace seen by this frame + f_trace tracing function for this frame, or None""" + return isinstance(object, types.FrameType) + +def iscode(object): + """Return true if the object is a code object. + + Code objects provide these attributes: + co_argcount number of arguments (not including *, ** args + or keyword only arguments) + co_code string of raw compiled bytecode + co_cellvars tuple of names of cell variables + co_consts tuple of constants used in the bytecode + co_filename name of file in which this code object was created + co_firstlineno number of first line in Python source code + co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg + | 16=nested | 32=generator | 64=nofree | 128=coroutine + | 256=iterable_coroutine | 512=async_generator + co_freevars tuple of names of free variables + co_kwonlyargcount number of keyword only arguments (not including ** arg) + co_lnotab encoded mapping of line numbers to bytecode indices + co_name name with which this code object was defined + co_names tuple of names of local variables + co_nlocals number of local variables + co_stacksize virtual machine stack space required + co_varnames tuple of names of arguments and local variables""" + return isinstance(object, types.CodeType) + +def isbuiltin(object): + """Return true if the object is a built-in function or method. + + Built-in functions and methods provide these attributes: + __doc__ documentation string + __name__ original name of this function or method + __self__ instance to which a method is bound, or None""" + return isinstance(object, types.BuiltinFunctionType) + +def isroutine(object): + """Return true if the object is any kind of function or method.""" + return (isbuiltin(object) + or isfunction(object) + or ismethod(object) + or ismethoddescriptor(object)) + +def isabstract(object): + """Return true if the object is an abstract base class (ABC).""" + if not isinstance(object, type): + return False + if object.__flags__ & TPFLAGS_IS_ABSTRACT: + return True + if not issubclass(type(object), abc.ABCMeta): + return False + if hasattr(object, '__abstractmethods__'): + # It looks like ABCMeta.__new__ has finished running; + # TPFLAGS_IS_ABSTRACT should have been accurate. + return False + # It looks like ABCMeta.__new__ has not finished running yet; we're + # probably in __init_subclass__. We'll look for abstractmethods manually. + for name, value in object.__dict__.items(): + if getattr(value, "__isabstractmethod__", False): + return True + for base in object.__bases__: + for name in getattr(base, "__abstractmethods__", ()): + value = getattr(object, name, None) + if getattr(value, "__isabstractmethod__", False): + return True + return False + +def getmembers(object, predicate=None): + """Return all members of an object as (name, value) pairs sorted by name. + Optionally, only return members that satisfy a given predicate.""" + if isclass(object): + mro = (object,) + getmro(object) + else: + mro = () + results = [] + processed = set() + names = dir(object) + # :dd any DynamicClassAttributes to the list of names if object is a class; + # this may result in duplicate entries if, for example, a virtual + # attribute with the same name as a DynamicClassAttribute exists + try: + for base in object.__bases__: + for k, v in base.__dict__.items(): + if isinstance(v, types.DynamicClassAttribute): + names.append(k) + except AttributeError: + pass + for key in names: + # First try to get the value via getattr. Some descriptors don't + # like calling their __get__ (see bug #1785), so fall back to + # looking in the __dict__. + try: + value = getattr(object, key) + # handle the duplicate key + if key in processed: + raise AttributeError + except AttributeError: + for base in mro: + if key in base.__dict__: + value = base.__dict__[key] + break + else: + # could be a (currently) missing slot member, or a buggy + # __dir__; discard and move on + continue + if not predicate or predicate(value): + results.append((key, value)) + processed.add(key) + results.sort(key=lambda pair: pair[0]) + return results + +Attribute = namedtuple('Attribute', 'name kind defining_class object') + +def classify_class_attrs(cls): + """Return list of attribute-descriptor tuples. + + For each name in dir(cls), the return list contains a 4-tuple + with these elements: + + 0. The name (a string). + + 1. The kind of attribute this is, one of these strings: + 'class method' created via classmethod() + 'static method' created via staticmethod() + 'property' created via property() + 'method' any other flavor of method or descriptor + 'data' not a method + + 2. The class which defined this attribute (a class). + + 3. The object as obtained by calling getattr; if this fails, or if the + resulting object does not live anywhere in the class' mro (including + metaclasses) then the object is looked up in the defining class's + dict (found by walking the mro). + + If one of the items in dir(cls) is stored in the metaclass it will now + be discovered and not have None be listed as the class in which it was + defined. Any items whose home class cannot be discovered are skipped. + """ + + mro = getmro(cls) + metamro = getmro(type(cls)) # for attributes stored in the metaclass + metamro = tuple([cls for cls in metamro if cls not in (type, object)]) + class_bases = (cls,) + mro + all_bases = class_bases + metamro + names = dir(cls) + # :dd any DynamicClassAttributes to the list of names; + # this may result in duplicate entries if, for example, a virtual + # attribute with the same name as a DynamicClassAttribute exists. + for base in mro: + for k, v in base.__dict__.items(): + if isinstance(v, types.DynamicClassAttribute): + names.append(k) + result = [] + processed = set() + + for name in names: + # Get the object associated with the name, and where it was defined. + # Normal objects will be looked up with both getattr and directly in + # its class' dict (in case getattr fails [bug #1785], and also to look + # for a docstring). + # For DynamicClassAttributes on the second pass we only look in the + # class's dict. + # + # Getting an obj from the __dict__ sometimes reveals more than + # using getattr. Static and class methods are dramatic examples. + homecls = None + get_obj = None + dict_obj = None + if name not in processed: + try: + if name == '__dict__': + raise Exception("__dict__ is special, don't want the proxy") + get_obj = getattr(cls, name) + except Exception as exc: + pass + else: + homecls = getattr(get_obj, "__objclass__", homecls) + if homecls not in class_bases: + # if the resulting object does not live somewhere in the + # mro, drop it and search the mro manually + homecls = None + last_cls = None + # first look in the classes + for srch_cls in class_bases: + srch_obj = getattr(srch_cls, name, None) + if srch_obj is get_obj: + last_cls = srch_cls + # then check the metaclasses + for srch_cls in metamro: + try: + srch_obj = srch_cls.__getattr__(cls, name) + except AttributeError: + continue + if srch_obj is get_obj: + last_cls = srch_cls + if last_cls is not None: + homecls = last_cls + for base in all_bases: + if name in base.__dict__: + dict_obj = base.__dict__[name] + if homecls not in metamro: + homecls = base + break + if homecls is None: + # unable to locate the attribute anywhere, most likely due to + # buggy custom __dir__; discard and move on + continue + obj = get_obj if get_obj is not None else dict_obj + # Classify the object or its descriptor. + if isinstance(dict_obj, staticmethod): + kind = "static method" + obj = dict_obj + elif isinstance(dict_obj, classmethod): + kind = "class method" + obj = dict_obj + elif isinstance(dict_obj, property): + kind = "property" + obj = dict_obj + elif isroutine(obj): + kind = "method" + else: + kind = "data" + result.append(Attribute(name, kind, homecls, obj)) + processed.add(name) + return result + +# ----------------------------------------------------------- class helpers + +def getmro(cls): + "Return tuple of base classes (including cls) in method resolution order." + return cls.__mro__ + +# -------------------------------------------------------- function helpers + +def unwrap(func, *, stop=None): + """Get the object wrapped by *func*. + + Follows the chain of :attr:`__wrapped__` attributes returning the last + object in the chain. + + *stop* is an optional callback accepting an object in the wrapper chain + as its sole argument that allows the unwrapping to be terminated early if + the callback returns a true value. If the callback never returns a true + value, the last object in the chain is returned as usual. For example, + :func:`signature` uses this to stop unwrapping if any object in the + chain has a ``__signature__`` attribute defined. + + :exc:`ValueError` is raised if a cycle is encountered. + + """ + if stop is None: + def _is_wrapper(f): + return hasattr(f, '__wrapped__') + else: + def _is_wrapper(f): + return hasattr(f, '__wrapped__') and not stop(f) + f = func # remember the original func for error reporting + # Memoise by id to tolerate non-hashable objects, but store objects to + # ensure they aren't destroyed, which would allow their IDs to be reused. + memo = {id(f): f} + recursion_limit = sys.getrecursionlimit() + while _is_wrapper(func): + func = func.__wrapped__ + id_func = id(func) + if (id_func in memo) or (len(memo) >= recursion_limit): + raise ValueError('wrapper loop when unwrapping {!r}'.format(f)) + memo[id_func] = func + return func + +# -------------------------------------------------- source code extraction +def indentsize(line): + """Return the indent size, in spaces, at the start of a line of text.""" + expline = line.expandtabs() + return len(expline) - len(expline.lstrip()) + +def _findclass(func): + cls = sys.modules.get(func.__module__) + if cls is None: + return None + for name in func.__qualname__.split('.')[:-1]: + cls = getattr(cls, name) + if not isclass(cls): + return None + return cls + +def _finddoc(obj): + if isclass(obj): + for base in obj.__mro__: + if base is not object: + try: + doc = base.__doc__ + except AttributeError: + continue + if doc is not None: + return doc + return None + + if ismethod(obj): + name = obj.__func__.__name__ + self = obj.__self__ + if (isclass(self) and + getattr(getattr(self, name, None), '__func__') is obj.__func__): + # classmethod + cls = self + else: + cls = self.__class__ + elif isfunction(obj): + name = obj.__name__ + cls = _findclass(obj) + if cls is None or getattr(cls, name) is not obj: + return None + elif isbuiltin(obj): + name = obj.__name__ + self = obj.__self__ + if (isclass(self) and + self.__qualname__ + '.' + name == obj.__qualname__): + # classmethod + cls = self + else: + cls = self.__class__ + # Should be tested before isdatadescriptor(). + elif isinstance(obj, property): + func = obj.fget + name = func.__name__ + cls = _findclass(func) + if cls is None or getattr(cls, name) is not obj: + return None + elif ismethoddescriptor(obj) or isdatadescriptor(obj): + name = obj.__name__ + cls = obj.__objclass__ + if getattr(cls, name) is not obj: + return None + else: + return None + + for base in cls.__mro__: + try: + doc = getattr(base, name).__doc__ + except AttributeError: + continue + if doc is not None: + return doc + return None + +def getdoc(object): + """Get the documentation string for an object. + + All tabs are expanded to spaces. To clean up docstrings that are + indented to line up with blocks of code, any whitespace than can be + uniformly removed from the second line onwards is removed.""" + try: + doc = object.__doc__ + except AttributeError: + return None + if doc is None: + try: + doc = _finddoc(object) + except (AttributeError, TypeError): + return None + if not isinstance(doc, str): + return None + return cleandoc(doc) + +def cleandoc(doc): + """Clean up indentation from docstrings. + + Any whitespace that can be uniformly removed from the second line + onwards is removed.""" + try: + lines = doc.expandtabs().split('\n') + except UnicodeError: + return None + else: + # Find minimum indentation of any non-blank lines after first line. + margin = sys.maxsize + for line in lines[1:]: + content = len(line.lstrip()) + if content: + indent = len(line) - content + margin = min(margin, indent) + # Remove indentation. + if lines: + lines[0] = lines[0].lstrip() + if margin < sys.maxsize: + for i in range(1, len(lines)): lines[i] = lines[i][margin:] + # Remove any trailing or leading blank lines. + while lines and not lines[-1]: + lines.pop() + while lines and not lines[0]: + lines.pop(0) + return '\n'.join(lines) + +def getfile(object): + """Work out which source or compiled file an object was defined in.""" + if ismodule(object): + if hasattr(object, '__file__'): + return object.__file__ + raise TypeError('{!r} is a built-in module'.format(object)) + if isclass(object): + if hasattr(object, '__module__'): + object = sys.modules.get(object.__module__) + if hasattr(object, '__file__'): + return object.__file__ + raise TypeError('{!r} is a built-in class'.format(object)) + if ismethod(object): + object = object.__func__ + if isfunction(object): + object = object.__code__ + if istraceback(object): + object = object.tb_frame + if isframe(object): + object = object.f_code + if iscode(object): + return object.co_filename + raise TypeError('{!r} is not a module, class, method, ' + 'function, traceback, frame, or code object'.format(object)) + +def getmodulename(path): + """Return the module name for a given file, or None.""" + fname = os.path.basename(path) + # Check for paths that look like an actual module file + suffixes = [(-len(suffix), suffix) + for suffix in importlib.machinery.all_suffixes()] + suffixes.sort() # try longest suffixes first, in case they overlap + for neglen, suffix in suffixes: + if fname.endswith(suffix): + return fname[:neglen] + return None + +def getsourcefile(object): + """Return the filename that can be used to locate an object's source. + Return None if no way can be identified to get the source. + """ + filename = getfile(object) + all_bytecode_suffixes = importlib.machinery.DEBUG_BYTECODE_SUFFIXES[:] + all_bytecode_suffixes += importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES[:] + if any(filename.endswith(s) for s in all_bytecode_suffixes): + filename = (os.path.splitext(filename)[0] + + importlib.machinery.SOURCE_SUFFIXES[0]) + elif any(filename.endswith(s) for s in + importlib.machinery.EXTENSION_SUFFIXES): + return None + if os.path.exists(filename): + return filename + # only return a non-existent filename if the module has a PEP 302 loader + if getattr(getmodule(object, filename), '__loader__', None) is not None: + return filename + # or it is in the linecache + if filename in linecache.cache: + return filename + +def getabsfile(object, _filename=None): + """Return an absolute path to the source or compiled file for an object. + + The idea is for each object to have a unique origin, so this routine + normalizes the result as much as possible.""" + if _filename is None: + _filename = getsourcefile(object) or getfile(object) + return os.path.normcase(os.path.abspath(_filename)) + +modulesbyfile = {} +_filesbymodname = {} + +def getmodule(object, _filename=None): + """Return the module an object was defined in, or None if not found.""" + if ismodule(object): + return object + if hasattr(object, '__module__'): + return sys.modules.get(object.__module__) + # Try the filename to modulename cache + if _filename is not None and _filename in modulesbyfile: + return sys.modules.get(modulesbyfile[_filename]) + # Try the cache again with the absolute file name + try: + file = getabsfile(object, _filename) + except TypeError: + return None + if file in modulesbyfile: + return sys.modules.get(modulesbyfile[file]) + # Update the filename to module name cache and check yet again + # Copy sys.modules in order to cope with changes while iterating + for modname, module in list(sys.modules.items()): + if ismodule(module) and hasattr(module, '__file__'): + f = module.__file__ + if f == _filesbymodname.get(modname, None): + # Have already mapped this module, so skip it + continue + _filesbymodname[modname] = f + f = getabsfile(module) + # Always map to the name the module knows itself by + modulesbyfile[f] = modulesbyfile[ + os.path.realpath(f)] = module.__name__ + if file in modulesbyfile: + return sys.modules.get(modulesbyfile[file]) + # Check the main module + main = sys.modules['__main__'] + if not hasattr(object, '__name__'): + return None + if hasattr(main, object.__name__): + mainobject = getattr(main, object.__name__) + if mainobject is object: + return main + # Check builtins + builtin = sys.modules['builtins'] + if hasattr(builtin, object.__name__): + builtinobject = getattr(builtin, object.__name__) + if builtinobject is object: + return builtin + +def findsource(object): + """Return the entire source file and starting line number for an object. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a list of all the lines + in the file and the line number indexes a line in that list. An OSError + is raised if the source code cannot be retrieved.""" + + file = getsourcefile(object) + if file: + # Invalidate cache if needed. + linecache.checkcache(file) + else: + file = getfile(object) + # Allow filenames in form of "" to pass through. + # `doctest` monkeypatches `linecache` module to enable + # inspection, so let `linecache.getlines` to be called. + if not (file.startswith('<') and file.endswith('>')): + raise OSError('source code not available') + + module = getmodule(object, file) + if module: + lines = linecache.getlines(file, module.__dict__) + else: + lines = linecache.getlines(file) + if not lines: + raise OSError('could not get source code') + + if ismodule(object): + return lines, 0 + + if isclass(object): + name = object.__name__ + pat = re.compile(r'^(\s*)class\s*' + name + r'\b') + # make some effort to find the best matching class definition: + # use the one with the least indentation, which is the one + # that's most probably not inside a function definition. + candidates = [] + for i in range(len(lines)): + match = pat.match(lines[i]) + if match: + # if it's at toplevel, it's already the best one + if lines[i][0] == 'c': + return lines, i + # else add whitespace to candidate list + candidates.append((match.group(1), i)) + if candidates: + # this will sort by whitespace, and by line number, + # less whitespace first + candidates.sort() + return lines, candidates[0][1] + else: + raise OSError('could not find class definition') + + if ismethod(object): + object = object.__func__ + if isfunction(object): + object = object.__code__ + if istraceback(object): + object = object.tb_frame + if isframe(object): + object = object.f_code + if iscode(object): + if not hasattr(object, 'co_firstlineno'): + raise OSError('could not find function definition') + lnum = object.co_firstlineno - 1 + pat = re.compile(r'^(\s*def\s)|(\s*async\s+def\s)|(.*(? 0: + if pat.match(lines[lnum]): break + lnum = lnum - 1 + return lines, lnum + raise OSError('could not find code object') + +def getcomments(object): + """Get lines of comments immediately preceding an object's source code. + + Returns None when source can't be found. + """ + try: + lines, lnum = findsource(object) + except (OSError, TypeError): + return None + + if ismodule(object): + # Look for a comment block at the top of the file. + start = 0 + if lines and lines[0][:2] == '#!': start = 1 + while start < len(lines) and lines[start].strip() in ('', '#'): + start = start + 1 + if start < len(lines) and lines[start][:1] == '#': + comments = [] + end = start + while end < len(lines) and lines[end][:1] == '#': + comments.append(lines[end].expandtabs()) + end = end + 1 + return ''.join(comments) + + # Look for a preceding block of comments at the same indentation. + elif lnum > 0: + indent = indentsize(lines[lnum]) + end = lnum - 1 + if end >= 0 and lines[end].lstrip()[:1] == '#' and \ + indentsize(lines[end]) == indent: + comments = [lines[end].expandtabs().lstrip()] + if end > 0: + end = end - 1 + comment = lines[end].expandtabs().lstrip() + while comment[:1] == '#' and indentsize(lines[end]) == indent: + comments[:0] = [comment] + end = end - 1 + if end < 0: break + comment = lines[end].expandtabs().lstrip() + while comments and comments[0].strip() == '#': + comments[:1] = [] + while comments and comments[-1].strip() == '#': + comments[-1:] = [] + return ''.join(comments) + +class EndOfBlock(Exception): pass + +class BlockFinder: + """Provide a tokeneater() method to detect the end of a code block.""" + def __init__(self): + self.indent = 0 + self.islambda = False + self.started = False + self.passline = False + self.indecorator = False + self.decoratorhasargs = False + self.last = 1 + + def tokeneater(self, type, token, srowcol, erowcol, line): + if not self.started and not self.indecorator: + # skip any decorators + if token == "@": + self.indecorator = True + # look for the first "def", "class" or "lambda" + elif token in ("def", "class", "lambda"): + if token == "lambda": + self.islambda = True + self.started = True + self.passline = True # skip to the end of the line + elif token == "(": + if self.indecorator: + self.decoratorhasargs = True + elif token == ")": + if self.indecorator: + self.indecorator = False + self.decoratorhasargs = False + elif type == tokenize.NEWLINE: + self.passline = False # stop skipping when a NEWLINE is seen + self.last = srowcol[0] + if self.islambda: # lambdas always end at the first NEWLINE + raise EndOfBlock + # hitting a NEWLINE when in a decorator without args + # ends the decorator + if self.indecorator and not self.decoratorhasargs: + self.indecorator = False + elif self.passline: + pass + elif type == tokenize.INDENT: + self.indent = self.indent + 1 + self.passline = True + elif type == tokenize.DEDENT: + self.indent = self.indent - 1 + # the end of matching indent/dedent pairs end a block + # (note that this only works for "def"/"class" blocks, + # not e.g. for "if: else:" or "try: finally:" blocks) + if self.indent <= 0: + raise EndOfBlock + elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL): + # any other token on the same indentation level end the previous + # block as well, except the pseudo-tokens COMMENT and NL. + raise EndOfBlock + +def getblock(lines): + """Extract the block of code at the top of the given list of lines.""" + blockfinder = BlockFinder() + try: + tokens = tokenize.generate_tokens(iter(lines).__next__) + for _token in tokens: + blockfinder.tokeneater(*_token) + except (EndOfBlock, IndentationError): + pass + return lines[:blockfinder.last] + +def getsourcelines(object): + """Return a list of source lines and starting line number for an object. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a list of the lines + corresponding to the object and the line number indicates where in the + original source file the first line of code was found. An OSError is + raised if the source code cannot be retrieved.""" + object = unwrap(object) + lines, lnum = findsource(object) + + if istraceback(object): + object = object.tb_frame + + # for module or frame that corresponds to module, return all source lines + if (ismodule(object) or + (isframe(object) and object.f_code.co_name == "")): + return lines, 0 + else: + return getblock(lines[lnum:]), lnum + 1 + +def getsource(object): + """Return the text of the source code for an object. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a single string. An + OSError is raised if the source code cannot be retrieved.""" + lines, lnum = getsourcelines(object) + return ''.join(lines) + +# --------------------------------------------------- class tree extraction +def walktree(classes, children, parent): + """Recursive helper function for getclasstree().""" + results = [] + classes.sort(key=attrgetter('__module__', '__name__')) + for c in classes: + results.append((c, c.__bases__)) + if c in children: + results.append(walktree(children[c], children, c)) + return results + +def getclasstree(classes, unique=False): + """Arrange the given list of classes into a hierarchy of nested lists. + + Where a nested list appears, it contains classes derived from the class + whose entry immediately precedes the list. Each entry is a 2-tuple + containing a class and a tuple of its base classes. If the 'unique' + argument is true, exactly one entry appears in the returned structure + for each class in the given list. Otherwise, classes using multiple + inheritance and their descendants will appear multiple times.""" + children = {} + roots = [] + for c in classes: + if c.__bases__: + for parent in c.__bases__: + if not parent in children: + children[parent] = [] + if c not in children[parent]: + children[parent].append(c) + if unique and parent in classes: break + elif c not in roots: + roots.append(c) + for parent in children: + if parent not in classes: + roots.append(parent) + return walktree(roots, children, None) + +# ------------------------------------------------ argument list extraction +Arguments = namedtuple('Arguments', 'args, varargs, varkw') + +def getargs(co): + """Get information about the arguments accepted by a code object. + + Three things are returned: (args, varargs, varkw), where + 'args' is the list of argument names. Keyword-only arguments are + appended. 'varargs' and 'varkw' are the names of the * and ** + arguments or None.""" + args, varargs, kwonlyargs, varkw = _getfullargs(co) + return Arguments(args + kwonlyargs, varargs, varkw) + +def _getfullargs(co): + """Get information about the arguments accepted by a code object. + + Four things are returned: (args, varargs, kwonlyargs, varkw), where + 'args' and 'kwonlyargs' are lists of argument names, and 'varargs' + and 'varkw' are the names of the * and ** arguments or None.""" + + if not iscode(co): + raise TypeError('{!r} is not a code object'.format(co)) + + nargs = co.co_argcount + names = co.co_varnames + nkwargs = co.co_kwonlyargcount + args = list(names[:nargs]) + kwonlyargs = list(names[nargs:nargs+nkwargs]) + step = 0 + + nargs += nkwargs + varargs = None + if co.co_flags & CO_VARARGS: + varargs = co.co_varnames[nargs] + nargs = nargs + 1 + varkw = None + if co.co_flags & CO_VARKEYWORDS: + varkw = co.co_varnames[nargs] + return args, varargs, kwonlyargs, varkw + + +ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults') + +def getargspec(func): + """Get the names and default values of a function's parameters. + + A tuple of four things is returned: (args, varargs, keywords, defaults). + 'args' is a list of the argument names, including keyword-only argument names. + 'varargs' and 'keywords' are the names of the * and ** parameters or None. + 'defaults' is an n-tuple of the default values of the last n parameters. + + This function is deprecated, as it does not support annotations or + keyword-only parameters and will raise ValueError if either is present + on the supplied callable. + + For a more structured introspection API, use inspect.signature() instead. + + Alternatively, use getfullargspec() for an API with a similar namedtuple + based interface, but full support for annotations and keyword-only + parameters. + + Deprecated since Python 3.5, use `inspect.getfullargspec()`. + """ + warnings.warn("inspect.getargspec() is deprecated since Python 3.0, " + "use inspect.signature() or inspect.getfullargspec()", + DeprecationWarning, stacklevel=2) + args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ + getfullargspec(func) + if kwonlyargs or ann: + raise ValueError("Function has keyword-only parameters or annotations" + ", use getfullargspec() API which can support them") + return ArgSpec(args, varargs, varkw, defaults) + +FullArgSpec = namedtuple('FullArgSpec', + 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations') + +def getfullargspec(func): + """Get the names and default values of a callable object's parameters. + + A tuple of seven things is returned: + (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations). + 'args' is a list of the parameter names. + 'varargs' and 'varkw' are the names of the * and ** parameters or None. + 'defaults' is an n-tuple of the default values of the last n parameters. + 'kwonlyargs' is a list of keyword-only parameter names. + 'kwonlydefaults' is a dictionary mapping names from kwonlyargs to defaults. + 'annotations' is a dictionary mapping parameter names to annotations. + + Notable differences from inspect.signature(): + - the "self" parameter is always reported, even for bound methods + - wrapper chains defined by __wrapped__ *not* unwrapped automatically + """ + + try: + # Re: `skip_bound_arg=False` + # + # There is a notable difference in behaviour between getfullargspec + # and Signature: the former always returns 'self' parameter for bound + # methods, whereas the Signature always shows the actual calling + # signature of the passed object. + # + # To simulate this behaviour, we "unbind" bound methods, to trick + # inspect.signature to always return their first parameter ("self", + # usually) + + # Re: `follow_wrapper_chains=False` + # + # getfullargspec() historically ignored __wrapped__ attributes, + # so we ensure that remains the case in 3.3+ + + sig = _signature_from_callable(func, + follow_wrapper_chains=False, + skip_bound_arg=False, + sigcls=Signature) + except Exception as ex: + # Most of the times 'signature' will raise ValueError. + # But, it can also raise AttributeError, and, maybe something + # else. So to be fully backwards compatible, we catch all + # possible exceptions here, and reraise a TypeError. + raise TypeError('unsupported callable') from ex + + args = [] + varargs = None + varkw = None + kwonlyargs = [] + defaults = () + annotations = {} + defaults = () + kwdefaults = {} + + if sig.return_annotation is not sig.empty: + annotations['return'] = sig.return_annotation + + for param in sig.parameters.values(): + kind = param.kind + name = param.name + + if kind is _POSITIONAL_ONLY: + args.append(name) + elif kind is _POSITIONAL_OR_KEYWORD: + args.append(name) + if param.default is not param.empty: + defaults += (param.default,) + elif kind is _VAR_POSITIONAL: + varargs = name + elif kind is _KEYWORD_ONLY: + kwonlyargs.append(name) + if param.default is not param.empty: + kwdefaults[name] = param.default + elif kind is _VAR_KEYWORD: + varkw = name + + if param.annotation is not param.empty: + annotations[name] = param.annotation + + if not kwdefaults: + # compatibility with 'func.__kwdefaults__' + kwdefaults = None + + if not defaults: + # compatibility with 'func.__defaults__' + defaults = None + + return FullArgSpec(args, varargs, varkw, defaults, + kwonlyargs, kwdefaults, annotations) + + +ArgInfo = namedtuple('ArgInfo', 'args varargs keywords locals') + +def getargvalues(frame): + """Get information about arguments passed into a particular frame. + + A tuple of four things is returned: (args, varargs, varkw, locals). + 'args' is a list of the argument names. + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + 'locals' is the locals dictionary of the given frame.""" + args, varargs, varkw = getargs(frame.f_code) + return ArgInfo(args, varargs, varkw, frame.f_locals) + +def formatannotation(annotation, base_module=None): + if getattr(annotation, '__module__', None) == 'typing': + return repr(annotation).replace('typing.', '') + if isinstance(annotation, type): + if annotation.__module__ in ('builtins', base_module): + return annotation.__qualname__ + return annotation.__module__+'.'+annotation.__qualname__ + return repr(annotation) + +def formatannotationrelativeto(object): + module = getattr(object, '__module__', None) + def _formatannotation(annotation): + return formatannotation(annotation, module) + return _formatannotation + +def formatargspec(args, varargs=None, varkw=None, defaults=None, + kwonlyargs=(), kwonlydefaults={}, annotations={}, + formatarg=str, + formatvarargs=lambda name: '*' + name, + formatvarkw=lambda name: '**' + name, + formatvalue=lambda value: '=' + repr(value), + formatreturns=lambda text: ' -> ' + text, + formatannotation=formatannotation): + """Format an argument spec from the values returned by getfullargspec. + + The first seven arguments are (args, varargs, varkw, defaults, + kwonlyargs, kwonlydefaults, annotations). The other five arguments + are the corresponding optional formatting functions that are called to + turn names and values into strings. The last argument is an optional + function to format the sequence of arguments.""" + def formatargandannotation(arg): + result = formatarg(arg) + if arg in annotations: + result += ': ' + formatannotation(annotations[arg]) + return result + specs = [] + if defaults: + firstdefault = len(args) - len(defaults) + for i, arg in enumerate(args): + spec = formatargandannotation(arg) + if defaults and i >= firstdefault: + spec = spec + formatvalue(defaults[i - firstdefault]) + specs.append(spec) + if varargs is not None: + specs.append(formatvarargs(formatargandannotation(varargs))) + else: + if kwonlyargs: + specs.append('*') + if kwonlyargs: + for kwonlyarg in kwonlyargs: + spec = formatargandannotation(kwonlyarg) + if kwonlydefaults and kwonlyarg in kwonlydefaults: + spec += formatvalue(kwonlydefaults[kwonlyarg]) + specs.append(spec) + if varkw is not None: + specs.append(formatvarkw(formatargandannotation(varkw))) + result = '(' + ', '.join(specs) + ')' + if 'return' in annotations: + result += formatreturns(formatannotation(annotations['return'])) + return result + +def formatargvalues(args, varargs, varkw, locals, + formatarg=str, + formatvarargs=lambda name: '*' + name, + formatvarkw=lambda name: '**' + name, + formatvalue=lambda value: '=' + repr(value)): + """Format an argument spec from the 4 values returned by getargvalues. + + The first four arguments are (args, varargs, varkw, locals). The + next four arguments are the corresponding optional formatting functions + that are called to turn names and values into strings. The ninth + argument is an optional function to format the sequence of arguments.""" + def convert(name, locals=locals, + formatarg=formatarg, formatvalue=formatvalue): + return formatarg(name) + formatvalue(locals[name]) + specs = [] + for i in range(len(args)): + specs.append(convert(args[i])) + if varargs: + specs.append(formatvarargs(varargs) + formatvalue(locals[varargs])) + if varkw: + specs.append(formatvarkw(varkw) + formatvalue(locals[varkw])) + return '(' + ', '.join(specs) + ')' + +def _missing_arguments(f_name, argnames, pos, values): + names = [repr(name) for name in argnames if name not in values] + missing = len(names) + if missing == 1: + s = names[0] + elif missing == 2: + s = "{} and {}".format(*names) + else: + tail = ", {} and {}".format(*names[-2:]) + del names[-2:] + s = ", ".join(names) + tail + raise TypeError("%s() missing %i required %s argument%s: %s" % + (f_name, missing, + "positional" if pos else "keyword-only", + "" if missing == 1 else "s", s)) + +def _too_many(f_name, args, kwonly, varargs, defcount, given, values): + atleast = len(args) - defcount + kwonly_given = len([arg for arg in kwonly if arg in values]) + if varargs: + plural = atleast != 1 + sig = "at least %d" % (atleast,) + elif defcount: + plural = True + sig = "from %d to %d" % (atleast, len(args)) + else: + plural = len(args) != 1 + sig = str(len(args)) + kwonly_sig = "" + if kwonly_given: + msg = " positional argument%s (and %d keyword-only argument%s)" + kwonly_sig = (msg % ("s" if given != 1 else "", kwonly_given, + "s" if kwonly_given != 1 else "")) + raise TypeError("%s() takes %s positional argument%s but %d%s %s given" % + (f_name, sig, "s" if plural else "", given, kwonly_sig, + "was" if given == 1 and not kwonly_given else "were")) + +def getcallargs(*func_and_positional, **named): + """Get the mapping of arguments to values. + + A dict is returned, with keys the function argument names (including the + names of the * and ** arguments, if any), and values the respective bound + values from 'positional' and 'named'.""" + func = func_and_positional[0] + positional = func_and_positional[1:] + spec = getfullargspec(func) + args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = spec + f_name = func.__name__ + arg2value = {} + + + if ismethod(func) and func.__self__ is not None: + # implicit 'self' (or 'cls' for classmethods) argument + positional = (func.__self__,) + positional + num_pos = len(positional) + num_args = len(args) + num_defaults = len(defaults) if defaults else 0 + + n = min(num_pos, num_args) + for i in range(n): + arg2value[args[i]] = positional[i] + if varargs: + arg2value[varargs] = tuple(positional[n:]) + possible_kwargs = set(args + kwonlyargs) + if varkw: + arg2value[varkw] = {} + for kw, value in named.items(): + if kw not in possible_kwargs: + if not varkw: + raise TypeError("%s() got an unexpected keyword argument %r" % + (f_name, kw)) + arg2value[varkw][kw] = value + continue + if kw in arg2value: + raise TypeError("%s() got multiple values for argument %r" % + (f_name, kw)) + arg2value[kw] = value + if num_pos > num_args and not varargs: + _too_many(f_name, args, kwonlyargs, varargs, num_defaults, + num_pos, arg2value) + if num_pos < num_args: + req = args[:num_args - num_defaults] + for arg in req: + if arg not in arg2value: + _missing_arguments(f_name, req, True, arg2value) + for i, arg in enumerate(args[num_args - num_defaults:]): + if arg not in arg2value: + arg2value[arg] = defaults[i] + missing = 0 + for kwarg in kwonlyargs: + if kwarg not in arg2value: + if kwonlydefaults and kwarg in kwonlydefaults: + arg2value[kwarg] = kwonlydefaults[kwarg] + else: + missing += 1 + if missing: + _missing_arguments(f_name, kwonlyargs, False, arg2value) + return arg2value + +ClosureVars = namedtuple('ClosureVars', 'nonlocals globals builtins unbound') + +def getclosurevars(func): + """ + Get the mapping of free variables to their current values. + + Returns a named tuple of dicts mapping the current nonlocal, global + and builtin references as seen by the body of the function. A final + set of unbound names that could not be resolved is also provided. + """ + + if ismethod(func): + func = func.__func__ + + if not isfunction(func): + raise TypeError("'{!r}' is not a Python function".format(func)) + + code = func.__code__ + # Nonlocal references are named in co_freevars and resolved + # by looking them up in __closure__ by positional index + if func.__closure__ is None: + nonlocal_vars = {} + else: + nonlocal_vars = { + var : cell.cell_contents + for var, cell in zip(code.co_freevars, func.__closure__) + } + + # Global and builtin references are named in co_names and resolved + # by looking them up in __globals__ or __builtins__ + global_ns = func.__globals__ + builtin_ns = global_ns.get("__builtins__", builtins.__dict__) + if ismodule(builtin_ns): + builtin_ns = builtin_ns.__dict__ + global_vars = {} + builtin_vars = {} + unbound_names = set() + for name in code.co_names: + if name in ("None", "True", "False"): + # Because these used to be builtins instead of keywords, they + # may still show up as name references. We ignore them. + continue + try: + global_vars[name] = global_ns[name] + except KeyError: + try: + builtin_vars[name] = builtin_ns[name] + except KeyError: + unbound_names.add(name) + + return ClosureVars(nonlocal_vars, global_vars, + builtin_vars, unbound_names) + +# -------------------------------------------------- stack frame extraction + +Traceback = namedtuple('Traceback', 'filename lineno function code_context index') + +def getframeinfo(frame, context=1): + """Get information about a frame or traceback object. + + A tuple of five things is returned: the filename, the line number of + the current line, the function name, a list of lines of context from + the source code, and the index of the current line within that list. + The optional second argument specifies the number of lines of context + to return, which are centered around the current line.""" + if istraceback(frame): + lineno = frame.tb_lineno + frame = frame.tb_frame + else: + lineno = frame.f_lineno + if not isframe(frame): + raise TypeError('{!r} is not a frame or traceback object'.format(frame)) + + filename = getsourcefile(frame) or getfile(frame) + if context > 0: + start = lineno - 1 - context//2 + try: + lines, lnum = findsource(frame) + except OSError: + lines = index = None + else: + start = max(0, min(start, len(lines) - context)) + lines = lines[start:start+context] + index = lineno - 1 - start + else: + lines = index = None + + return Traceback(filename, lineno, frame.f_code.co_name, lines, index) + +def getlineno(frame): + """Get the line number from a frame object, allowing for optimization.""" + # FrameType.f_lineno is now a descriptor that grovels co_lnotab + return frame.f_lineno + +FrameInfo = namedtuple('FrameInfo', ('frame',) + Traceback._fields) + +def getouterframes(frame, context=1): + """Get a list of records for a frame and all higher (calling) frames. + + Each record contains a frame object, filename, line number, function + name, a list of lines of context, and index within the context.""" + framelist = [] + while frame: + frameinfo = (frame,) + getframeinfo(frame, context) + framelist.append(FrameInfo(*frameinfo)) + frame = frame.f_back + return framelist + +def getinnerframes(tb, context=1): + """Get a list of records for a traceback's frame and all lower frames. + + Each record contains a frame object, filename, line number, function + name, a list of lines of context, and index within the context.""" + framelist = [] + while tb: + frameinfo = (tb.tb_frame,) + getframeinfo(tb, context) + framelist.append(FrameInfo(*frameinfo)) + tb = tb.tb_next + return framelist + +def currentframe(): + """Return the frame of the caller or None if this is not possible.""" + return sys._getframe(1) if hasattr(sys, "_getframe") else None + +def stack(context=1): + """Return a list of records for the stack above the caller's frame.""" + return getouterframes(sys._getframe(1), context) + +def trace(context=1): + """Return a list of records for the stack below the current exception.""" + return getinnerframes(sys.exc_info()[2], context) + + +# ------------------------------------------------ static version of getattr + +_sentinel = object() + +def _static_getmro(klass): + return type.__dict__['__mro__'].__get__(klass) + +def _check_instance(obj, attr): + instance_dict = {} + try: + instance_dict = object.__getattribute__(obj, "__dict__") + except AttributeError: + pass + return dict.get(instance_dict, attr, _sentinel) + + +def _check_class(klass, attr): + for entry in _static_getmro(klass): + if _shadowed_dict(type(entry)) is _sentinel: + try: + return entry.__dict__[attr] + except KeyError: + pass + return _sentinel + +def _is_type(obj): + try: + _static_getmro(obj) + except TypeError: + return False + return True + +def _shadowed_dict(klass): + dict_attr = type.__dict__["__dict__"] + for entry in _static_getmro(klass): + try: + class_dict = dict_attr.__get__(entry)["__dict__"] + except KeyError: + pass + else: + if not (type(class_dict) is types.GetSetDescriptorType and + class_dict.__name__ == "__dict__" and + class_dict.__objclass__ is entry): + return class_dict + return _sentinel + +def getattr_static(obj, attr, default=_sentinel): + """Retrieve attributes without triggering dynamic lookup via the + descriptor protocol, __getattr__ or __getattribute__. + + Note: this function may not be able to retrieve all attributes + that getattr can fetch (like dynamically created attributes) + and may find attributes that getattr can't (like descriptors + that raise AttributeError). It can also return descriptor objects + instead of instance members in some cases. See the + documentation for details. + """ + instance_result = _sentinel + if not _is_type(obj): + klass = type(obj) + dict_attr = _shadowed_dict(klass) + if (dict_attr is _sentinel or + type(dict_attr) is types.MemberDescriptorType): + instance_result = _check_instance(obj, attr) + else: + klass = obj + + klass_result = _check_class(klass, attr) + + if instance_result is not _sentinel and klass_result is not _sentinel: + if (_check_class(type(klass_result), '__get__') is not _sentinel and + _check_class(type(klass_result), '__set__') is not _sentinel): + return klass_result + + if instance_result is not _sentinel: + return instance_result + if klass_result is not _sentinel: + return klass_result + + if obj is klass: + # for types we check the metaclass too + for entry in _static_getmro(type(klass)): + if _shadowed_dict(type(entry)) is _sentinel: + try: + return entry.__dict__[attr] + except KeyError: + pass + if default is not _sentinel: + return default + raise AttributeError(attr) + + +# ------------------------------------------------ generator introspection + +GEN_CREATED = 'GEN_CREATED' +GEN_RUNNING = 'GEN_RUNNING' +GEN_SUSPENDED = 'GEN_SUSPENDED' +GEN_CLOSED = 'GEN_CLOSED' + +def getgeneratorstate(generator): + """Get current state of a generator-iterator. + + Possible states are: + GEN_CREATED: Waiting to start execution. + GEN_RUNNING: Currently being executed by the interpreter. + GEN_SUSPENDED: Currently suspended at a yield expression. + GEN_CLOSED: Execution has completed. + """ + if generator.gi_running: + return GEN_RUNNING + if generator.gi_frame is None: + return GEN_CLOSED + if generator.gi_frame.f_lasti == -1: + return GEN_CREATED + return GEN_SUSPENDED + + +def getgeneratorlocals(generator): + """ + Get the mapping of generator local variables to their current values. + + A dict is returned, with the keys the local variable names and values the + bound values.""" + + if not isgenerator(generator): + raise TypeError("'{!r}' is not a Python generator".format(generator)) + + frame = getattr(generator, "gi_frame", None) + if frame is not None: + return generator.gi_frame.f_locals + else: + return {} + + +# ------------------------------------------------ coroutine introspection + +CORO_CREATED = 'CORO_CREATED' +CORO_RUNNING = 'CORO_RUNNING' +CORO_SUSPENDED = 'CORO_SUSPENDED' +CORO_CLOSED = 'CORO_CLOSED' + +def getcoroutinestate(coroutine): + """Get current state of a coroutine object. + + Possible states are: + CORO_CREATED: Waiting to start execution. + CORO_RUNNING: Currently being executed by the interpreter. + CORO_SUSPENDED: Currently suspended at an await expression. + CORO_CLOSED: Execution has completed. + """ + if coroutine.cr_running: + return CORO_RUNNING + if coroutine.cr_frame is None: + return CORO_CLOSED + if coroutine.cr_frame.f_lasti == -1: + return CORO_CREATED + return CORO_SUSPENDED + + +def getcoroutinelocals(coroutine): + """ + Get the mapping of coroutine local variables to their current values. + + A dict is returned, with the keys the local variable names and values the + bound values.""" + frame = getattr(coroutine, "cr_frame", None) + if frame is not None: + return frame.f_locals + else: + return {} + + +############################################################################### +### Function Signature Object (PEP 362) +############################################################################### + + +_WrapperDescriptor = type(type.__call__) +_MethodWrapper = type(all.__call__) +_ClassMethodWrapper = type(int.__dict__['from_bytes']) + +_NonUserDefinedCallables = (_WrapperDescriptor, + _MethodWrapper, + _ClassMethodWrapper, + types.BuiltinFunctionType) + + +def _signature_get_user_defined_method(cls, method_name): + """Private helper. Checks if ``cls`` has an attribute + named ``method_name`` and returns it only if it is a + pure python function. + """ + try: + meth = getattr(cls, method_name) + except AttributeError: + return + else: + if not isinstance(meth, _NonUserDefinedCallables): + # Once '__signature__' will be added to 'C'-level + # callables, this check won't be necessary + return meth + + +def _signature_get_partial(wrapped_sig, partial, extra_args=()): + """Private helper to calculate how 'wrapped_sig' signature will + look like after applying a 'functools.partial' object (or alike) + on it. + """ + + old_params = wrapped_sig.parameters + new_params = OrderedDict(old_params.items()) + + partial_args = partial.args or () + partial_keywords = partial.keywords or {} + + if extra_args: + partial_args = extra_args + partial_args + + try: + ba = wrapped_sig.bind_partial(*partial_args, **partial_keywords) + except TypeError as ex: + msg = 'partial object {!r} has incorrect arguments'.format(partial) + raise ValueError(msg) from ex + + + transform_to_kwonly = False + for param_name, param in old_params.items(): + try: + arg_value = ba.arguments[param_name] + except KeyError: + pass + else: + if param.kind is _POSITIONAL_ONLY: + # If positional-only parameter is bound by partial, + # it effectively disappears from the signature + new_params.pop(param_name) + continue + + if param.kind is _POSITIONAL_OR_KEYWORD: + if param_name in partial_keywords: + # This means that this parameter, and all parameters + # after it should be keyword-only (and var-positional + # should be removed). Here's why. Consider the following + # function: + # foo(a, b, *args, c): + # pass + # + # "partial(foo, a='spam')" will have the following + # signature: "(*, a='spam', b, c)". Because attempting + # to call that partial with "(10, 20)" arguments will + # raise a TypeError, saying that "a" argument received + # multiple values. + transform_to_kwonly = True + # Set the new default value + new_params[param_name] = param.replace(default=arg_value) + else: + # was passed as a positional argument + new_params.pop(param.name) + continue + + if param.kind is _KEYWORD_ONLY: + # Set the new default value + new_params[param_name] = param.replace(default=arg_value) + + if transform_to_kwonly: + assert param.kind is not _POSITIONAL_ONLY + + if param.kind is _POSITIONAL_OR_KEYWORD: + new_param = new_params[param_name].replace(kind=_KEYWORD_ONLY) + new_params[param_name] = new_param + new_params.move_to_end(param_name) + elif param.kind in (_KEYWORD_ONLY, _VAR_KEYWORD): + new_params.move_to_end(param_name) + elif param.kind is _VAR_POSITIONAL: + new_params.pop(param.name) + + return wrapped_sig.replace(parameters=new_params.values()) + + +def _signature_bound_method(sig): + """Private helper to transform signatures for unbound + functions to bound methods. + """ + + params = tuple(sig.parameters.values()) + + if not params or params[0].kind in (_VAR_KEYWORD, _KEYWORD_ONLY): + raise ValueError('invalid method signature') + + kind = params[0].kind + if kind in (_POSITIONAL_OR_KEYWORD, _POSITIONAL_ONLY): + # Drop first parameter: + # '(p1, p2[, ...])' -> '(p2[, ...])' + params = params[1:] + else: + if kind is not _VAR_POSITIONAL: + # Unless we add a new parameter type we never + # get here + raise ValueError('invalid argument type') + # It's a var-positional parameter. + # Do nothing. '(*args[, ...])' -> '(*args[, ...])' + + return sig.replace(parameters=params) + + +def _signature_is_builtin(obj): + """Private helper to test if `obj` is a callable that might + support Argument Clinic's __text_signature__ protocol. + """ + return (isbuiltin(obj) or + ismethoddescriptor(obj) or + isinstance(obj, _NonUserDefinedCallables) or + # Can't test 'isinstance(type)' here, as it would + # also be True for regular python classes + obj in (type, object)) + + +def _signature_is_functionlike(obj): + """Private helper to test if `obj` is a duck type of FunctionType. + A good example of such objects are functions compiled with + Cython, which have all attributes that a pure Python function + would have, but have their code statically compiled. + """ + + if not callable(obj) or isclass(obj): + # All function-like objects are obviously callables, + # and not classes. + return False + + name = getattr(obj, '__name__', None) + code = getattr(obj, '__code__', None) + defaults = getattr(obj, '__defaults__', _void) # Important to use _void ... + kwdefaults = getattr(obj, '__kwdefaults__', _void) # ... and not None here + annotations = getattr(obj, '__annotations__', None) + + return (isinstance(code, types.CodeType) and + isinstance(name, str) and + (defaults is None or isinstance(defaults, tuple)) and + (kwdefaults is None or isinstance(kwdefaults, dict)) and + isinstance(annotations, dict)) + + +def _signature_get_bound_param(spec): + """ Private helper to get first parameter name from a + __text_signature__ of a builtin method, which should + be in the following format: '($param1, ...)'. + Assumptions are that the first argument won't have + a default value or an annotation. + """ + + assert spec.startswith('($') + + pos = spec.find(',') + if pos == -1: + pos = spec.find(')') + + cpos = spec.find(':') + assert cpos == -1 or cpos > pos + + cpos = spec.find('=') + assert cpos == -1 or cpos > pos + + return spec[2:pos] + + +def _signature_strip_non_python_syntax(signature): + """ + Private helper function. Takes a signature in Argument Clinic's + extended signature format. + + Returns a tuple of three things: + * that signature re-rendered in standard Python syntax, + * the index of the "self" parameter (generally 0), or None if + the function does not have a "self" parameter, and + * the index of the last "positional only" parameter, + or None if the signature has no positional-only parameters. + """ + + if not signature: + return signature, None, None + + self_parameter = None + last_positional_only = None + + lines = [l.encode('ascii') for l in signature.split('\n')] + generator = iter(lines).__next__ + token_stream = tokenize.tokenize(generator) + + delayed_comma = False + skip_next_comma = False + text = [] + add = text.append + + current_parameter = 0 + OP = token.OP + ERRORTOKEN = token.ERRORTOKEN + + # token stream always starts with ENCODING token, skip it + t = next(token_stream) + assert t.type == tokenize.ENCODING + + for t in token_stream: + type, string = t.type, t.string + + if type == OP: + if string == ',': + if skip_next_comma: + skip_next_comma = False + else: + assert not delayed_comma + delayed_comma = True + current_parameter += 1 + continue + + if string == '/': + assert not skip_next_comma + assert last_positional_only is None + skip_next_comma = True + last_positional_only = current_parameter - 1 + continue + + if (type == ERRORTOKEN) and (string == '$'): + assert self_parameter is None + self_parameter = current_parameter + continue + + if delayed_comma: + delayed_comma = False + if not ((type == OP) and (string == ')')): + add(', ') + add(string) + if (string == ','): + add(' ') + clean_signature = ''.join(text) + return clean_signature, self_parameter, last_positional_only + + +def _signature_fromstr(cls, obj, s, skip_bound_arg=True): + """Private helper to parse content of '__text_signature__' + and return a Signature based on it. + """ + + Parameter = cls._parameter_cls + + clean_signature, self_parameter, last_positional_only = \ + _signature_strip_non_python_syntax(s) + + program = "def foo" + clean_signature + ": pass" + + try: + module = ast.parse(program) + except SyntaxError: + module = None + + if not isinstance(module, ast.Module): + raise ValueError("{!r} builtin has invalid signature".format(obj)) + + f = module.body[0] + + parameters = [] + empty = Parameter.empty + invalid = object() + + module = None + module_dict = {} + module_name = getattr(obj, '__module__', None) + if module_name: + module = sys.modules.get(module_name, None) + if module: + module_dict = module.__dict__ + sys_module_dict = sys.modules.copy() + + def parse_name(node): + assert isinstance(node, ast.arg) + if node.annotation != None: + raise ValueError("Annotations are not currently supported") + return node.arg + + def wrap_value(s): + try: + value = eval(s, module_dict) + except NameError: + try: + value = eval(s, sys_module_dict) + except NameError: + raise RuntimeError() + + if isinstance(value, str): + return ast.Str(value) + if isinstance(value, (int, float)): + return ast.Num(value) + if isinstance(value, bytes): + return ast.Bytes(value) + if value in (True, False, None): + return ast.NameConstant(value) + raise RuntimeError() + + class RewriteSymbolics(ast.NodeTransformer): + def visit_Attribute(self, node): + a = [] + n = node + while isinstance(n, ast.Attribute): + a.append(n.attr) + n = n.value + if not isinstance(n, ast.Name): + raise RuntimeError() + a.append(n.id) + value = ".".join(reversed(a)) + return wrap_value(value) + + def visit_Name(self, node): + if not isinstance(node.ctx, ast.Load): + raise ValueError() + return wrap_value(node.id) + + def p(name_node, default_node, default=empty): + name = parse_name(name_node) + if name is invalid: + return None + if default_node and default_node is not _empty: + try: + default_node = RewriteSymbolics().visit(default_node) + o = ast.literal_eval(default_node) + except ValueError: + o = invalid + if o is invalid: + return None + default = o if o is not invalid else default + parameters.append(Parameter(name, kind, default=default, annotation=empty)) + + # non-keyword-only parameters + args = reversed(f.args.args) + defaults = reversed(f.args.defaults) + iter = itertools.zip_longest(args, defaults, fillvalue=None) + if last_positional_only is not None: + kind = Parameter.POSITIONAL_ONLY + else: + kind = Parameter.POSITIONAL_OR_KEYWORD + for i, (name, default) in enumerate(reversed(list(iter))): + p(name, default) + if i == last_positional_only: + kind = Parameter.POSITIONAL_OR_KEYWORD + + # *args + if f.args.vararg: + kind = Parameter.VAR_POSITIONAL + p(f.args.vararg, empty) + + # keyword-only arguments + kind = Parameter.KEYWORD_ONLY + for name, default in zip(f.args.kwonlyargs, f.args.kw_defaults): + p(name, default) + + # **kwargs + if f.args.kwarg: + kind = Parameter.VAR_KEYWORD + p(f.args.kwarg, empty) + + if self_parameter is not None: + # Possibly strip the bound argument: + # - We *always* strip first bound argument if + # it is a module. + # - We don't strip first bound argument if + # skip_bound_arg is False. + assert parameters + _self = getattr(obj, '__self__', None) + self_isbound = _self is not None + self_ismodule = ismodule(_self) + if self_isbound and (self_ismodule or skip_bound_arg): + parameters.pop(0) + else: + # for builtins, self parameter is always positional-only! + p = parameters[0].replace(kind=Parameter.POSITIONAL_ONLY) + parameters[0] = p + + return cls(parameters, return_annotation=cls.empty) + + +def _signature_from_builtin(cls, func, skip_bound_arg=True): + """Private helper function to get signature for + builtin callables. + """ + + if not _signature_is_builtin(func): + raise TypeError("{!r} is not a Python builtin " + "function".format(func)) + + s = getattr(func, "__text_signature__", None) + if not s: + raise ValueError("no signature found for builtin {!r}".format(func)) + + return _signature_fromstr(cls, func, s, skip_bound_arg) + + +def _signature_from_function(cls, func): + """Private helper: constructs Signature for the given python function.""" + + is_duck_function = False + if not isfunction(func): + if _signature_is_functionlike(func): + is_duck_function = True + else: + # If it's not a pure Python function, and not a duck type + # of pure function: + raise TypeError('{!r} is not a Python function'.format(func)) + + Parameter = cls._parameter_cls + + # Parameter information. + func_code = func.__code__ + pos_count = func_code.co_argcount + arg_names = func_code.co_varnames + positional = tuple(arg_names[:pos_count]) + keyword_only_count = func_code.co_kwonlyargcount + keyword_only = arg_names[pos_count:(pos_count + keyword_only_count)] + annotations = func.__annotations__ + defaults = func.__defaults__ + kwdefaults = func.__kwdefaults__ + + if defaults: + pos_default_count = len(defaults) + else: + pos_default_count = 0 + + parameters = [] + + # Non-keyword-only parameters w/o defaults. + non_default_count = pos_count - pos_default_count + for name in positional[:non_default_count]: + annotation = annotations.get(name, _empty) + parameters.append(Parameter(name, annotation=annotation, + kind=_POSITIONAL_OR_KEYWORD)) + + # ... w/ defaults. + for offset, name in enumerate(positional[non_default_count:]): + annotation = annotations.get(name, _empty) + parameters.append(Parameter(name, annotation=annotation, + kind=_POSITIONAL_OR_KEYWORD, + default=defaults[offset])) + + # *args + if func_code.co_flags & CO_VARARGS: + name = arg_names[pos_count + keyword_only_count] + annotation = annotations.get(name, _empty) + parameters.append(Parameter(name, annotation=annotation, + kind=_VAR_POSITIONAL)) + + # Keyword-only parameters. + for name in keyword_only: + default = _empty + if kwdefaults is not None: + default = kwdefaults.get(name, _empty) + + annotation = annotations.get(name, _empty) + parameters.append(Parameter(name, annotation=annotation, + kind=_KEYWORD_ONLY, + default=default)) + # **kwargs + if func_code.co_flags & CO_VARKEYWORDS: + index = pos_count + keyword_only_count + if func_code.co_flags & CO_VARARGS: + index += 1 + + name = arg_names[index] + annotation = annotations.get(name, _empty) + parameters.append(Parameter(name, annotation=annotation, + kind=_VAR_KEYWORD)) + + # Is 'func' is a pure Python function - don't validate the + # parameters list (for correct order and defaults), it should be OK. + return cls(parameters, + return_annotation=annotations.get('return', _empty), + __validate_parameters__=is_duck_function) + + +def _signature_from_callable(obj, *, + follow_wrapper_chains=True, + skip_bound_arg=True, + sigcls): + + """Private helper function to get signature for arbitrary + callable objects. + """ + + if not callable(obj): + raise TypeError('{!r} is not a callable object'.format(obj)) + + if isinstance(obj, types.MethodType): + print ("Ok") + # In this case we skip the first parameter of the underlying + # function (usually `self` or `cls`). + sig = _signature_from_callable( + obj.__func__, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg, + sigcls=sigcls) + + if skip_bound_arg: + print ("1") + return _signature_bound_method(sig) + else: + print ("2") + return sig + + # Was this function wrapped by a decorator? + if follow_wrapper_chains: + obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__"))) + if isinstance(obj, types.MethodType): + # If the unwrapped object is a *method*, we might want to + # skip its first parameter (self). + # See test_signature_wrapped_bound_method for details. + return _signature_from_callable( + obj, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg, + sigcls=sigcls) + + try: + sig = obj.__signature__ + except AttributeError: + pass + else: + if sig is not None: + if not isinstance(sig, Signature): + raise TypeError( + 'unexpected object {!r} in __signature__ ' + 'attribute'.format(sig)) + return sig + + try: + partialmethod = obj._partialmethod + except AttributeError: + pass + else: + if isinstance(partialmethod, functools.partialmethod): + # Unbound partialmethod (see functools.partialmethod) + # This means, that we need to calculate the signature + # as if it's a regular partial object, but taking into + # account that the first positional argument + # (usually `self`, or `cls`) will not be passed + # automatically (as for boundmethods) + + wrapped_sig = _signature_from_callable( + partialmethod.func, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg, + sigcls=sigcls) + + sig = _signature_get_partial(wrapped_sig, partialmethod, (None,)) + first_wrapped_param = tuple(wrapped_sig.parameters.values())[0] + if first_wrapped_param.kind is Parameter.VAR_POSITIONAL: + # First argument of the wrapped callable is `*args`, as in + # `partialmethod(lambda *args)`. + return sig + else: + sig_params = tuple(sig.parameters.values()) + assert (not sig_params or + first_wrapped_param is not sig_params[0]) + new_params = (first_wrapped_param,) + sig_params + return sig.replace(parameters=new_params) + + if isfunction(obj) or _signature_is_functionlike(obj): + # If it's a pure Python function, or an object that is duck type + # of a Python function (Cython functions, for instance), then: + return _signature_from_function(sigcls, obj) + + if _signature_is_builtin(obj): + return _signature_from_builtin(sigcls, obj, + skip_bound_arg=skip_bound_arg) + + if isinstance(obj, functools.partial): + wrapped_sig = _signature_from_callable( + obj.func, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg, + sigcls=sigcls) + return _signature_get_partial(wrapped_sig, obj) + + sig = None + if isinstance(obj, type): + # obj is a class or a metaclass + + # First, let's see if it has an overloaded __call__ defined + # in its metaclass + call = _signature_get_user_defined_method(type(obj), '__call__') + if call is not None: + sig = _signature_from_callable( + call, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg, + sigcls=sigcls) + else: + # Now we check if the 'obj' class has a '__new__' method + new = _signature_get_user_defined_method(obj, '__new__') + if new is not None: + sig = _signature_from_callable( + new, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg, + sigcls=sigcls) + else: + # Finally, we should have at least __init__ implemented + init = _signature_get_user_defined_method(obj, '__init__') + if init is not None: + sig = _signature_from_callable( + init, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg, + sigcls=sigcls) + + if sig is None: + # At this point we know, that `obj` is a class, with no user- + # defined '__init__', '__new__', or class-level '__call__' + + for base in obj.__mro__[:-1]: + # Since '__text_signature__' is implemented as a + # descriptor that extracts text signature from the + # class docstring, if 'obj' is derived from a builtin + # class, its own '__text_signature__' may be 'None'. + # Therefore, we go through the MRO (except the last + # class in there, which is 'object') to find the first + # class with non-empty text signature. + try: + text_sig = base.__text_signature__ + except AttributeError: + pass + else: + if text_sig: + # If 'obj' class has a __text_signature__ attribute: + # return a signature based on it + return _signature_fromstr(sigcls, obj, text_sig) + + # No '__text_signature__' was found for the 'obj' class. + # Last option is to check if its '__init__' is + # object.__init__ or type.__init__. + if type not in obj.__mro__: + # We have a class (not metaclass), but no user-defined + # __init__ or __new__ for it + if (obj.__init__ is object.__init__ and + obj.__new__ is object.__new__): + # Return a signature of 'object' builtin. + return signature(object) + else: + raise ValueError( + 'no signature found for builtin type {!r}'.format(obj)) + + elif not isinstance(obj, _NonUserDefinedCallables): + # An object with __call__ + # We also check that the 'obj' is not an instance of + # _WrapperDescriptor or _MethodWrapper to avoid + # infinite recursion (and even potential segfault) + call = _signature_get_user_defined_method(type(obj), '__call__') + if call is not None: + try: + sig = _signature_from_callable( + call, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg, + sigcls=sigcls) + except ValueError as ex: + msg = 'no signature found for {!r}'.format(obj) + raise ValueError(msg) from ex + + if sig is not None: + # For classes and objects we skip the first parameter of their + # __call__, __new__, or __init__ methods + if skip_bound_arg: + return _signature_bound_method(sig) + else: + return sig + + if isinstance(obj, types.BuiltinFunctionType): + # Raise a nicer error message for builtins + msg = 'no signature found for builtin function {!r}'.format(obj) + raise ValueError(msg) + + #print (type(obj)) + #raise ValueError('callable {!r} is not supported by signature'.format(obj)) + + +class _void: + """A private marker - used in Parameter & Signature.""" + + +class _empty: + """Marker object for Signature.empty and Parameter.empty.""" + + +class _ParameterKind(enum.IntEnum): + POSITIONAL_ONLY = 0 + POSITIONAL_OR_KEYWORD = 1 + VAR_POSITIONAL = 2 + KEYWORD_ONLY = 3 + VAR_KEYWORD = 4 + + def __str__(self): + return self._name_ + + +_POSITIONAL_ONLY = _ParameterKind.POSITIONAL_ONLY +_POSITIONAL_OR_KEYWORD = _ParameterKind.POSITIONAL_OR_KEYWORD +_VAR_POSITIONAL = _ParameterKind.VAR_POSITIONAL +_KEYWORD_ONLY = _ParameterKind.KEYWORD_ONLY +_VAR_KEYWORD = _ParameterKind.VAR_KEYWORD +_PARAM_NAME_MAPPING = { + _POSITIONAL_ONLY: 'positional-only', + _POSITIONAL_OR_KEYWORD: 'positional or keyword', + _VAR_POSITIONAL: 'variadic positional', + _KEYWORD_ONLY: 'keyword-only', + _VAR_KEYWORD: 'variadic keyword'} + +_get_paramkind_descr = _PARAM_NAME_MAPPING.__getitem__ + + +class Parameter: + """Represents a parameter in a function signature. + + Has the following public attributes: + + * name : str + The name of the parameter as a string. + * default : object + The default value for the parameter if specified. If the + parameter has no default value, this attribute is set to + `Parameter.empty`. + * annotation + The annotation for the parameter if specified. If the + parameter has no annotation, this attribute is set to + `Parameter.empty`. + * kind : str + Describes how argument values are bound to the parameter. + Possible values: `Parameter.POSITIONAL_ONLY`, + `Parameter.POSITIONAL_OR_KEYWORD`, `Parameter.VAR_POSITIONAL`, + `Parameter.KEYWORD_ONLY`, `Parameter.VAR_KEYWORD`. + """ + + __slots__ = ('_name', '_kind', '_default', '_annotation') + + POSITIONAL_ONLY = _POSITIONAL_ONLY + POSITIONAL_OR_KEYWORD = _POSITIONAL_OR_KEYWORD + VAR_POSITIONAL = _VAR_POSITIONAL + KEYWORD_ONLY = _KEYWORD_ONLY + VAR_KEYWORD = _VAR_KEYWORD + + empty = _empty + + def __init__(self, name, kind, *, default=_empty, annotation=_empty): + try: + self._kind = _ParameterKind(kind) + except ValueError: + raise ValueError(f'value {kind!r} is not a valid Parameter.kind') + if default is not _empty: + if self._kind in (_VAR_POSITIONAL, _VAR_KEYWORD): + msg = '{} parameters cannot have default values' + msg = msg.format(_get_paramkind_descr(self._kind)) + raise ValueError(msg) + self._default = default + self._annotation = annotation + + if name is _empty: + raise ValueError('name is a required attribute for Parameter') + + if not isinstance(name, str): + msg = 'name must be a str, not a {}'.format(type(name).__name__) + raise TypeError(msg) + + if name[0] == '.' and name[1:].isdigit(): + # These are implicit arguments generated by comprehensions. In + # order to provide a friendlier interface to users, we recast + # their name as "implicitN" and treat them as positional-only. + # See issue 19611. + if self._kind != _POSITIONAL_OR_KEYWORD: + msg = ( + 'implicit arguments must be passed as ' + 'positional or keyword arguments, not {}' + ) + msg = msg.format(_get_paramkind_descr(self._kind)) + raise ValueError(msg) + self._kind = _POSITIONAL_ONLY + name = 'implicit{}'.format(name[1:]) + + if not name.isidentifier(): + raise ValueError('{!r} is not a valid parameter name'.format(name)) + + self._name = name + + def __reduce__(self): + return (type(self), + (self._name, self._kind), + {'_default': self._default, + '_annotation': self._annotation}) + + def __setstate__(self, state): + self._default = state['_default'] + self._annotation = state['_annotation'] + + @property + def name(self): + return self._name + + @property + def default(self): + return self._default + + @property + def annotation(self): + return self._annotation + + @property + def kind(self): + return self._kind + + def replace(self, *, name=_void, kind=_void, + annotation=_void, default=_void): + """Creates a customized copy of the Parameter.""" + + if name is _void: + name = self._name + + if kind is _void: + kind = self._kind + + if annotation is _void: + annotation = self._annotation + + if default is _void: + default = self._default + + return type(self)(name, kind, default=default, annotation=annotation) + + def __str__(self): + kind = self.kind + formatted = self._name + + # Add annotation and default value + if self._annotation is not _empty: + formatted = '{}:{}'.format(formatted, + formatannotation(self._annotation)) + + if self._default is not _empty: + formatted = '{}={}'.format(formatted, repr(self._default)) + + if kind == _VAR_POSITIONAL: + formatted = '*' + formatted + elif kind == _VAR_KEYWORD: + formatted = '**' + formatted + + return formatted + + def __repr__(self): + return '<{} "{}">'.format(self.__class__.__name__, self) + + def __hash__(self): + return hash((self.name, self.kind, self.annotation, self.default)) + + def __eq__(self, other): + if self is other: + return True + if not isinstance(other, Parameter): + return NotImplemented + return (self._name == other._name and + self._kind == other._kind and + self._default == other._default and + self._annotation == other._annotation) + + +class BoundArguments: + """Result of `Signature.bind` call. Holds the mapping of arguments + to the function's parameters. + + Has the following public attributes: + + * arguments : OrderedDict + An ordered mutable mapping of parameters' names to arguments' values. + Does not contain arguments' default values. + * signature : Signature + The Signature object that created this instance. + * args : tuple + Tuple of positional arguments values. + * kwargs : dict + Dict of keyword arguments values. + """ + + __slots__ = ('arguments', '_signature', '__weakref__') + + def __init__(self, signature, arguments): + self.arguments = arguments + self._signature = signature + + @property + def signature(self): + return self._signature + + @property + def args(self): + args = [] + for param_name, param in self._signature.parameters.items(): + if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): + break + + try: + arg = self.arguments[param_name] + except KeyError: + # We're done here. Other arguments + # will be mapped in 'BoundArguments.kwargs' + break + else: + if param.kind == _VAR_POSITIONAL: + # *args + args.extend(arg) + else: + # plain argument + args.append(arg) + + return tuple(args) + + @property + def kwargs(self): + kwargs = {} + kwargs_started = False + for param_name, param in self._signature.parameters.items(): + if not kwargs_started: + if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): + kwargs_started = True + else: + if param_name not in self.arguments: + kwargs_started = True + continue + + if not kwargs_started: + continue + + try: + arg = self.arguments[param_name] + except KeyError: + pass + else: + if param.kind == _VAR_KEYWORD: + # **kwargs + kwargs.update(arg) + else: + # plain keyword argument + kwargs[param_name] = arg + + return kwargs + + def apply_defaults(self): + """Set default values for missing arguments. + + For variable-positional arguments (*args) the default is an + empty tuple. + + For variable-keyword arguments (**kwargs) the default is an + empty dict. + """ + arguments = self.arguments + new_arguments = [] + for name, param in self._signature.parameters.items(): + try: + new_arguments.append((name, arguments[name])) + except KeyError: + if param.default is not _empty: + val = param.default + elif param.kind is _VAR_POSITIONAL: + val = () + elif param.kind is _VAR_KEYWORD: + val = {} + else: + # This BoundArguments was likely produced by + # Signature.bind_partial(). + continue + new_arguments.append((name, val)) + self.arguments = OrderedDict(new_arguments) + + def __eq__(self, other): + if self is other: + return True + if not isinstance(other, BoundArguments): + return NotImplemented + return (self.signature == other.signature and + self.arguments == other.arguments) + + def __setstate__(self, state): + self._signature = state['_signature'] + self.arguments = state['arguments'] + + def __getstate__(self): + return {'_signature': self._signature, 'arguments': self.arguments} + + def __repr__(self): + args = [] + for arg, value in self.arguments.items(): + args.append('{}={!r}'.format(arg, value)) + return '<{} ({})>'.format(self.__class__.__name__, ', '.join(args)) + + +class Signature: + """A Signature object represents the overall signature of a function. + It stores a Parameter object for each parameter accepted by the + function, as well as information specific to the function itself. + + A Signature object has the following public attributes and methods: + + * parameters : OrderedDict + An ordered mapping of parameters' names to the corresponding + Parameter objects (keyword-only arguments are in the same order + as listed in `code.co_varnames`). + * return_annotation : object + The annotation for the return type of the function if specified. + If the function has no annotation for its return type, this + attribute is set to `Signature.empty`. + * bind(*args, **kwargs) -> BoundArguments + Creates a mapping from positional and keyword arguments to + parameters. + * bind_partial(*args, **kwargs) -> BoundArguments + Creates a partial mapping from positional and keyword arguments + to parameters (simulating 'functools.partial' behavior.) + """ + + __slots__ = ('_return_annotation', '_parameters') + + _parameter_cls = Parameter + _bound_arguments_cls = BoundArguments + + empty = _empty + + def __init__(self, parameters=None, *, return_annotation=_empty, + __validate_parameters__=True): + """Constructs Signature from the given list of Parameter + objects and 'return_annotation'. All arguments are optional. + """ + + if parameters is None: + params = OrderedDict() + else: + if __validate_parameters__: + params = OrderedDict() + top_kind = _POSITIONAL_ONLY + kind_defaults = False + + for idx, param in enumerate(parameters): + kind = param.kind + name = param.name + + if kind < top_kind: + msg = ( + 'wrong parameter order: {} parameter before {} ' + 'parameter' + ) + msg = msg.format(_get_paramkind_descr(top_kind), + _get_paramkind_descr(kind)) + raise ValueError(msg) + elif kind > top_kind: + kind_defaults = False + top_kind = kind + + if kind in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD): + if param.default is _empty: + if kind_defaults: + # No default for this parameter, but the + # previous parameter of the same kind had + # a default + msg = 'non-default argument follows default ' \ + 'argument' + raise ValueError(msg) + else: + # There is a default for this parameter. + kind_defaults = True + + if name in params: + msg = 'duplicate parameter name: {!r}'.format(name) + raise ValueError(msg) + + params[name] = param + else: + params = OrderedDict(((param.name, param) + for param in parameters)) + + self._parameters = types.MappingProxyType(params) + self._return_annotation = return_annotation + + @classmethod + def from_function(cls, func): + """Constructs Signature for the given python function. + + Deprecated since Python 3.5, use `Signature.from_callable()`. + """ + + warnings.warn("inspect.Signature.from_function() is deprecated since " + "Python 3.5, use Signature.from_callable()", + DeprecationWarning, stacklevel=2) + return _signature_from_function(cls, func) + + @classmethod + def from_builtin(cls, func): + """Constructs Signature for the given builtin function. + + Deprecated since Python 3.5, use `Signature.from_callable()`. + """ + + warnings.warn("inspect.Signature.from_builtin() is deprecated since " + "Python 3.5, use Signature.from_callable()", + DeprecationWarning, stacklevel=2) + return _signature_from_builtin(cls, func) + + @classmethod + def from_callable(cls, obj, *, follow_wrapped=True): + """Constructs Signature for the given callable object.""" + return _signature_from_callable(obj, sigcls=cls, + follow_wrapper_chains=follow_wrapped) + + @property + def parameters(self): + return self._parameters + + @property + def return_annotation(self): + return self._return_annotation + + def replace(self, *, parameters=_void, return_annotation=_void): + """Creates a customized copy of the Signature. + Pass 'parameters' and/or 'return_annotation' arguments + to override them in the new copy. + """ + + if parameters is _void: + parameters = self.parameters.values() + + if return_annotation is _void: + return_annotation = self._return_annotation + + return type(self)(parameters, + return_annotation=return_annotation) + + def _hash_basis(self): + params = tuple(param for param in self.parameters.values() + if param.kind != _KEYWORD_ONLY) + + kwo_params = {param.name: param for param in self.parameters.values() + if param.kind == _KEYWORD_ONLY} + + return params, kwo_params, self.return_annotation + + def __hash__(self): + params, kwo_params, return_annotation = self._hash_basis() + kwo_params = frozenset(kwo_params.values()) + return hash((params, kwo_params, return_annotation)) + + def __eq__(self, other): + if self is other: + return True + if not isinstance(other, Signature): + return NotImplemented + return self._hash_basis() == other._hash_basis() + + def _bind(self, args, kwargs, *, partial=False): + """Private method. Don't use directly.""" + + arguments = OrderedDict() + + parameters = iter(self.parameters.values()) + parameters_ex = () + arg_vals = iter(args) + + while True: + # Let's iterate through the positional arguments and corresponding + # parameters + try: + arg_val = next(arg_vals) + except StopIteration: + # No more positional arguments + try: + param = next(parameters) + except StopIteration: + # No more parameters. That's it. Just need to check that + # we have no `kwargs` after this while loop + break + else: + if param.kind == _VAR_POSITIONAL: + # That's OK, just empty *args. Let's start parsing + # kwargs + break + elif param.name in kwargs: + if param.kind == _POSITIONAL_ONLY: + msg = '{arg!r} parameter is positional only, ' \ + 'but was passed as a keyword' + msg = msg.format(arg=param.name) + raise TypeError(msg) from None + parameters_ex = (param,) + break + elif (param.kind == _VAR_KEYWORD or + param.default is not _empty): + # That's fine too - we have a default value for this + # parameter. So, lets start parsing `kwargs`, starting + # with the current parameter + parameters_ex = (param,) + break + else: + # No default, not VAR_KEYWORD, not VAR_POSITIONAL, + # not in `kwargs` + if partial: + parameters_ex = (param,) + break + else: + msg = 'missing a required argument: {arg!r}' + msg = msg.format(arg=param.name) + raise TypeError(msg) from None + else: + # We have a positional argument to process + try: + param = next(parameters) + except StopIteration: + raise TypeError('too many positional arguments') from None + else: + if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): + # Looks like we have no parameter for this positional + # argument + raise TypeError( + 'too many positional arguments') from None + + if param.kind == _VAR_POSITIONAL: + # We have an '*args'-like argument, let's fill it with + # all positional arguments we have left and move on to + # the next phase + values = [arg_val] + values.extend(arg_vals) + arguments[param.name] = tuple(values) + break + + if param.name in kwargs: + raise TypeError( + 'multiple values for argument {arg!r}'.format( + arg=param.name)) from None + + arguments[param.name] = arg_val + + # Now, we iterate through the remaining parameters to process + # keyword arguments + kwargs_param = None + for param in itertools.chain(parameters_ex, parameters): + if param.kind == _VAR_KEYWORD: + # Memorize that we have a '**kwargs'-like parameter + kwargs_param = param + continue + + if param.kind == _VAR_POSITIONAL: + # Named arguments don't refer to '*args'-like parameters. + # We only arrive here if the positional arguments ended + # before reaching the last parameter before *args. + continue + + param_name = param.name + try: + arg_val = kwargs.pop(param_name) + except KeyError: + # We have no value for this parameter. It's fine though, + # if it has a default value, or it is an '*args'-like + # parameter, left alone by the processing of positional + # arguments. + if (not partial and param.kind != _VAR_POSITIONAL and + param.default is _empty): + raise TypeError('missing a required argument: {arg!r}'. \ + format(arg=param_name)) from None + + else: + if param.kind == _POSITIONAL_ONLY: + # This should never happen in case of a properly built + # Signature object (but let's have this check here + # to ensure correct behaviour just in case) + raise TypeError('{arg!r} parameter is positional only, ' + 'but was passed as a keyword'. \ + format(arg=param.name)) + + arguments[param_name] = arg_val + + if kwargs: + if kwargs_param is not None: + # Process our '**kwargs'-like parameter + arguments[kwargs_param.name] = kwargs + else: + raise TypeError( + 'got an unexpected keyword argument {arg!r}'.format( + arg=next(iter(kwargs)))) + + return self._bound_arguments_cls(self, arguments) + + def bind(*args, **kwargs): + """Get a BoundArguments object, that maps the passed `args` + and `kwargs` to the function's signature. Raises `TypeError` + if the passed arguments can not be bound. + """ + return args[0]._bind(args[1:], kwargs) + + def bind_partial(*args, **kwargs): + """Get a BoundArguments object, that partially maps the + passed `args` and `kwargs` to the function's signature. + Raises `TypeError` if the passed arguments can not be bound. + """ + return args[0]._bind(args[1:], kwargs, partial=True) + + def __reduce__(self): + return (type(self), + (tuple(self._parameters.values()),), + {'_return_annotation': self._return_annotation}) + + def __setstate__(self, state): + self._return_annotation = state['_return_annotation'] + + def __repr__(self): + return '<{} {}>'.format(self.__class__.__name__, self) + + def __str__(self): + result = [] + render_pos_only_separator = False + render_kw_only_separator = True + for param in self.parameters.values(): + formatted = str(param) + + kind = param.kind + + if kind == _POSITIONAL_ONLY: + render_pos_only_separator = True + elif render_pos_only_separator: + # It's not a positional-only parameter, and the flag + # is set to 'True' (there were pos-only params before.) + result.append('/') + render_pos_only_separator = False + + if kind == _VAR_POSITIONAL: + # OK, we have an '*args'-like parameter, so we won't need + # a '*' to separate keyword-only arguments + render_kw_only_separator = False + elif kind == _KEYWORD_ONLY and render_kw_only_separator: + # We have a keyword-only parameter to render and we haven't + # rendered an '*args'-like parameter before, so add a '*' + # separator to the parameters list ("foo(arg1, *, arg2)" case) + result.append('*') + # This condition should be only triggered once, so + # reset the flag + render_kw_only_separator = False + + result.append(formatted) + + if render_pos_only_separator: + # There were only positional-only parameters, hence the + # flag was not reset to 'False' + result.append('/') + + rendered = '({})'.format(', '.join(result)) + + if self.return_annotation is not _empty: + anno = formatannotation(self.return_annotation) + rendered += ' -> {}'.format(anno) + + return rendered + + +def signature(obj, *, follow_wrapped=True): + """Get a signature object for the passed callable.""" + return Signature.from_callable(obj, follow_wrapped=follow_wrapped) + + +def _main(): + """ Logic for inspecting an object given at command line """ + import argparse + import importlib + + parser = argparse.ArgumentParser() + parser.add_argument( + 'object', + help="The object to be analysed. " + "It supports the 'module:qualname' syntax") + parser.add_argument( + '-d', '--details', action='store_true', + help='Display info about the module rather than its source code') + + args = parser.parse_args() + + target = args.object + mod_name, has_attrs, attrs = target.partition(":") + try: + obj = module = importlib.import_module(mod_name) + except Exception as exc: + msg = "Failed to import {} ({}: {})".format(mod_name, + type(exc).__name__, + exc) + print(msg, file=sys.stderr) + exit(2) + + if has_attrs: + parts = attrs.split(".") + obj = module + for part in parts: + obj = getattr(obj, part) + + if module.__name__ in sys.builtin_module_names: + print("Can't get info for builtin modules.", file=sys.stderr) + exit(1) + + if args.details: + print('Target: {}'.format(target)) + print('Origin: {}'.format(getsourcefile(module))) + print('Cached: {}'.format(module.__cached__)) + if obj is module: + print('Loader: {}'.format(repr(module.__loader__))) + if hasattr(module, '__path__'): + print('Submodule search path: {}'.format(module.__path__)) + else: + try: + __, lineno = findsource(obj) + except Exception: + pass + else: + print('Line: {}'.format(lineno)) + + print('\n') + else: + print(getsource(obj)) + + +print (signature(m1.write)) \ No newline at end of file diff --git a/script/test/t.py b/script/test/t.py new file mode 100644 index 0000000..dd3f5bd --- /dev/null +++ b/script/test/t.py @@ -0,0 +1,7 @@ + +i=1 +j=time.sleep(1.0) +r1 = lscan(inp, (sin,out,), 0, 40, 100, 0.05, print_scan=True) +r1 = lscan(inp, (sin,out,), 0, 40, 100, 0.01) + +j=time.sleep(1.0) \ No newline at end of file diff --git a/script/test/test1.py b/script/test/test1.py index 2b296e0..968f7b3 100755 --- a/script/test/test1.py +++ b/script/test/test1.py @@ -14,11 +14,12 @@ Line Scan #set_exec_pars(name="out", open=False) -print get_exec_pars().path +print (get_exec_pars().path) + def before_pass(pass_num): - print "Starting pass: " , pass_num + print ("Starting pass: " , pass_num) def after_pass(pass_num): - print "Finished pass: " , pass_num + print ("Finished pass: " , pass_num) #set_exec_pars(layout="sf") diff --git a/script/test/test14.xml b/script/test/test14.xml index db1f4ec..fd6be6c 100755 --- a/script/test/test14.xml +++ b/script/test/test14.xml @@ -1,20 +1,22 @@ - alexandre.gobbo@psi.ch + alexandre.gobbo@psi.ch My first test - - + + 0.0 20.0 1.0 - + + + diff --git a/script/test/test2.xml b/script/test/test2.xml index 04e6b94..04aa43c 100755 --- a/script/test/test2.xml +++ b/script/test/test2.xml @@ -9,7 +9,7 @@ - 0.0 + 10.0 31.0 1.0 @@ -23,8 +23,8 @@ def process(): - 0.0 - 5.0 + 5.0 + 10.0 1.0 diff --git a/script/test/test29.py b/script/test/test29.py index 8045532..e119800 100755 --- a/script/test/test29.py +++ b/script/test/test29.py @@ -1,7 +1,7 @@ [py, px, pxy]=plot([None,None,None],["y","x", "xy"]) - +# #XY error plot pxy.setStyle(pxy.Style.ErrorXY) diff --git a/script/test/test2v.xml b/script/test/test2v.xml new file mode 100644 index 0000000..df9dc95 --- /dev/null +++ b/script/test/test2v.xml @@ -0,0 +1,46 @@ + + + + alexandre.gobbo@psi.ch + + + My second test + + + + + + + + + + + 0.0 + 0.0 + 1.0 + START_X + END_X + STEP_X + + + + + + + + + + 0.0 + 10.0 + 0.0 + START_Y + END_Y + STEP_Y + + + + + + diff --git a/script/test/test6v.xml b/script/test/test6v.xml new file mode 100644 index 0000000..d16a1ef --- /dev/null +++ b/script/test/test6v.xml @@ -0,0 +1,25 @@ + + + + + + + 100 + + + + + 100 + + + + + + + + + + + + diff --git a/script/test/test7.xml b/script/test/test7.xml index 0083083..94eba01 100755 --- a/script/test/test7.xml +++ b/script/test/test7.xml @@ -25,11 +25,6 @@ def process(x): - - - - - + diff --git a/script/test/test9.xml b/script/test/test8v.xml old mode 100755 new mode 100644 similarity index 72% rename from script/test/test9.xml rename to script/test/test8v.xml index cf97860..40c408b --- a/script/test/test9.xml +++ b/script/test/test8v.xml @@ -3,15 +3,21 @@ alexandre.gobbo@psi.ch - - My third test + + My first test + + + 0.0 31.0 1.0 + START + END + STEP + + + + 10.0 + 20.0 + 1.0 + + + + + + + + + + diff --git a/script/test/test_loop_caget.py b/script/test/test_loop_caget.py new file mode 100644 index 0000000..300822f --- /dev/null +++ b/script/test/test_loop_caget.py @@ -0,0 +1,11 @@ +add_device(ChannelDouble("c0", "TESTIOC:TESTSINUS:SinCalc"), True) +c0.monitored=True +show_panel(c0) + +for i in range(1000000): + c=ChannelDouble("channel", "TESTIOC:TESTSINUS:SinCalc") + c.initialize() + print i, c.read() + c.close() + time.sleep(0.001) + \ No newline at end of file diff --git a/script/test/test_manip.xml b/script/test/test_manip.xml new file mode 100644 index 0000000..ae35869 --- /dev/null +++ b/script/test/test_manip.xml @@ -0,0 +1,24 @@ + + + + + + + 5 + + + + + + + + + + + + + + + diff --git a/script/test/test_receive_sender.py b/script/test/test_receive_sender.py new file mode 100644 index 0000000..93548a7 --- /dev/null +++ b/script/test/test_receive_sender.py @@ -0,0 +1,19 @@ + +url="tcp://localhost:9999" + +st1 = Stream("st1", url, SocketType.PULL) +#st1.parent.config.headerReservingAllocator = True + +st1.initialize() +st1.start() +st1.waitCacheChange(60000) + + +#show_panel(st1) + + +try: + bscan (st1, 5, 5, save=False) +finally: + st1.close() + #p.close() \ No newline at end of file diff --git a/script/test/test_roi.py b/script/test/test_roi.py new file mode 100644 index 0000000..385f2b6 --- /dev/null +++ b/script/test/test_roi.py @@ -0,0 +1,20 @@ +r=show_panel(ca) +r.addDataSelection(Overlays.Rect(None, Point(70,50), Dimension(20,40))) + + + +ov = r.getDataSelection() +size =20 +ov.width = 40 +ov.height = 80 +r.refresh() + +ov.setPosition(Point(100,79)) +r.refresh() + +print ov.position.x,ov.position.x,ov.size.width, ov.size.height + + +r.addDataSelection(Overlays.Line(None, Point(20,50), Point(40,90))) +r.addDataSelection(Overlays.Crosshairs(None, Point(20,50), Dimension(-1,1))) +r.addDataSelection(Overlays.Crosshairs(None, Point(20,50), Dimension(1,-1))) \ No newline at end of file diff --git a/script/test/test_sender.py b/script/test/test_sender.py new file mode 100644 index 0000000..dd674e8 --- /dev/null +++ b/script/test/test_sender.py @@ -0,0 +1,77 @@ +from ch.psi.bsread import ScheduledSender +from ch.psi.bsread import SenderConfig +from ch.psi.bsread import DataChannel +from ch.psi.bsread.impl import StandardPulseIdProvider +from ch.psi.bsread.impl import StandardTimeProvider +from ch.psi.bsread.message import Timestamp +from ch.psi.bsread.message import ChannelConfig +from ch.psi.bsread.converter import MatlabByteConverter +from java.util.concurrent import TimeUnit +from ch.psi.bsread.message import Type as ChanlelType +from ch.psi.bsread.compression import Compression + +try: + sender.close() +except: + pass +try: + receiver.close() +except: + pass + +#address "tcp://*:9999" +#try: +pid_provider = StandardPulseIdProvider() +time_provider = StandardTimeProvider(); +converter = MatlabByteConverter() +sender = ScheduledSender(SenderConfig(SenderConfig.DEFAULT_ADDRESS,pid_provider,time_provider,converter)) + +class ScalarChannel(DataChannel): + def getValue(self, pulseId): + #print pulseId + return float(pulseId); + def getTime(self, pulseId): + return Timestamp(pulseId, 0L) +scalar_channel_config = ChannelConfig("Scalar", ChanlelType.Float64, 10, 0) +scalar_channel = ScalarChannel(scalar_channel_config) +sender.addSource(scalar_channel) + + +#Compression: bitshuffle_lz4 , none or lz4 +compression = Compression.none + +SIZE_ARRAY = 1200000 #54268 +#SIZE_ARRAY = 120 + + +class ArrayChannel(DataChannel): + def getValue(self, pulseId): + return Arr.indexesDouble(SIZE_ARRAY) + def getTime(self, pulseId): + return Timestamp(pulseId, 0L) + +array_channel_config = ChannelConfig("Array", ChanlelType.Float64, [SIZE_ARRAY/1000, 1000], 10, 0, ChannelConfig.DEFAULT_ENCODING, compression) +array_channel = ArrayChannel(array_channel_config) +sender.addSource(array_channel) + + +sender.connect(); +initialDelay = 20 +period = 20 +sender.sendAtFixedRate(initialDelay, period, TimeUnit.MILLISECONDS) +back=sender + +#run ("test/test_receive_sender") + + +receiver = Stream("st1", "tcp://localhost:9999", SocketType.PULL) +#st1.parent.config.headerReservingAllocator = True +receiver.initialize() +receiver.start() +show_panel(receiver) + + +#finally: +# #receiver.close(); +# sender.close(); +# pass \ No newline at end of file diff --git a/script/test/testbug.xml b/script/test/testbug.xml new file mode 100644 index 0000000..40b9f29 --- /dev/null +++ b/script/test/testbug.xml @@ -0,0 +1,250 @@ + + + + + + + + + + + + + -8.0 + 0.0 + 0.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/script/test/testempty.xml b/script/test/testempty.xml new file mode 100644 index 0000000..5dbb75c --- /dev/null +++ b/script/test/testempty.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/script/test/testsettling.py b/script/test/testsettling.py new file mode 100644 index 0000000..c5e4b30 --- /dev/null +++ b/script/test/testsettling.py @@ -0,0 +1,9 @@ +cc =ChannelSettlingCondition("TESTIOC:TESTCALCOUT:Input", 0) + +positioner = ControlledVariable("positioner", "TESTIOC:TESTCALCOUT:Output", "TESTIOC:TESTSINUS:SinCalc") +positioner.getConfig().resolution = float('inf') +positioner.initialize() + +positioner.setSettlingCondition(ChannelSettlingCondition("TESTIOC:TESTCALCOUT:Input", 0)) +positioner.write(2.0) +positioner.read() \ No newline at end of file diff --git a/script/test/testx.xml b/script/test/testx.xml index 09d6938..3e49478 100755 --- a/script/test/testx.xml +++ b/script/test/testx.xml @@ -5,8 +5,12 @@ My first test - + + + + + 0.0 @@ -18,6 +22,9 @@ def process(): time.sleep(0.1) + + + diff --git a/script/test/test1.xml b/script/test/testy.xml old mode 100755 new mode 100644 similarity index 56% rename from script/test/test1.xml rename to script/test/testy.xml index 9dcb773..1c18587 --- a/script/test/test1.xml +++ b/script/test/testy.xml @@ -3,10 +3,22 @@ alexandre.gobbo@psi.ch - - My first test a + + My first test + + + + + + + + + + 0.0 @@ -15,12 +27,17 @@ +time.sleep(0.1) +print 2 + + + + diff --git a/script/test/x.xml b/script/test/x.xml new file mode 100644 index 0000000..7358f1e --- /dev/null +++ b/script/test/x.xml @@ -0,0 +1,23 @@ + + + + + + + + 0.0 + 0.0 + 0.0 + 0.0 + + + + + 0.0 + 0.0 + 0.0 + + + + + diff --git a/script/test/xxx.xml b/script/test/xxx.xml index ee504d4..cec85dd 100755 --- a/script/test/xxx.xml +++ b/script/test/xxx.xml @@ -1,4 +1,16 @@ - + + + + + 1000 + + + + + + + + diff --git a/script/test/y.xml b/script/test/y.xml new file mode 100644 index 0000000..9e5ebb4 --- /dev/null +++ b/script/test/y.xml @@ -0,0 +1,23 @@ + + + + + + + + 0.0 + 0.0 + 0.0 + 0.0 + + + + + 0.0 + 0.0 + 0.0 + + + + + diff --git a/script/test2.xml b/script/test2.xml index 68ba8f6..bf3f86f 100644 --- a/script/test2.xml +++ b/script/test2.xml @@ -1,5 +1,17 @@ - - - + + + + + + + 100 + + + + + + + + diff --git a/script/ttt.xml b/script/ttt.xml index ee504d4..f628750 100755 --- a/script/ttt.xml +++ b/script/ttt.xml @@ -1,4 +1,20 @@ - - + + + + + + + 10 + + + + + + + + + + diff --git a/script/www.xml b/script/www.xml index ee504d4..c7197bd 100755 --- a/script/www.xml +++ b/script/www.xml @@ -1,4 +1,5 @@ +