diff --git a/config/config.properties b/config/config.properties index 1d63a2d..646fbef 100755 --- a/config/config.properties +++ b/config/config.properties @@ -1,5 +1,6 @@ -#Thu Aug 02 10:45:31 CEST 2018 +#Tue Nov 06 14:31:07 CET 2018 autoSaveScanData=true +commandExecutionEvents=false createSessionFiles=true dataLayout=default dataPath={data}/{year}_{month}/{date}/{date}_{time}_{name} @@ -9,6 +10,7 @@ dataScanPreserveTypes=false dataScanReleaseRecords=false dataServerPort=5573 depthDimension=0 +generateCommandExecutionEvents=true hostName= instanceName=Dev logDaysToLive=50 @@ -17,7 +19,7 @@ logLevelConsole=Off logPath={logs}/{date}_{time} notificationLevel=Off scanStreamerPort=5563 -serverEnabled=true +serverEnabled=false serverPort=8080 simulation=false terminalEnabled=false diff --git a/config/devices.properties b/config/devices.properties index b26e732..990f240 100755 --- a/config/devices.properties +++ b/config/devices.properties @@ -1,7 +1,9 @@ dispatcher=ch.psi.pshell.bs.Provider|tcp://localhost:9999||| cam_server_local=ch.psi.pshell.bs.PipelineServer|localhost:8889|||true cam_server=ch.psi.pshell.bs.PipelineServer|sf-daqsync-01:8889|||true +#ts1=ch.psi.pshell.epics.GenericArray|TESTIOC:TESTWF2:MyWF||| #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||| #scalar=ch.psi.pshell.bs.Scalar|stream Int8Scalar||| #cam=ch.psi.pshell.bs.StreamCamera|"tcp://gfa-lc6-64:10100" 1|||true @@ -9,7 +11,8 @@ cam_server=ch.psi.pshell.bs.PipelineServer|sf-daqsync-01:8889|||true #rr=RotationReadback|TESTIOC:TESTCALCOUT:Output|||true #rp=ch.psi.pshell.epics.Positioner|TESTIOC:TESTCALCOUT:Input null rr||| #webcam=ch.psi.pshell.webcam.Webcam|:2|||true -#det=ch.psi.pshell.epics.AreaDetector|13SIM1|||false +$det=ch.psi.pshell.epics.AreaDetector|13SIM1|||true +deting=ch.psi.pshell.imaging.CameraSource|det||-500| #PiezoRoll1=ch.psi.pshell.epics.ControlledVariable|"TESTIOC:TESTCALCOUT:Input" TESTIOC:TESTCALCOUT:Output false|||true #$ser=ch.psi.pshell.serial.TcpDevice|||| #$beam_ok=ch.psi.pshell.epics.ChannelString|CHANNEL||| @@ -57,6 +60,11 @@ sin=ch.psi.pshell.epics.ChannelDouble|TESTIOC:TESTSINUS:SinCalc 3 true|||true #average=ch.psi.pshell.device.Averager|sin||2000| #isin=ch.psi.pshell.epics.ChannelInteger|TESTIOC:TESTSINUS:SinCalc|||true arr=ch.psi.pshell.epics.ChannelDoubleArray|TESTIOC:TESTWF2:MyWF 6 -1 false|||true +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||| 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 diff --git a/config/jcae.properties b/config/jcae.properties index d43dd02..02ecf33 100755 --- a/config/jcae.properties +++ b/config/jcae.properties @@ -1,7 +1,7 @@ -#Fri Aug 24 11:15:23 CEST 2018 +#Fri Nov 16 23:08:57 CET 2018 ch.psi.jcae.ContextFactory.addressList=127.0.0.1\:54321 ch.psi.jcae.ContextFactory.maxArrayBytes=10000000 -ch.psi.jcae.ChannelFactory.timeout=100 +ch.psi.jcae.ChannelFactory.timeout=200 ch.psi.jcae.ChannelFactory.retries=1 ch.psi.jcae.ContextFactory.serverPort= ch.psi.jcae.impl.DefaultChannelService.retries=1 diff --git a/config/plugins.properties b/config/plugins.properties index c422d63..c0f1b45 100755 --- a/config/plugins.properties +++ b/config/plugins.properties @@ -1,3 +1,5 @@ +PID.java=enabled +SpinnerLayoutTest.java=disabled MXSC-1.10.0.jar=disabled ScreenPanel3.java=disabled Tomaz.java=disabled diff --git a/devices/as.properties b/devices/as.properties new file mode 100644 index 0000000..baa434c --- /dev/null +++ b/devices/as.properties @@ -0,0 +1,27 @@ +#Tue Oct 30 09:21:40 CET 2018 +colormap=Grayscale +colormapAutomatic=false +colormapLogarithmic=false +colormapMax=NaN +colormapMin=NaN +flipHorizontally=false +flipVertically=false +grayscale=false +imageHeight=3 +imageWidth=3 +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/as1.properties b/devices/as1.properties new file mode 100644 index 0000000..9ad1f88 --- /dev/null +++ b/devices/as1.properties @@ -0,0 +1,27 @@ +#Tue Oct 30 09:23:19 CET 2018 +colormap=Grayscale +colormapAutomatic=false +colormapLogarithmic=false +colormapMax=NaN +colormapMin=NaN +flipHorizontally=false +flipVertically=false +grayscale=false +imageHeight=3 +imageWidth=3 +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/cm1.properties b/devices/cm1.properties new file mode 100644 index 0000000..f461649 --- /dev/null +++ b/devices/cm1.properties @@ -0,0 +1,9 @@ +#Tue Oct 30 09:41:22 CET 2018 +mirror_x=false +mirror_y=false +precision=-1 +roi_height=-1 +roi_width=-1 +roi_x=0 +roi_y=0 +transpose=false diff --git a/devices/detector_roi_img.properties b/devices/detector_roi_img.properties new file mode 100644 index 0000000..e03ee73 --- /dev/null +++ b/devices/detector_roi_img.properties @@ -0,0 +1,25 @@ +#Fri Aug 31 16:53:08 CEST 2018 +colormap=Temperature +colormapAutomatic=true +colormapLogarithmic=false +colormapMax=1.0 +colormapMin=0.0 +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/deting.properties b/devices/deting.properties new file mode 100644 index 0000000..2bccd75 --- /dev/null +++ b/devices/deting.properties @@ -0,0 +1,25 @@ +#Thu Sep 13 17:21:24 CEST 2018 +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/motor2.properties b/devices/motor2.properties index 6eec265..2bb0f23 100755 --- a/devices/motor2.properties +++ b/devices/motor2.properties @@ -1,4 +1,4 @@ -#Tue Jun 19 17:19:36 CEST 2018 +#Tue Oct 16 15:21:38 CEST 2018 accessType=ReadWrite channel=MTEST-GOBBO\:MOT2 defaultSpeed=0.2 @@ -7,9 +7,9 @@ hasEnable=true homingDirection=Backward homingType=Backward maxSpeed=100.0 -maxValue=2.0 +maxValue=100.0 minSpeed=0.001 -minValue=-2.0 +minValue=-100.0 offset=10.0 precision=3 resolution=NaN diff --git a/devices/mt.properties b/devices/mt.properties new file mode 100644 index 0000000..96d7bad --- /dev/null +++ b/devices/mt.properties @@ -0,0 +1,9 @@ +#Tue Oct 30 08:49:48 CET 2018 +mirror_x=false +mirror_y=false +precision=-1 +roi_height=-1 +roi_width=-1 +roi_x=0 +roi_y=0 +transpose=false diff --git a/devices/mt1.properties b/devices/mt1.properties new file mode 100644 index 0000000..96d7bad --- /dev/null +++ b/devices/mt1.properties @@ -0,0 +1,9 @@ +#Tue Oct 30 08:49:48 CET 2018 +mirror_x=false +mirror_y=false +precision=-1 +roi_height=-1 +roi_width=-1 +roi_x=0 +roi_y=0 +transpose=false diff --git a/plugins/PID.java b/plugins/PID.java new file mode 100644 index 0000000..62f5bea --- /dev/null +++ b/plugins/PID.java @@ -0,0 +1,468 @@ +/** +* Small, easy to use PID implementation with advanced controller capability.
+* Minimal usage:
+* MiniPID pid = new MiniPID(p,i,d);
+* ...looping code...{
+* output= pid.getOutput(sensorvalue,target);
+* } +* +* @see http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-direction/improving-the-beginners-pid-introduction +*/ +public class PID{ + //********************************** + // Class private variables + //********************************** + + private double P=0; + private double I=0; + private double D=0; + private double F=0; + + private double maxIOutput=0; + private double maxError=0; + private double errorSum=0; + + private double maxOutput=0; + private double minOutput=0; + + private double setpoint=0; + + private double lastActual=0; + + private boolean firstRun=true; + private boolean reversed=false; + + private double outputRampRate=0; + private double lastOutput=0; + + private double outputFilter=0; + + private double setpointRange=0; + + //********************************** + // Constructor functions + //********************************** + + /** + * Create a MiniPID class object. + * See setP, setI, setD methods for more detailed parameters. + * @param p Proportional gain. Large if large difference between setpoint and target. + * @param i Integral gain. Becomes large if setpoint cannot reach target quickly. + * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot. + */ + public PID(double p, double i, double d){ + P=p; I=i; D=d; + checkSigns(); + } + + /** + * Create a MiniPID class object. + * See setP, setI, setD, setF methods for more detailed parameters. + * @param p Proportional gain. Large if large difference between setpoint and target. + * @param i Integral gain. Becomes large if setpoint cannot reach target quickly. + * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot. + * @param f Feed-forward gain. Open loop "best guess" for the output should be. Only useful if setpoint represents a rate. + */ + public PID(double p, double i, double d, double f){ + P=p; I=i; D=d; F=f; + checkSigns(); + } + + //********************************** + // Configuration functions + //********************************** + /** + * Configure the Proportional gain parameter.
+ * This responds quickly to changes in setpoint, and provides most of the initial driving force + * to make corrections.
+ * Some systems can be used with only a P gain, and many can be operated with only PI.
+ * For position based controllers, this is the first parameter to tune, with I second.
+ * For rate controlled systems, this is often the second after F. + * + * @param p Proportional gain. Affects output according to output+=P*(setpoint-current_value) + */ + public void setP(double p){ + P=p; + checkSigns(); + } + + /** + * Changes the I parameter
+ * This is used for overcoming disturbances, and ensuring that the controller always gets to the control mode. + * Typically tuned second for "Position" based modes, and third for "Rate" or continuous based modes.
+ * Affects output through output+=previous_errors*Igain ;previous_errors+=current_error + * + * @see {@link #setMaxIOutput(double) setMaxIOutput} for how to restrict + * + * @param i New gain value for the Integral term + */ + public void setI(double i){ + if(I!=0){ + errorSum=errorSum*I/i; + } + if(maxIOutput!=0){ + maxError=maxIOutput/i; + } + I=i; + checkSigns(); + // Implementation note: + // This Scales the accumulated error to avoid output errors. + // As an example doubling the I term cuts the accumulated error in half, which results in the + // output change due to the I term constant during the transition. + } + + /** + * Changes the D parameter
+ * This has two primary effects: + * + *
  • Adds a "startup kick" and speeds up system response during setpoint changes + *
  • Adds "drag" and slows the system when moving toward the target + * + * A small D value can be useful for both improving response times, and preventing overshoot. + * However, in many systems a large D value will cause significant instability, particularly + * for large setpoint changes. + *
    + * Affects output through output += -D*(current_input_value - last_input_value) + * + * @param d New gain value for the Derivative term + */ + public void setD(double d){ + D=d; + checkSigns(); + } + + /** + * Configure the FeedForward parameter.
    + * This is excellent for velocity, rate, and other continuous control modes where you can + * expect a rough output value based solely on the setpoint.
    + * Should not be used in "position" based control modes.
    + * Affects output according to output+=F*Setpoint. Note, that a F-only system is actually open loop. + * + * @param f Feed forward gain. + */ + public void setF(double f){ + F=f; + checkSigns(); + } + + /** + * Configure the PID object. + * See setP, setI, setD methods for more detailed parameters. + * @param p Proportional gain. Large if large difference between setpoint and target. + * @param i Integral gain. Becomes large if setpoint cannot reach target quickly. + * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot. + */ + public void setPID(double p, double i, double d){ + P=p;D=d; + //Note: the I term has additional calculations, so we need to use it's + //specific method for setting it. + setI(i); + checkSigns(); + } + + /** + * Configure the PID object. + * See setP, setI, setD, setF methods for more detailed parameters. + * @param p Proportional gain. Large if large difference between setpoint and target. + * @param i Integral gain. Becomes large if setpoint cannot reach target quickly. + * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot. + * @param f Feed-forward gain. Open loop "best guess" for the output should be. Only useful if setpoint represents a rate. + */ + public void setPID(double p, double i, double d,double f){ + P=p;D=d;F=f; + //Note: the I term has additional calculations, so we need to use it's + //specific method for setting it. + setI(i); + checkSigns(); + } + + /** + * Set the maximum output value contributed by the I component of the system + * This can be used to prevent large windup issues and make tuning simpler + * @param maximum. Units are the same as the expected output value + */ + public void setMaxIOutput(double maximum){ + // Internally maxError and Izone are similar, but scaled for different purposes. + // The maxError is generated for simplifying math, since calculations against + // the max error are far more common than changing the I term or Izone. + maxIOutput=maximum; + if(I!=0){ + maxError=maxIOutput/I; + } + } + + /** + * Specify a maximum output range.
    + * When one input is specified, output range is configured to + * [-output, output] + * @param output + */ + public void setOutputLimits(double output){ + setOutputLimits(-output,output); + } + + /** + * Specify a maximum output. + * When two inputs specified, output range is configured to + * [minimum, maximum] + * @param minimum possible output value + * @param maximum possible output value + */ + public void setOutputLimits(double minimum,double maximum){ + if(maximum(maximum-minimum) ){ + setMaxIOutput(maximum-minimum); + } + } + + /** + * Set the operating direction of the PID controller + * @param reversed Set true to reverse PID output + */ + public void setDirection(boolean reversed){ + this.reversed=reversed; + } + + //********************************** + // Primary operating functions + //********************************** + + /** + * Configure setpoint for the PID calculations
    + * This represents the target for the PID system's, such as a + * position, velocity, or angle.
    + * @see PID#getOutput(actual)
    + * @param setpoint + */ + public void setSetpoint(double setpoint){ + this.setpoint=setpoint; + } + + /** + * Calculate the output value for the current PID cycle.
    + * @param actual The monitored value, typically as a sensor input. + * @param setpoint The target value for the system + * @return calculated output value for driving the system + */ + public double getOutput(double actual, double setpoint){ + double output; + double Poutput; + double Ioutput; + double Doutput; + double Foutput; + + this.setpoint=setpoint; + + // Ramp the setpoint used for calculations if user has opted to do so + if(setpointRange!=0){ + setpoint=constrain(setpoint,actual-setpointRange,actual+setpointRange); + } + + // Do the simple parts of the calculations + double error=setpoint-actual; + + // Calculate F output. Notice, this depends only on the setpoint, and not the error. + Foutput=F*setpoint; + + // Calculate P term + Poutput=P*error; + + // If this is our first time running this, we don't actually _have_ a previous input or output. + // For sensor, sanely assume it was exactly where it is now. + // For last output, we can assume it's the current time-independent outputs. + if(firstRun){ + lastActual=actual; + lastOutput=Poutput+Foutput; + firstRun=false; + } + + // Calculate D Term + // Note, this is negative. This actually "slows" the system if it's doing + // the correct thing, and small values helps prevent output spikes and overshoot + Doutput= -D*(actual-lastActual); + lastActual=actual; + + // The Iterm is more complex. There's several things to factor in to make it easier to deal with. + // 1. maxIoutput restricts the amount of output contributed by the Iterm. + // 2. prevent windup by not increasing errorSum if we're already running against our max Ioutput + // 3. prevent windup by not increasing errorSum if output is output=maxOutput + Ioutput=I*errorSum; + if(maxIOutput!=0){ + Ioutput=constrain(Ioutput,-maxIOutput,maxIOutput); + } + + // And, finally, we can just add the terms up + output=Foutput + Poutput + Ioutput + Doutput; + + // Figure out what we're doing with the error. + if(minOutput!=maxOutput && !bounded(output, minOutput,maxOutput) ){ + errorSum=error; + // reset the error sum to a sane level + // Setting to current error ensures a smooth transition when the P term + // decreases enough for the I term to start acting upon the controller + // From that point the I term will build up as would be expected + } + else if(outputRampRate!=0 && !bounded(output, lastOutput-outputRampRate,lastOutput+outputRampRate) ){ + errorSum=error; + } + else if(maxIOutput!=0){ + errorSum=constrain(errorSum+error,-maxError,maxError); + // In addition to output limiting directly, we also want to prevent I term + // buildup, so restrict the error directly + } + else{ + errorSum+=error; + } + + // Restrict output to our specified output and ramp limits + if(outputRampRate!=0){ + output=constrain(output, lastOutput-outputRampRate,lastOutput+outputRampRate); + } + if(minOutput!=maxOutput){ + output=constrain(output, minOutput,maxOutput); + } + if(outputFilter!=0){ + output=lastOutput*outputFilter+output*(1-outputFilter); + } + + // Get a test printline with lots of details about the internal + // calculations. This can be useful for debugging. + // System.out.printf("Final output %5.2f [ %5.2f, %5.2f , %5.2f ], eSum %.2f\n",output,Poutput, Ioutput, Doutput,errorSum ); + // System.out.printf("%5.2f\t%5.2f\t%5.2f\t%5.2f\n",output,Poutput, Ioutput, Doutput ); + + lastOutput=output; + return output; + } + + /** + * Calculate the output value for the current PID cycle.
    + * In no-parameter mode, this uses the last sensor value, + * and last setpoint value.
    + * Not typically useful, and use of parameter modes is suggested.
    + * @return calculated output value for driving the system + */ + public double getOutput(){ + return getOutput(lastActual,setpoint); + } + + /** + * Calculate the output value for the current PID cycle.
    + * In one parameter mode, the last configured setpoint will be used.
    + * @see PID#setSetpoint() + * @param actual The monitored value, typically as a sensor input. + * @param setpoint The target value for the system + * @return calculated output value for driving the system + */ + public double getOutput(double actual){ + return getOutput(actual,setpoint); + } + + /** + * Resets the controller. This erases the I term buildup, and removes + * D gain on the next loop.
    + * This should be used any time the PID is disabled or inactive for extended + * duration, and the controlled portion of the system may have changed due to + * external forces. + */ + public void reset(){ + firstRun=true; + errorSum=0; + } + + /** + * Set the maximum rate the output can increase per cycle.
    + * This can prevent sharp jumps in output when changing setpoints or + * enabling a PID system, which might cause stress on physical or electrical + * systems.
    + * Can be very useful for fast-reacting control loops, such as ones + * with large P or D values and feed-forward systems. + * + * @param rate, with units being the same as the output + */ + public void setOutputRampRate(double rate){ + outputRampRate=rate; + } + + /** + * Set a limit on how far the setpoint can be from the current position + *
    Can simplify tuning by helping tuning over a small range applies to a much larger range. + *
    This limits the reactivity of P term, and restricts impact of large D term + * during large setpoint adjustments. Increases lag and I term if range is too small. + * @param range, with units being the same as the expected sensor range. + */ + public void setSetpointRange(double range){ + setpointRange=range; + } + + /** + * Set a filter on the output to reduce sharp oscillations.
    + * 0.1 is likely a sane starting value. Larger values use historical data + * more heavily, with low values weigh newer data. 0 will disable, filtering, and use + * only the most recent value.
    + * Increasing the filter strength will P and D oscillations, but force larger I + * values and increase I term overshoot.
    + * Uses an exponential wieghted rolling sum filter, according to a simple
    + *
    output*(1-strength)*sum(0..n){output*strength^n}
    algorithm. + * @param output valid between [0..1), meaning [current output only.. historical output only) + */ + public void setOutputFilter(double strength){ + if(strength==0 || bounded(strength,0,1)){ + outputFilter=strength; + } + } + + //************************************** + // Helper functions + //************************************** + + /** + * Forces a value into a specific range + * @param value input value + * @param min maximum returned value + * @param max minimum value in range + * @return Value if it's within provided range, min or max otherwise + */ + private double constrain(double value, double min, double max){ + if(value > max){ return max;} + if(value < min){ return min;} + return value; + } + + /** + * Test if the value is within the min and max, inclusive + * @param value to test + * @param min Minimum value of range + * @param max Maximum value of range + * @return true if value is within range, false otherwise + */ + private boolean bounded(double value, double min, double max){ + // Note, this is an inclusive range. This is so tests like + // `bounded(constrain(0,0,1),0,1)` will return false. + // This is more helpful for determining edge-case behaviour + // than <= is. + return (min0) P*=-1; + if(I>0) I*=-1; + if(D>0) D*=-1; + if(F>0) F*=-1; + } + else{ // all values should be above zero + if(P<0) P*=-1; + if(I<0) I*=-1; + if(D<0) D*=-1; + if(F<0) F*=-1; + } + } +} \ No newline at end of file diff --git a/script/AreaDetectorROI.py b/script/AreaDetectorROI.py new file mode 100644 index 0000000..e3fbd32 --- /dev/null +++ b/script/AreaDetectorROI.py @@ -0,0 +1,27 @@ +device = det +det.imageCounter.polling = 500 + +class AreaDetectorROI(ReadonlyRegisterBase, ReadonlyRegisterMatrix): + def __init__(self, name, detector, x, y, w, h): + ReadonlyRegisterBase.__init__(self, name) + self.detector = detector + self.x, self.y, self.w, self.h = x, y, w, h + + def doRead(self): + data = self.detector.dataMatrix.take() + ret = Convert.matrixRoi(data, self.x, self.y, self.w, self.h) + return ret + + def getWidth(self): + return self.w + + def getHeight(self): + return self.h + + +add_device(AreaDetectorROI("roi1", device, 10,10,10,5), True) +add_device(AreaDetectorROI("roi2", device,100,30,7,3), True) + +#tscan((roi1, roi2), 10, 0.1) + +mscan(device.imageCounter, (roi1, roi2), 10, async=False) \ No newline at end of file diff --git a/script/TestPID.py b/script/TestPID.py new file mode 100644 index 0000000..e69de29 diff --git a/script/local.groovy b/script/local.groovy index 1c34bc1..cb64a4b 100755 --- a/script/local.groovy +++ b/script/local.groovy @@ -1,18 +1,21 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// // Deployment specific global definitions - executed after startup.groovy /////////////////////////////////////////////////////////////////////////////////////////////////// -import ch.psi.pshell.scan.ScanRecord +import ch.psi.pshell.scan.ScanRecord System.out.println("OK") before_readout = { double[] pos-> println (pos) } -after_readout = { ScanRecord rec->println (rec) } +after_readout = { ch.psi.pshell.scan.ScanRecord rec->println (rec) } def onBeforeReadout(double[]pos){ println (pos) } -def onAfterReadout(ScanRecord rec){ +def onAfterReadout(ch.psi.pshell.scan.ScanRecord rec){ println (rec) -} \ No newline at end of file +} + + +//// \ No newline at end of file diff --git a/script/local.js b/script/local.js index a7bb602..20bc0fa 100755 --- a/script/local.js +++ b/script/local.js @@ -10,4 +10,5 @@ function onAfterReadout(rec){ -run("SimulatedDEvices") \ No newline at end of file +run("SimulatedDEvices") + diff --git a/script/local.py b/script/local.py index 67eae9e..19168fa 100755 --- a/script/local.py +++ b/script/local.py @@ -8,17 +8,21 @@ import ch.psi.pshell.crlogic.CrlogicPositioner as CrlogicPositioner import ch.psi.pshell.crlogic.CrlogicSensor as CrlogicSensor +def on_command_started(info): + print "Started: " + str(info.script) + str(info.error) +def on_command_finished(info): + print "Finished: " + str(info.script) + str(info.error) ################################################################################################### # Layout setup ################################################################################################### import ch.psi.pshell.data.LayoutSF as LayoutSF -LayoutSF.setExperimentArguments([pv, motor, pe, cv, en, sin]) +LayoutSF.setExperimentArguments([pv, motor, pe, cv, energy, sin]) -#Libraries +#Librariesenergy #import Jama.Matrix #sys.path.append('/Users/gobbo_a/dev/pshell/config/home/script/Lib/diffcalc') @@ -136,14 +140,14 @@ get_context().addListener(clistener) def trig_scienta(): time.sleep(1.0) -energy = None +en_val = None class SimulatedEnergy(Writable): def write(self, value): self.put(value) def put(self, value, timeout = None): - global energy - energy = value + global en_val + en_val = value def close(self): pass @@ -155,8 +159,8 @@ class SimulatedEnergy(Writable): class SimulatedEnergyReadback(Readable): def read(self): - global energy - return energy; + global en_val + return en_val; def get(self): return self.read() diff --git a/script/test/CustomPlot.py b/script/test/CustomPlot.py new file mode 100644 index 0000000..4e1b69f --- /dev/null +++ b/script/test/CustomPlot.py @@ -0,0 +1,14 @@ + + +p = plot(None, title="Custom Plot")[0] +p.addSeries(LinePlotSeries("My Series")) +proc_data = "/proc/calc" + +create_dataset(proc_data , 'd') + +def AfterReadout(record, scan): + val = record.values[1] - record.values[0] + p.getSeries(0).appendData(record.positions[0], val) + append_dataset(proc_data , val) + +lscan(inp, (out, sin), 0.0, 10.0, 1.0, latency = 0.1, after_read=AfterReadout) \ No newline at end of file diff --git a/script/test/TestChanel.py b/script/test/TestChanel.py new file mode 100644 index 0000000..eacc2f0 --- /dev/null +++ b/script/test/TestChanel.py @@ -0,0 +1,22 @@ +import ch.psi.pshell.epics.CAS as CAS +import random +class Waveform(ReadonlyRegisterBase, ReadonlyRegisterArray): + def doRead(self): + ret = [] + for i in range(self.getSize()): + ret.append(random.random()) + ret = to_array(ret, 'd') + return ret + + def getSize(self): + return 1000 + + +wf = Waveform("wf") +wf.initialize() +print wf.read()[0] + +casN = CAS("TESTCAS:VAL", wf, 'double') +print casN + +print caget("TESTCAS:VAL") \ No newline at end of file diff --git a/script/test/TestData.py b/script/test/TestData.py new file mode 100644 index 0000000..578093b --- /dev/null +++ b/script/test/TestData.py @@ -0,0 +1,78 @@ +################################################################################################### +#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 read.tolist() +assert data1d==read.tolist() +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 read.tolist() +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 read.tolist() +read =load_data(path,1) +print read.tolist() + +#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") + + diff --git a/script/test/TestDetectorROI.py b/script/test/TestDetectorROI.py new file mode 100644 index 0000000..ff98632 --- /dev/null +++ b/script/test/TestDetectorROI.py @@ -0,0 +1,22 @@ + + + + + +class DetectorRoi(ReadonlyRegisterBase, ReadonlyRegisterMatrix): + def doRead(self): + #data = caget(“PINK:GEYES:image2:ArrayData") + data = caget("TESTCAS:VAL", '[d', self.getHeight() * self.getWidth()) + return Convert.reshape(data,self.getHeight(), self.getWidth()) # + + def getWidth(self): + return 50 + + def getHeight(self): + return 20 + +add_device (DetectorRoi("detector_roi"), True) + + +add_device(RegisterMatrixSource("detector_roi_img", detector_roi), True) +detector_roi_img.polling = -500 \ No newline at end of file diff --git a/script/test/TestDiff.py b/script/test/TestDiff.py new file mode 100644 index 0000000..6a80146 --- /dev/null +++ b/script/test/TestDiff.py @@ -0,0 +1,557 @@ +###################################################################################################\ +# Diffcalc utilities +################################################################################################### + +###################################################################################################\ +# Installaling +################################################################################################### + +#1- Download from: https://github.com/DiamondLightSource/diffcalc/archive/master.zip +#2- Extract the contents to {script}/Lib/diffcalc +#3- Download http://central.maven.org/maven2/gov/nist/math/jama/1.0.3/jama-1.0.3.jar +# to the extensions folder. + +###################################################################################################\ +# Library loading and Hardware setup +################################################################################################### + +#1- Create a MotorGroup with the diffractometer motors +# e.g. 'sixc', containing mu, delta, gam, eta, chi, phi motors (gam = nu) +# or 'fivec', containing delta, gam, eta, chi, phi motors +# or 'fourc', containing delta, eta, chi, phi motors +#2- Create positioner to read/set the energy in kEv, e.g. named 'en' +#3- Execute: run("diffutils") +#4- Execute: setup_diff(sixc, en) + + +from __future__ import absolute_import +import traceback + + +import Jama.Matrix +diffcalc_path = os.path.abspath(get_context().setup.expandPath("{script}/Lib/diffcalc")) +if not diffcalc_path in sys.path: + sys.path.append(diffcalc_path) + +import diffcalc +from diffcalc import settings +from diffcalc.hkl.you.geometry import YouGeometry,SixCircle, FiveCircle, FourCircle, YouPosition +from diffcalc.hardware import HardwareAdapter +from diffcalc.ub.persistence import UbCalculationNonPersister +from diffcalc.gdasupport.minigda.scannable import ScannableBase, ScannableGroup +#from diffcalc.gdasupport.minigda import command +from diffcalc.hardware import HardwareAdapter + + +import ch.psi.pshell.device.PositionerConfig as PositionerConfig +import ch.psi.pshell.device.RegisterConfig as RegisterConfig +import ch.psi.pshell.device.Register as Register + +_difcalc_names = {} + +# +# Disable error handling designed for interactive use +#diffcalc.util.DEBUG = True + +################################################################################################### +# Device mapping to difcalc +################################################################################################### +class PositionerScannable(ScannableBase): + def __init__(self, positioner, name = None): + self.positioner = positioner + self.name = positioner.name if name is None else name + self.inputNames = [self.name] + self.outputFormat = ['% 6.4f'] + self.level = 3 + + def isBusy(self): + return self.positioner.state == State.Busy + + def waitWhileBusy(self): + self.positioner.waitReady(-1) + + def asynchronousMoveTo(self, new_position): + #print "Moving " , self.name, " to: ", new_position + self.positioner.moveAsync(float(new_position), -1) + + def getPosition(self): + return self.positioner.getPosition() + +def _get_diffcalc_axis_names(): + nu_name=diffcalc.hkl.you.constraints.NUNAME + return ("mu", "delta", nu_name, "eta", "chi", "phi") + +class PositionerScannableGroup(ScannableGroup): + def __init__(self, name, motors, diffcalc_axis_names=None): + self.name = name + global _difcalc_names + _difcalc_names = {} + positioners = [] + if diffcalc_axis_names is None: + if len(motors) == 6: diffcalc_axis_names = _get_diffcalc_axis_names() + elif len(motors) == 5: diffcalc_axis_names = ("delta", "gam", "eta", "chi", " phi") + elif len(motors) == 4: diffcalc_axis_names = ("delta", "eta", "chi", " phi") + for i in range(len(motors)): + _difcalc_names[motors[i]] = diffcalc_axis_names[i] + exec('self.' + diffcalc_axis_names[i] + ' = PositionerScannable(' + motors[i].name + ', "' +diffcalc_axis_names[i] + '")') + exec('positioners.append(self.' + diffcalc_axis_names[i] + ')' ) + #for m in motors: + # exec('self.' + m.name + ' = PositionerScannable(' + m.name + ', "' + m.name + '")') + # exec('positioners.append(self.' + m.name + ')' ) + ScannableGroup.__init__(self, self.name, positioners) + +class MotorGroupScannable(PositionerScannableGroup): + def __init__(self, motor_group, diffcalc_axis_names=None): + self.motor_group = motor_group + PositionerScannableGroup.__init__(self, motor_group.name, motor_group.motors, diffcalc_axis_names) + + +class ScannableAdapter(HardwareAdapter): + def __init__(self, diffractometer, energy, energy_multiplier_to_kev=1): + self.diffractometer = diffractometer + self.energy = energy + self.energy_multiplier_to_kev = energy_multiplier_to_kev + input_names = diffractometer.getInputNames() + HardwareAdapter.__init__(self, input_names) + + #Returns the current physical POSITIONS + def get_position(self): + """ + pos = getDiffractometerPosition() -- returns the current physical + diffractometer position as a list in degrees + """ + return self.diffractometer.getPosition() + + #returns energy in kEv + def get_energy(self): + """energy = get_energy() -- returns energy in kEv (NOT eV!) """ + multiplier = self.energy_multiplier_to_kev + energy = self.energy.getPosition() * multiplier + if energy is None: + raise DiffcalcException("Energy has not been set") + return energy + + @property + def name(self): + return self.diffractometer.getName() + +class MotorGroupAdapter(ScannableAdapter): + def __init__(self, diffractometer, energy, energy_multiplier_to_kev=1, diffcalc_axis_names=None): + self.diffractometer = MotorGroupScannable(diffractometer, diffcalc_axis_names) + self.energy = PositionerScannable(energy) + self.energy.level = 3 + ScannableAdapter.__init__(self, self.diffractometer, self.energy, energy_multiplier_to_kev) + +class Wavelength(RegisterBase): + def doRead(self): + try: + return get_wavelength().getPosition() + except: + return None + + def doWrite(self, val): + get_wavelength().asynchronousMoveTo(val) + + +################################################################################################### +# HKL Pseudo-devices +################################################################################################### +class HklPositoner (PositionerBase): + def __init__(self, name, index, hkl_group): + PositionerBase.__init__(self, name, PositionerConfig()) + self.setParent(hkl_group) + self.index = index + + def isReady(self): + return PositionerBase.isReady(self) and self.getParent().isReady() + + def doRead(self): + return self.getParent()._setpoint[self.index] + + def doWrite(self, value): + #print "Setting " , self.getName(), "to: ", value + pos = [None, None, None] + pos[self.index] = value + self.getParent().write(pos) + + def doReadReadback(self): + if java.lang.Thread.currentThread() != self.getParent()._updating_thread: + self.getParent().update() + return self.getParent()._readback[self.index] + +class HklGroup(RegisterBase, Register.RegisterArray): + def __init__(self, name): + RegisterBase.__init__(self, name, RegisterConfig()) + self.hkl=get_hkl() + self.h, self.k, self.l = HklPositoner("h", 0, self), HklPositoner("k", 1, self), HklPositoner("l", 2, self) + add_device(self.h, True) + add_device(self.k, True) + add_device(self.l, True) + self._setpoint = self.doRead() + self._updating = False + + def getSize(self): + return 3 + + def doRead(self): + try: + self._readback = self.hkl.getPosition() + self._updating_thread = java.lang.Thread.currentThread() + self.h.update() + self.k.update() + self.l.update() + except: + #traceback.print_exc() + self._readback = (None, None, None) + finally: + self._updating_thread = None + return self._readback + + def doWrite(self, pos): + self._setpoint = pos + #print "Moving to: " + str(pos) + self.hkl.asynchronousMoveTo(pos) + + def sim(self, pos): + return self.hkl.simulateMoveTo(pos) + +################################################################################################### +# System setup +################################################################################################### +you = None +dc, ub, hardware, hkl = None, None, None, None +_motor_group = None +def setup_diff(diffractometer, energy, diffcalc_axis_names = None, geometry=None): + """ + diffractometer: Diffraction motor group + energy: Positioner having energy in kev + geometry: YouGeometry extension. If none, uses default + diffcalc_axis_names: if None use defaults: + - mu, delta, gam, eta, chi, phi (six circle) + - delta, gam, eta, chi, phi (ficve circle) + - delta, eta, chi, phi (four circle) + """ + global you, dc, ub, hardware, hkl, _motor_group + _motor_group = diffractometer + you = None + if geometry is not None: + settings.geometry = geometry + elif diffcalc_axis_names is not None: + class CustomGeometry(YouGeometry): + def __init__(self): + self.all_axis_names = _get_diffcalc_axis_names() + self.my_axis_names = diffcalc_axis_names + fixed_constraints = {} + for axis in self.all_axis_names: + if not axis in self.my_axis_names: + fixed_constraints[axis] = 0 + YouGeometry.__init__(self, diffractometer.name, fixed_constraints) + def physical_angles_to_internal_position(self, physical_angle_tuple): + pos=[] + index = 0 + for axis in self.all_axis_names: + pos.append(physical_angle_tuple[index] if (axis in self.my_axis_names) else 0) + index = index+1 + return YouPosition(*pos) + def internal_position_to_physical_angles(self, internal_position): + pos = internal_position.totuple() + ret = [] + for i in range (len(self.all_axis_names)): + if self.all_axis_names[i] in self.my_axis_names: + ret.append(pos[i]) + return tuple(ret) + settings.geometry = CustomGeometry() + elif len(diffractometer.motors) == 6: + settings.geometry = SixCircle() + elif len(diffractometer.motors) == 5: + settings.geometry = FiveCircle() + elif len(diffractometer.motors) == 4: + settings.geometry = FourCircle() + else: + raise Exception("Invalid motor group") + settings.hardware = MotorGroupAdapter(diffractometer, energy, diffcalc_axis_names = diffcalc_axis_names) + settings.ubcalc_persister = UbCalculationNonPersister() + settings.axes_scannable_group = settings.hardware.diffractometer + settings.energy_scannable = settings.hardware.energy + settings.ubcalc_strategy = diffcalc.hkl.you.calc.YouUbCalcStrategy() + settings.angles_to_hkl_function = diffcalc.hkl.you.calc.youAnglesToHkl + from diffcalc.gdasupport import you + reload(you) + + # These must be imported AFTER the settings have been configured + from diffcalc.dc import dcyou as dc + from diffcalc.ub import ub + from diffcalc import hardware + from diffcalc.hkl.you import hkl + + add_device(HklGroup("hkl_group"), True) + add_device(Wavelength("wavelength", 6), True) + hkl_group.polling = 250 + wavelength.polling = 250 + +def setup_axis(motor, min=None, max=None, cut=None): + name = _difcalc_names[motor] + if min is not None: hardware.setmin(name, min) + if max is not None: hardware.setmax(name, max) + if cut is not None: hardware.setcut(name, cut) + +def print_axis_setup(): + print "Diffcalc names:" + for m in _difcalc_names.keys(): + print " \t" + m.name + " = " + _difcalc_names[m] + print "------------------------------------------------------" + hardware.hardware() + + +################################################################################################### +# Acceess functions +################################################################################################### +def get_diff(): + return settings.hardware.diffractometer + +def get_en(): + return settings.hardware.energy + +def get_motor_group(): + return _motor_group + +def get_wavelength(): + return you.wl + +def get_hkl(): + return you.hkl + +def hkl_to_angles(h, k, l, energy=None): + return dc.hkl_to_angles(h, k, l, energy) + +def angles_to_hkl(positions, energy=None): + return dc.angles_to_hkl(positions, energy) + +def hkl_read(): + return hkl_group.read() + +def hkl_write(h, k, l): + hkl_group.write([h,k,l]) + +def hkl_simulate(h, k, l): + return hkl_group.sim([h,k,l]) + +def con(*args): + hkl.con(*args) + +def uncon(name): + hkl.uncon(name) + +def print_con(): + hkl.con() +################################################################################################### +# HKL Combined Scan +################################################################################################### +def hklscan(vector, readables,latency = 0.0, passes = 1, **pars): + """ + HKL Scan: + + Args: + vector(list of lists): HKL values to be scanned + readables(list of Readable): Sensors to be sampled on each step. + latency(float, optional): settling time for each step before readout, defaults to 0.0. + passes(int, optional): number of passes + 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, optional): callback on each step, before sampling. Arguments: positions, scan + - after_read (function, optional): callback on each step, after sampling. Arguments: record, scan. + - before_pass (function, optional): callback before each scan pass execution. Arguments: pass_num, scan. + - after_pass (function, optional): callback after each scan pass execution. Arguments: pass_num, scan. + - Aditional arguments defined by set_exec_pars. + Returns: + ScanResult object. + + """ + readables=to_list(string_to_obj(readables)) + pars["initial_move"] = False + scan = ManualScan([h,k,l], readables ,vector[0], vector[-1], [len(vector)-1] * 3, dimensions = 1) + if not "domain_axis" in pars.keys(): + pars["domain_axis"] = "Index" + processScanPars(scan, pars) + scan.start() + try: + for pos in vector: + #print "Writing ", pos + hkl_group.write(pos) + time.sleep(0.1) #Make sure is busy + get_motor_group().update() + get_motor_group().waitReady(-1) + time.sleep(latency) + hkl_group.update() + scan.append ([h.take(), k.take(), l.take()], [h.getPosition(), k.getPosition(), l.getPosition()], [readable.read() for readable in readables ]) + finally: + scan.end() + return scan.result + + +def test_diffcalc(): + print "Start test" + en.move(20.0) + delta.config.maxSpeed = 50.0 + delta.speed = 50.0 + delta.move(1.0) + + #Setup + setup_diff(sixc, en) + setup_axis('gam', 0, 179) + setup_axis('delta', 0, 179) + setup_axis('delta', min=0) + setup_axis('phi', cut=-180.0) + print_axis_setup() + + #Orientation + help(ub.ub) + ub.listub() + # Create a new ub calculation and set lattice parameters + ub.newub('test') + ub.setlat('cubic', 1, 1, 1, 90, 90, 90) + # Add 1st reflection (demonstrating the hardware adapter) + settings.hardware.wavelength = 1 + ub.c2th([1, 0, 0]) # energy from hardware + settings.hardware.position = 0, 60, 0, 30, 0, 0 + ub.addref([1, 0, 0])# energy and position from hardware + # Add 2nd reflection (this time without the harware adapter) + ub.c2th([0, 1, 0], 12.39842) + ub.addref([0, 1, 0], [0, 60, 0, 30, 0, 90], 12.39842) + # check the state + ub.ub() + ub.checkub() + + #Constraints + help(hkl.con) + hkl.con('qaz', 90) + hkl.con('a_eq_b') + hkl.con('mu', 0) + hkl.con() + + #Motion + print angles_to_hkl((0., 60., 0., 30., 0., 0.)) + print hkl_to_angles(1, 0, 0) + sixc.write([0, 60, 0, 30, 90, 0]) + print "sixc=" , sixc.position + wavelength.write(1.0) + print "wavelength = ", wavelength.read() + ub.lastub() + ub.setu ([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + ub.showref() + ub.swapref(1,2) + #print you.hkl + #pos(get_hkl()) + hkl_group.read() + #you.hkl.simulateMoveTo([0,1,1]) + #sim(get_hkl(), [0,1,1]) + hkl_group.sim([0.0,1.0,1.0]) + #pos(get_hkl(), [0,1,1]) + hkl_group.write([0.0,1.0,1.0]) + + #Scans + lscan(l, [sin], 1.0, 1.5, 0.1) + ascan([k,l], [sin], [1.0, 1.0], [1.2, 1.3], [0.1, 0.1], zigzag=True, parallel_positioning = False) + vector = [[1.0,1.0,1.0], [1.0,1.0,1.1], [1.0,1.0,1.2], [1.0,1.0,1.4]] + hklscan(vector, [sin, arr], 0.9) + + + + + + + + + + + + + +# +#run("diffutils") + +###################################################################################################\ +#Setup +################################################################################################### + +#alpha, delta, gamma, omegaV +setup_diff(fourcv, energy, ("mu", "delta", "gam", "eta")) +print_axis_setup() + + +setup_axis(mu, mu.getMinValue(), mu.getMaxValue()) +setup_axis(delta, delta.getMinValue(), 90) #delta.getMaxValue()) +setup_axis(gamma, 0, gamma.getMaxValue()) +setup_axis(eta, eta.getMinValue(), eta.getMaxValue()) + + +wavelength.write(1.0) + + +###################################################################################################\ +#Orientation +################################################################################################### +help(ub.ub) +ub.listub() + +#alpha delta gamma omegaV + +# Create a new ub calculation and set lattice parameters +ub.newub('test') + +""" +ub.setlat('cubic', 5.114, 5.8361, 11.058, 90, 90, 90) +en = 8 +#ub.c2th([0, 0, 4], en) +#ub.addref([0, 0, 4]) #From current position and ekergy +ub.addref([0, 0, 4], [16.2785, 0.0, 32.5568, 0.0], en) +#ub.c2th([2, 0, 12], en) +ub.addref([2, 0, 12], [71.8285, 37.3082, 138.7440, 0.0], en) +#ub.c2th([1, -4, 10], en) +ub.addref([1, -4, 10], [27.7185, 17.6409 , 128.4220, 0.0], en) +""" + +ub.setlat('cubic', 1.0, 1.0, 1.0, 90, 90, 90) + +en = 12.4 +#ub.c2th([0, 0, 4], en) +#ub.addref([0, 0, 4]) #From current position and ekergy +ub.addref([0, 0, 1], [30.0, 0.0, 60.0, 0.0], en) +#ub.c2th([2, 0, 12], en) +ub.addref([1, 0, 1], [20.0, 45.5564,90.000, 44.4437], en) +#ub.c2th([1, -4, 10], en) +ub.addref([0, 1, 1], [20.0, 45.5564,90.000, 134.4437], en) + +ub.ub() + +#ub.setub([[1.22862,0.00000,0.00000], [-0.00000,1.07663,0.00000], [-0.00000,-0.00000,0.56820]]) + + +# check the state + +ub.checkub() + + + +###################################################################################################\ +#Constraints +################################################################################################### +help(hkl.con) +hkl.con('a_eq_b') +#hkl.con('eta:0') + + +#hkl.con( 'eta', 0) #OmegaV constant +#hkl.con( 'mu', 20) #Alpha constant + + +###################################################################################################\ +#Motion +################################################################################################### + +#print angles_to_hkl((16.278, 0.0000, 32.5568, 0.0)) +#print angles_to_hkl((44.3400, 0.0000, 123.7322 , 0.0)) +#print hkl_to_angles(2, -2, 10) + + \ No newline at end of file diff --git a/script/test/TestNilson.py b/script/test/TestNilson.py new file mode 100644 index 0000000..fe0d445 --- /dev/null +++ b/script/test/TestNilson.py @@ -0,0 +1,154 @@ +# Greateyes scan + +#******** SCAN Settings ******** +Note="DESY - " + +Exp_Time= 1 + +X0=4200 +Xstep=450 +XNum_points=3 + +Y0=5960 +Ystep=-40 +YNum_points=10 + +GE_ROI_Line = 3 + +GE_AreaDet = det + +GE_ROI_Image= det.getDataMatrix() +GE_Raw_Image= det.getDataMatrix() +GE_BG_Image = det.getDataMatrix() +GE_Spectrum_Conv = det.getDataArray() +GE_Spectrum = det.getDataArray() +GE_BG_Line = det.getArraySize2() +GE_BG_SizeX = det.getArraySize0() +GE_BG_SizeY = det.getArraySize1() +GE_ROI_Line = det.getArraySize2() +GE_ROI_SizeX = det.getArraySize0() +GE_ROI_SizeY = det.getArraySize1() +IZero_Profile = det.getDataArray() +TFY_Profile = det.getDataArray() +IZero=sin +TFY = sin +GE_Sensor_Temp = sin +GE_FrameID = sin +Press_Diag_PV= sin +Press_Spec_PV= sin +Press_Spec_HV =sin +Press_Sample_Ch=sin +Press_Diag_HV = sin +GE_Spectrum_Sum = det.getDataArray() + +#******** Functions Definitions ******** +def Save_Pre_Scan_Data(): + save_dataset("RAW/GE_BG_Image", GE_BG_Image.read()) + save_dataset("Processed/GE_Spectrum_Convertion", GE_Spectrum_Conv.read()) + save_dataset("Detector/GE_ROI_Line", GE_ROI_Line.read()) + save_dataset("Detector/GE_ROI_SizeX", GE_ROI_SizeX.read()) + save_dataset("Detector/GE_ROI_SizeY", GE_ROI_SizeY.read()) + save_dataset("Detector/Exposure_Time", GE_AreaDet.getExposure()) + save_dataset("Detector/GE_Open_Delay", 1) + save_dataset("Detector/GE_Close_Delay", 1) + save_dataset("Detector/GE_Num_Images", GE_AreaDet.getNumImages()) + save_dataset("Detector/Gain_Type", 1) + save_dataset("Scan/Scan_Start_Time", time.ctime()) + save_dataset("Scan/Note", Note) + #save_dataset("Scan/Note", Note) + +def Create_Scan_Dataset(): + create_dataset("RAW/GE_Raw_Image", 'd', False, (Num_Images, int(GE_BG_SizeY.take()), int(GE_BG_SizeX.take()))) + create_dataset("RAW/IZero_Profile", 'd', False, (Num_Images, 100)) + create_dataset("RAW/TFY_Profile", 'd', False, (Num_Images, 100)) + create_dataset("Processed/GE_ROI_Image", 'd', False, (Num_Images, int(GE_ROI_SizeY.take()), int(GE_ROI_SizeX.take()))) + create_dataset("Processed/GE_Spectrum", 'd', False, (Num_Images, int(GE_BG_SizeX.take()))) + create_dataset("Processed/Izero", 'd', False) + create_dataset("Processed/TFY", 'd', False) + create_dataset("Detector/GE_Sensor_Temp", 'd', False) + create_dataset("Scan/GE_FrameID", 'i', False) + create_dataset("Scan/Timestamps", 'l', False) + create_dataset("Pressure/Diagnostic_PV", 'd', False) + create_dataset("Pressure/Diagnostic_HV", 'd', False) + create_dataset("Pressure/Spectrometer_PV", 'd', False) + create_dataset("Pressure/Spectrometer_HV", 'd', False) + create_dataset("Pressure/Sample_Chamber", 'd', False) + create_dataset("RAW/Xposition", 'd', False) + create_dataset("RAW/Yposition", 'd', False) + + + +def Save_Scan_Data(): + #sleep(0.2) + append_dataset("RAW/GE_Raw_Image", GE_Raw_Image.read()) + append_dataset("RAW/IZero_Profile", IZero_Profile.take()) + append_dataset("RAW/TFY_Profile", TFY_Profile.take()) + append_dataset("Processed/GE_ROI_Image", GE_ROI_Image.read()) + append_dataset("Processed/GE_Spectrum", GE_Spectrum.take()) + append_dataset("Processed/Izero", IZero.take()) + append_dataset("Processed/TFY", TFY.take()) + append_dataset("Detector/GE_Sensor_Temp", GE_Sensor_Temp.take()) + append_dataset("Scan/GE_FrameID", GE_FrameID.take()) + append_dataset("Scan/Timestamps", GE_FrameID.getTimestampNanos()) + append_dataset("Pressure/Diagnostic_PV", Press_Diag_PV.take()) + append_dataset("Pressure/Diagnostic_HV", Press_Diag_HV.take()) + append_dataset("Pressure/Spectrometer_PV", Press_Spec_PV.take()) + append_dataset("Pressure/Spectrometer_HV", Press_Spec_HV.take()) + append_dataset("Pressure/Sample_Chamber", Press_Sample_Ch.take()) + #Scan_Progress = (100*calcprog(GE_FrameID.take(),GE_start_frame,Num_Images)) + +def Save_Pos_Scan_Data(): + sleep(1) + save_dataset("Processed/GE_Spectrum_Sum", GE_Spectrum_Sum.read()) + save_dataset("Scan/Scan_Finish_Time", time.ctime()) + +#******** Test limits on sample vertical and horizontal motor ******** +X0=float(X0) +Xstep=float(Xstep) +Y0=float(Y0) +Ystep=float(Ystep) + +X1=X0+(XNum_points*Xstep) +Y1=Y0+(YNum_points*Ystep) +Num_Images= XNum_points*YNum_points + +#******** Setting up Caenels ******** +values_p_reading=1000*Exp_Time +Scan_Progress = 1 + +############### Scan ############### + + +#******** Scan Script Begins here ******** + +# Set Nr of images to NofImages +#******** Saving Pre Scan data ******** +Save_Pre_Scan_Data() + +#******** Pre Scan Setup ******** +print("Scan starting: " + time.ctime()) +GE_start_frame =1 +Create_Scan_Dataset() +#Sample_Horiz.move(X0) + + +#******** Main Scan Function ******** + +for j in range(XNum_points): + #Sample_Horiz.move(X0+(j*Xstep)) + for i in range(YNum_points): + #Sample_Vert.move(Y0+(i*Ystep)) + print GE_start_frame , " / ", (XNum_points*YNum_points) + time.sleep(0.001) + Save_Scan_Data() + GE_start_frame = GE_start_frame+1 + +#Save_Scan_Data() +#Save_Scan_Data() +#******** Saving Pos Scan data ******** +Save_Pos_Scan_Data() + +#******** Post Scan ******** +print("Scan Finished: " + time.ctime()) + + diff --git a/script/test/TestNilson2.py b/script/test/TestNilson2.py new file mode 100644 index 0000000..7760869 --- /dev/null +++ b/script/test/TestNilson2.py @@ -0,0 +1,172 @@ +#features = {"compression" : "true", "shuffle": "false", "chunk":[1, 100, 200]} +features = {"compression" : True, "shuffle": False} +#features =None +FIXED = False +# Greateyes scan + + + +#******** SCAN Settings ******** +Note="DESY - " + +Exp_Time= 1 + +X0=4200 +Xstep=450 +XNum_points=10 + +Y0=5960 +Ystep=-40 +YNum_points=10 + +GE_ROI_Line = 3 + +GE_AreaDet = det + +GE_ROI_Image= det.getDataMatrix() +GE_Raw_Image= det.getDataMatrix() +GE_BG_Image = det.getDataMatrix() +GE_Spectrum_Conv = arr #det.getDataArray() +GE_Spectrum = arr #det.getDataArray() +GE_BG_Line = det.getArraySize2() +GE_BG_SizeX = det.getArraySize0() +GE_BG_SizeY = det.getArraySize1() +GE_ROI_Line = det.getArraySize2() +GE_ROI_SizeX = det.getArraySize0() +GE_ROI_SizeY = det.getArraySize1() +IZero_Profile = arr #det.getDataArray() +TFY_Profile = arr #det.getDataArray() +IZero=sin +TFY = sin +GE_Sensor_Temp = sin +GE_FrameID = sin +Press_Diag_PV= sin +Press_Spec_PV= sin +Press_Spec_HV =sin +Press_Sample_Ch=sin +Press_Diag_HV = sin +GE_Spectrum_Sum = det.getDataArray() +Sample_Horiz=motor +Sample_Vert=motor2 + +#******** Functions Definitions ******** +def Save_Pre_Scan_Data(): + save_dataset("RAW/GE_BG_Image", GE_BG_Image.read()) + save_dataset("Processed/GE_Spectrum_Convertion", GE_Spectrum_Conv.read()) + save_dataset("Detector/GE_ROI_Line", GE_ROI_Line.read()) + save_dataset("Detector/GE_ROI_SizeX", GE_ROI_SizeX.read()) + save_dataset("Detector/GE_ROI_SizeY", GE_ROI_SizeY.read()) + save_dataset("Detector/Exposure_Time", GE_AreaDet.getExposure()) + save_dataset("Detector/GE_Open_Delay", 1) + save_dataset("Detector/GE_Close_Delay", 1) + save_dataset("Detector/GE_Num_Images", GE_AreaDet.getNumImages()) + save_dataset("Detector/Gain_Type", 1) + save_dataset("Scan/Scan_Start_Time", time.ctime()) + save_dataset("Scan/Note", Note) + #save_dataset("Scan/Note", Note) + +def Create_Scan_Dataset(): + create_dataset("RAW/GE_Raw_Image", 'd', False, (Num_Images if FIXED else 0, int(GE_BG_SizeY.take()), int(GE_BG_SizeX.take())), features) + create_dataset("RAW/IZero_Profile", 'd', False, (Num_Images if FIXED else 0, 100)) + create_dataset("RAW/TFY_Profile", 'd', False, (Num_Images if FIXED else 0, 100)) + #create_dataset("Processed/GE_ROI_Image", 'd', False, (Num_Images if FIXED else 0Images, int(GE_ROI_SizeY.take()), int(GE_ROI_SizeX.take()))) + create_dataset("Processed/GE_Spectrum", 'd', False, (Num_Images if FIXED else 0, int(GE_BG_SizeX.take()))) + create_dataset("Processed/Izero", 'd', False) + create_dataset("Processed/TFY", 'd', False) + create_dataset("Detector/GE_Sensor_Temp", 'd', False) + create_dataset("Scan/GE_FrameID", 'i', False) + create_dataset("Scan/Timestamps", 'l', False) + create_dataset("Pressure/Diagnostic_PV", 'd', False) + create_dataset("Pressure/Diagnostic_HV", 'd', False) + create_dataset("Pressure/Spectrometer_PV", 'd', False) + create_dataset("Pressure/Spectrometer_HV", 'd', False) + create_dataset("Pressure/Sample_Chamber", 'd', False) + create_dataset("RAW/Xposition", 'd', False) + create_dataset("RAW/Yposition", 'd', False) + + + +def Save_Scan_Data(): + #sleep(0.2) + append_dataset("RAW/GE_Raw_Image", GE_Raw_Image.read()) + append_dataset("RAW/IZero_Profile", IZero_Profile.take()) + append_dataset("RAW/TFY_Profile", TFY_Profile.take()) + #append_dataset("Processed/GE_ROI_Image", GE_ROI_Image.read()) + append_dataset("Processed/GE_Spectrum", GE_Spectrum.take()) + append_dataset("Processed/Izero", IZero.take()) + append_dataset("Processed/TFY", TFY.take()) + append_dataset("Detector/GE_Sensor_Temp", GE_Sensor_Temp.take()) + append_dataset("Scan/GE_FrameID", GE_FrameID.take()) + append_dataset("Scan/Timestamps", GE_FrameID.getTimestampNanos()) + append_dataset("Pressure/Diagnostic_PV", Press_Diag_PV.take()) + append_dataset("Pressure/Diagnostic_HV", Press_Diag_HV.take()) + append_dataset("Pressure/Spectrometer_PV", Press_Spec_PV.take()) + append_dataset("Pressure/Spectrometer_HV", Press_Spec_HV.take()) + append_dataset("Pressure/Sample_Chamber", Press_Sample_Ch.take()) + #Scan_Progress = (100*calcprog(GE_FrameID.take(),GE_start_frame,Num_Images)) + +def Save_Pos_Scan_Data(): + sleep(1) + save_dataset("Processed/GE_Spectrum_Sum", GE_Spectrum_Sum.read()) + save_dataset("Scan/Scan_Finish_Time", time.ctime()) + +#******** Test limits on sample vertical and horizontal motor ******** +X0=float(X0) +Xstep=float(Xstep) +Y0=float(Y0) +Ystep=float(Ystep) + +X1=X0+(XNum_points*Xstep) +Y1=Y0+(YNum_points*Ystep) +Num_Images= XNum_points*YNum_points + +#******** Setting up Caenels ******** +values_p_reading=1000*Exp_Time +Scan_Progress = 1 + +############### Scan ############### + +create_dataset("RAW/GE_Raw_Image2", 'd', False, (Num_Images if FIXED else 0, int(GE_BG_SizeY.take()), int(GE_BG_SizeX.take())), features) + + + + +Save_Pre_Scan_Data() + +#******** Pre Scan Setup ******** +print("Scan starting: " + time.ctime()) +GE_start_frame =1 +Create_Scan_Dataset() + +#Sample_Horiz.move(X0) + + +#******** Main Scan Function ******** +#XNum_points, YNum_points 3, 4 +X0, Y0, Xstep, Ystep = 0, 0, 0.1, 0.1 + +for j in range(XNum_points): + #Sample_Horiz.move(X0+(j*Xstep)) + for i in range(YNum_points): + #Sample_Vert.move(Y0+(i*Ystep)) + print GE_start_frame , " / ", (XNum_points*YNum_points) + time.sleep(0.001) + Save_Scan_Data() + GE_start_frame = GE_start_frame+1 + + +""" +def after(record, scan): + Save_Scan_Data() + +ascan((Sample_Horiz, Sample_Vert), (GE_Raw_Image), (X0, Y0), (X1, Y1), (Xstep, Ystep), after_read = after) +""" +#Save_Scan_Data() +#Save_Scan_Data() +#******** Saving Pos Scan data ******** +Save_Pos_Scan_Data() + +#******** Post Scan ******** +print("Scan Finished: " + time.ctime()) + + diff --git a/script/test/TestNilson3.py b/script/test/TestNilson3.py new file mode 100644 index 0000000..bc80758 --- /dev/null +++ b/script/test/TestNilson3.py @@ -0,0 +1,23 @@ +features = None +size = 5 +typ = 'd' +features = {"compression" : True, "shuffle": True} + +#features = {"layout" : "chunked", "chunk_size":[1, 500, 1000]} + + +create_dataset("group/contiguous", typ, False, (size, 1000, 1000), features) +create_dataset("group/chunked", typ, False, (0, 1000, 1000), features) + + + + +for i in range(size): + data = [ [int(i)] * 1000, ] * 1000 + #data = Convert.flatten(to_array(data, typ)) + append_dataset("group/chunked", data ) + append_dataset("group/contiguous", data) + + + + diff --git a/script/test/TestPID.py b/script/test/TestPID.py new file mode 100644 index 0000000..2aa11ae --- /dev/null +++ b/script/test/TestPID.py @@ -0,0 +1,17 @@ + +PID = get_context().getClassByName("PID") + + + +pid=PID(1,1,1); + + +while True: + sensor = sin.read() + target = 30.0 + #set some sort of target value + output=pid.getOutput(sensor,target); + print output + #do something with the output + inp.write(output) + time.sleep(1.0) diff --git a/script/test/TestPlotLayout.py b/script/test/TestPlotLayout.py new file mode 100644 index 0000000..28c529a --- /dev/null +++ b/script/test/TestPlotLayout.py @@ -0,0 +1,5 @@ +tscan([out, inp, sin, arr], 10, 0.1) +set_exec_pars(plot_layout = "Grid") +tscan([out, inp, sin, arr], 10, 0.1, plot_layout = "Grid") +set_exec_pars(defaults=True) +tscan([out, inp, sin, arr], 10, 0.1) \ No newline at end of file diff --git a/script/test/TestThen.py b/script/test/TestThen.py new file mode 100644 index 0000000..450148f --- /dev/null +++ b/script/test/TestThen.py @@ -0,0 +1,2 @@ +lscan(inp, sin, 0, 10, 0.1) +set_exec_pars(then="lscan(inp, sin, 0, 10, 0.2)") \ No newline at end of file diff --git a/script/test/TestTiff.py b/script/test/TestTiff.py new file mode 100644 index 0000000..b043ee7 --- /dev/null +++ b/script/test/TestTiff.py @@ -0,0 +1,143 @@ +from ijutils import * + + +#Image Loading +ip = load_image("/Users/gobbo_a/dev/pshell/config/home/images/img.tiff", title="Image") + +#Basic image manipulation: creation, copying, padding, saving +resized = resize(ip, 300,300) +save_image(resized, get_context().setup.expandPath("{images}/resized.tiff") ,"tiff") +crop=sub_image(ip,10,20,50,30) +bin_im = binning(ip,2) +new_im = new_image(256, 256, "color") +copy_image_to(bin_im, new_im, 20, 20) +pad_im = pad_image(ip, 1, 2, 3, 4, Color.RED) +stack=create_stack([ip,resized,crop, bin_im, new_im, pad_im], title = "Basic Functions") +save_image(stack, get_context().setup.expandPath("{images}/stack.tiff") ,"tiff") +stack.show() + + +#Decomposing color channels + +create_stack([ get_channel(ip, "red"), + get_channel(ip, "green"), + get_channel(ip, "blue"), + get_channel(ip, "alpha"), + grayscale(get_channel(ip, "brightness"), False)], title = "Color Decomposition").show() + + +#Basic functions (in_place) +aux = ip.duplicate() +aux.show() +grayscale(aux) +gaussian_blur(aux); aux.repaintWindow() +invert(aux); aux.repaintWindow() +smooth(aux); aux.repaintWindow() +sharpen(aux); aux.repaintWindow() +noise(aux, 100); aux.repaintWindow() + + +#Changing LUT +aux = ip.duplicate() +aux = grayscale(aux, in_place=False) +r,g,b = [],[],[] +for i in range(256): + r.append(0) + g.append(0) + b.append(i) +set_lut(aux, r, g, b) +aux.show() + + +#Histogram +plot(get_histogram(ip)) + + +aux = grayscale(ip, in_place = False) +bin = ip.duplicate() +ip_bin = auto_threshold(aux, in_place=False) +create_stack([ ip_bin, + binary_fill_holes(ip_bin, in_place=False), + binary_outline(ip_bin, in_place=False), + binary_outline(binary_fill_holes(ip_bin, in_place=False)), + binary_dilate(ip_bin, in_place=False), + binary_erode(ip_bin, in_place=False), + binary_open(ip_bin, in_place=False), + binary_close(ip_bin, in_place=False), + binary_skeletonize(ip_bin, in_place=False)], title = "Binarization").show() + + +#EDM, const & image operations +aux = grayscale(ip, in_place = False) +ip_bin = auto_threshold(aux, in_place=False) +binary_fill_holes(ip_bin) + +edm = edm(ip_bin, in_place=False) +ws = watershed(ip_bin, in_place=False) +up = ultimate_points(ip_bin, in_place=False) +vr = veronoi(ip_bin, in_place=False) +edm_disp = remap(edm, in_place=False) +ws_disp = grayscale(ws, False) +up_disp = enhance_contrast(up, in_place=False) +vr_disp = enhance_contrast(vr, in_place=False) +create_stack([edm_disp, aux, ip_bin, ws_disp, up_disp, vr_disp], title = "EDM Operations").show() +final = grayscale(ip_bin, in_place = False) +op_const(final,"add", -200) +op_image(final, vr_disp, 'or') +op_image(final, up_disp, 'or') +final.show() + +aux = grayscale(ip, in_place = False) + +create_stack([ aux, + subtract_background(aux, in_place=False), + smooth(aux, False), + sharpen(aux, False), + edges(aux, False), + bandpass_filter(aux,0, 5, in_place=False), + bandpass_filter(aux,5, 100, in_place=False), + op_const(aux,"and", 127, False), + convolve(aux, KERNEL_BLUR, False), + convolve(aux, KERNEL_SHARPEN, False), + convolve(aux, KERNEL_SHARPEN_2, False), + convolve(aux, KERNEL_LIGHT, False), + convolve(aux, KERNEL_DARK, False), + convolve(aux, KERNEL_EDGE_DETECT, False), + convolve(aux, KERNEL_EDGE_DETECT_2, False), + convolve(aux, KERNEL_DIFFERENTIAL_EDGE_DETECT, False), + convolve(aux, KERNEL_PREWITT, False), + convolve(aux, KERNEL_SOBEL, False) + ], title = "General Operations").show() + + +#Rank operators +rank_opers = [] +for op in "mean", "min", "max", "variance", "median", "close_maxima", "open_maxima", "remove_outliers", "remove_nan", "despeckle": + rank_opers.append(op_rank(aux,op, in_place=False, kernel_radius=1)) +create_stack(rank_opers, title = "Rank Operations").show() + + +#Reslicing +#orig = load_image("{data}/img/img2.png") +orig = resize(ip, 300,200) +grayscale(orig) +images=[] +for i in range (20): + images.append(orig.duplicate()) + op_const(orig, "multiply", 0.9) +stack=create_stack(images, title = "Original Stack") +#stack.show() +r1 = reslice(stack, start_at="Left", title="Reslice Horizontally") +r2 = reslice(stack, start_at="Top", title="Reslice Vertically") +r1.show() +r2.show() + + +#Particle Analysis +aux = grayscale(ip, in_place = False) +auto_threshold(aux) +#binary_fill_holes(aux) +#aux.show() +(results,output_img)=analyse_particles(aux, 100,1000, print_table=True) +output_img.show() + diff --git a/script/test/TestTypes.py b/script/test/TestTypes.py new file mode 100644 index 0000000..90dabad --- /dev/null +++ b/script/test/TestTypes.py @@ -0,0 +1,31 @@ +class StringDev(ReadonlyRegisterBase, Readable.StringType): + def doRead(self): + time.sleep(0.001) + return str(time.time()) + +class BoolDevS(ReadonlyRegisterBase): + def doRead(self): + return (int(time.time()) %2) == 0 + +class BoolDev(ReadonlyRegisterBase, Readable.BooleanType): + def doRead(self): + return (int(time.time()) %2) == 0 + +class ImageDev(ReadonlyRegisterBase, ReadonlyRegisterMatrix, Readable.IntegerType): + def doRead(self): + return mt1.read() + + def getWidth(self): + return mt1.width + + def getHeight(self): + return mt1.height + + + +add_device(StringDev(), True) +add_device(BoolDev(), True) +add_device(BoolDevS(), True) +add_device(ImageDev(), True) + +tscan((StringDev, BoolDev, BoolDevS, sin, arr, arr1, mt, mt1, cm1, ImageDev), 10, 0.1, compression =ImageDev) \ No newline at end of file diff --git a/script/test/test_multipass.py b/script/test/test_multipass.py new file mode 100644 index 0000000..ce02cf6 --- /dev/null +++ b/script/test/test_multipass.py @@ -0,0 +1,55 @@ +def set_energy(v): + motor.move(v) +energy_setpoint = motor +energy = motor.getReadback() +set_device_alias(energy, "energy") + + +START, STOP, STEP = 0, 40, 2 +ENERGIES = [0.0, 0.5, 0.25] +sensors = (sin,out, energy) + + + +#def before_pass(pass_num): +# set_energy(ENERGIES[pass_num-1]) +#ret= lscan(inp, sensors, START, STOP, STEP, 0.2, passes = len(ENERGIES), before_pass = before_pass, latency = 0.5) + + +#positions = frange(START, STOP, STEP , True) +#vector = [[pos, en] for en in ENERGIES for pos in positions] +#ret = vscan((inp,energy_setpoint), sensors, vector, line = True, latency = 0.5) + + +""" +plots = plot([None]*len(sensors), name = [d.name for d in sensors]) +for p in plots: p.clear() +def AfterReadout(record, scan): + if record.setpoints[1] == scan.getStart()[1]: + for p in plots: p.addSeries(LinePlotSeries(str(record.positions[0]))) + for i in range(len(plots)): + plots[i].getSeries(plots[i].numberOfSeries-1).appendData(record.positions[1], record.values[i]) + +class EnergyIndex("Writable): + def write(self, value): + if not hasattr(self, 'setpoint') or self.setpoint != value: + self.setpoint = value + set_energy(ENERGIES[int(value)]) + +positions = frange(START, STOP, STEP , True) +ret = ascan([EnergyIndex(), inp], sensors, (0,START), (len(ENERGIES)-1,STOP), (1.0,STEP), latency = 0.1, after_read=AfterReadout, plot_disabled=True) +""" + +plots = plot([None]*len(sensors), name = [d.name for d in sensors]) +for p in plots: + p.clear() + p.legendVisible = True +def after_readout(record, scan): + for i in range(len(plots)): + plots[i].getSeries(plots[i].numberOfSeries-1).appendData(record.positions[0], record.values[i]) +def before_pass(pass_num): + en = ENERGIES[pass_num-1] + set_energy(en) + for p in plots: p.addSeries(LinePlotSeries(str(en))) + +ret= lscan(inp, sensors, START, STOP, STEP, latency = 0.2, passes = len(ENERGIES), before_pass = before_pass, after_read=after_readout, plot_disabled=True)