See attached delivery note ...
* EDT PCIe4 DV frame grabber: installation notes for linux system
Main issue I encountered was the fact that most of the shell scripts
did not run by simply entering them. It's bit strange because if you
do ls -al to view the file lists they are made executable. So it's
possible that others don't encounter the same kind of problems as I
However, if one executes the command "./linux.go", for example, and
receives the message saying
bash: ./linux.go: /bin/sh: bad interpreter: Permission denied
then one may follow the steps I took as below.
1. Make a folder to put the content of CD, for example:
2. Copy the content of the CD-ROM to the folder.
3. Go to the folder.
4. Change or check the mode of the following script files (using the
command chmod) to be executable (using "chmod a+x filename"):
~/fgdriver/linux/EDTpdv/installpdv (this one should already be
5. run ./linux.go and choose DV by clicking it.
I am assuming that the programming language Tcl is already installed
in the machine. CentOS 5.4 that I have installed came with Tcl. If Tcl
is not installed, I think that linux.go will run cli_startmenu.sh
instead (located in the same directory as linux.go). So make sure
cli_startmenu.sh is executable (see step 4).
6. Choose default installation directory and start installation
In my first attempt to install the files, the installation message
window hung after displaying many lines of "........". That was
because the file setup.sh was not made executable (see step 4). So I
made setup.sh executable, ran linux.go again, then I could see further
messages flowing through (basically compiling c source files). I'm not
sure whether others will enounter the exactly same problem though.
7. After the installation completes, go to the /opt/EDTpdv folder.
8. Final Step: Make edt_load and edt_unload executable. (See step 4)
Most of the other executables we need for running the frame
grabber/camera should already be executable at this point; but somehow
in my installation the above two files were not made executable. I
again do not know whether others will experience the same
problem. Since there are lots of executables generated when
installation completes, I advise that, whenever a certain command does
not run, one should check if that command file is executable or not.
Please let me know if you find any parts of the above confusing. I will
do my best to clarify.
Given that the HWS requires several 2" optics to handle the big beam size, I've ordered the following items from Newport:
Attached is .m file of the custom function that I wrote and used to automatically detect peaks in a Hartmann image,
and calculate the centroid corrdinates of each of those peaks.
A simple example of its usage, provided that myimage is a two-dimensional image array obtained from the camera, is
radius = 10;
peak_positions = detect_peaks_uml(myimage,radius);
no_of_peaks = length(peak_positions);
centroids_array = zeros(no_of_peaks);
for k = 1:no_of_peaks
centroids_array(k,1) = peak_positions(k).WeightedCentroid(1);
centroids_array(k,2) = peak_positions(k).WeightedCentroid(2);
I chose my value of radius by looking at spots in a sample image and counting the number of pixels across a peak. It may be
more useful to automatically obtain a value for the radius. I may run some tests to see how different choices of radius
affect the centroid calculations.
I may also need to add some error checking and/or image validating codes, but so far I have not encountered any problems.
Please let me know if anyone needs more explanation!
This looks really efficient! However, I think there's a systematic error in the calculation. I tested it on some simulated data and it had trouble getting the centroids exactly right. I need to better understand the functions that are called to get an idea of what might be the problem.
Attached is .m file of the custom function that I wrote and used to automatically detect peaks in a Hartmann image,
and calculate the centroid corrdinates of each of those peaks.
I chose my value of radius by looking at spots in a sample image and counting the number of pixels across a peak. It may be
more useful to automatically obtain a value for the radius. I may run some tests to see how different choices of radius
affect the centroid calculations.
Despite some considerable time spent, I was not able to get the Omega SCR controllers working. The first unit definitely arrived damaged. None of its LED indicator lights ever functioned, despite those on the second controller working fine under the same setup. I tried swapping in the second controller, but it has no voltage output and a red LED is illuminated which, according to the manual, means "malfunction on trigger board" or "open SCR." Either way, the remedy is to "consult factory."
Since we have get moving with data collection, I installed a simple variable transformer (borrowed from the 40m) which steps up/down the AC voltage from 0-120 V with the turn of a knob. I soldered the leads of one of the heaters to a standard power cable which plugs directly into the transformer. I have tested it and confirmed it to work.
I analyzed the results from the prism experiment. The time series and spectra of the prism are attached.
Conclusions to follow ...
I've set up a quick experiment to modulate the angle of the Hartmann sensor probe beam at 10mHz and to monitor the measured prism. The beam from the SLED is collimated by a lens and this is incident on a galvo mirror. The reflection travels around 19" and is incident on the HWS. When the galvo mirror is sent a 1.1Vpp sine wave, then beam moves around +/- 0.5" on the surface of the Hartmann sensor, giving around 50mrad per Vpp.
The galvo is currently being sent a 0.02Vpp sine wave at 10mHz.
I changed the drive amplitude on the function generator to 0.05Vpp and have measured the angle of deflection by bouncing a laser off the laser mirror and projecting it 5.23m onto the wall. The total displacement of the spot was ~3.3mm +/- 0.4mm, so the amplitude of the angular signal is 1.6mm/5.23m ~ 3.1E-4 radians. The Hartmann Sensor should measure a prism of corresponding magnitude.
The frequency is still 10mHz.
I wrote a Python script, ~/scripts/dalsa_to_epics.py that reads the temperature off the camera using serial_cmd vt and then it writes this to the EPICS channels using ezcawrite. See attached. It is now running continuously in the background as dalsa_to_epics.
Dalsa1M60 baud rate
Also I accessed the menu of the 1M60 and changed the baud rate to 115200 using sbr 115200. Then I edited the dalsa_1m60.cfg file to set the baud rate to 115200 in that file. Finally, I changed the settings on the camera so that it will boot with the new baud rate when it is turned off and on again - this was with wus in the camera menu.
All the files are attached.
I ran a test of the HWS with the QFLD-950-3S for 5 days. The test was terminated as we need to disconnect all the cabling and tidy up all the computers in the lab.
I've started building the NFS server for the QIL cymac. It's sitting on the workbench in the TCS lab next to the rack. Please don't move it or any of the parts behind it.
dV = 0.385V
Transimpedance = 1.5E4 V/A
therefore power= 0.385V / (1.5E4 * 0.65 V/W) = 40uW
The 400 mW CO2 laser on the Hartmann table is currently configured for a measurement of its relative intensity noise. It is aligned to a TCS CO2P photodetector powered by a dual DC power supply beside the light enclosure. I got some data last night with the laser current dialed back for low output power (0.5-10 mW incident), but still need to analyze it. In the meantime please don't remove parts from the setup, as I may need to repeat the measurement with better power control.
Attached for reference is the RIN measurement from the initial data.
We set up the Hartmann sensor and illuminated it with the output from the fiber-coupled SLED placed about 1m away. The whole arrangement was covered with a box to block out ambient light. The exposure time on the Hartmann sensor was adjusted so that the maximum number of counts in a pixel was about 95% of the saturation level.
We recorded a set of 5000 images to file and analyzed them using the Caltech and Adelaide centroiding codes. The results are shown below. Basically, we see the same deviation from ideal improvement that is observed at Adelaide.
Time was still off by nine days as of yesterday. I tried rebooting remotely to see if time would correct to system clock. It didn't and fb4 hung.
Just manually restarted the box. Now dataviewer is showing a 'Time Now' of 5 Jan 1980.
Not sure how to set the frame builder clock time. Ultimately the best solution is to have ADC cards but can we find a hack for now? Is it possible to run a cron script it to reset time to the computer time?
The framebuilder on FB4 thinks the current time is 26-Jan-2018 6:18AM UTC. The date command on FB4 yields the correct date and time (5-Feb-2018 15:17 PST).
There is a major error with the framebuilder clock.
Yesterday, we were able to take some data using the 120 V DC power supply. The reflectors cut at the focal point and radius were both tested; the semi-circle cut proved to give a better focus, likely because roughly half the heat is lost using the focal-point reflectors. For upcoming tests, the semicircle reflectors will be used. We varied the surface shine by using the dull and reflective side of Al foil, as well as using the machined Al itself. The best result was given by using the more reflective side of Al foil.
Figure 1 shows the steady-state surface deformation profile detected by the HWS. The heaters don't have a uniform distribution along the wire, so more heat is radiated in the center of it, thus more of it is being focused to the center of the test optic. The data needs to be analyzed to determine the radius of the focus. Our rough estimate is about ~1.5 - 2 cm. We cannot collect any more data until we get a new power supply (AC 120 V).
Today, I came up with a new design for mounting the reflectors. I used a big 3-axis stage and a small 4-axis stage. This provides 5 degrees of freedom: 3 translational and 2 rotational, which is what we need for fine-tuning the focus and directing it at different angles incident to the test optic. The only problem with this design is that the 3-axis stage is too tall for the box, so the lid won't close.There is a smaller one available, but I have to figure out a way to increase its height, since the screw size is different from the ones on the pedestals available.
Additionally, Chub used metal-to-metal epoxy to glue a screw to the back of a reflector. I will wait until tomorrow to test it, because it is a slow acting epoxy. If it works, I have the necessary tools to do the same with the other reflectors. With the current deisgn the reflector wil be screwed in to where the round screw is in the stage. If it heats up a lot and affects the material of the stages, a small optical post (top of stage) will be used to make up for the absorbed heat.
I removed the cooling fins from the Hartmann sensor to see what steady-state temperature it reached without any passive cooling elements. I also dropped the set-point temperature for the lab to help keep for getting too hot.
After nearly 3 hours the temperature is:
(Digitizer: 54.3C, Sensor: 46.6C, Ambient: 19.6C)
I just replaced the brass Hartmann plate with the Invar one. The camera was off during the process but has been turned on again. The camera is now warming up again. I've manually set the temperature in the EPICS channels by looking at the on-board temperature via the serial communications.
I also made sure the front plate was secured tightly.
I replaced the dead 24" monitor on the work bench, which is connected to the video multiplexer. Mike Pedraza was kind enough to bring us us a new one and take away the old one.
hartmann had started responding to requests to log-in with the a request to change the password. Attempts to change the password proved unsuccessful. I tried to access the machine locally to change the password but I couldn't the display started, so I had to reboot it.
Restarted the HWS EPICS channels on hartmann with the following command:
/cvs/opt/epics-3.14.10-RC2-i386/base/bin/linux-x86/softIoc -S HWS.cmd &
9:40PM PDT - I've just restarted the long term measurement of the Hartmann sensor noise with the QFLD-950-3S.
Hideously slow internet at airport is making me write a brief entry. This is the times series of the hesilver watlow heater radiative response to a step function.
Laso United airlines are a bit cheap ....
I've been looking to see what the time constant of the ring heater is. The attached plot shows the voltage measured by the photodiode in response to the heater turning on and off with a period of 30 minutes.
The time constant looks to be on the order of 600s.
After leaving the ring heater off for several hours I turned on a 40V, 0.2A supply at a gps time of 949 988 700
The channel recording the PD response is C2:ATF-TCS_PD_HGCDTE_OUT.
However, there is a delay between the time at which something is supposed to be recorded and the time at which it is recorded. I looked at the GPS clock and it read that time when I started the heater voltage. If you play the channel back in dataviewer you see the temperature start to increase around 80s BEFORE the heater current was switched on. This needs to be calibrated away!!!
I applied a step function to the silver WATLOW heater and measured the response with the photodiode. The power spectrum of the derivative of the PD response is attached. The voltage isn't calibrated, but that's okay because right now we're just interested in the shape of the transfer function. It looks like a single pole around 850uHz. The noise floor is too great above 4 or 5 mHz to say anything about the transfer function.
I mounted the thinner Aluminium Watlow heater inside a 14" long, 1" inner diameter cylinder. The inner surface was lined with Aluminium foil to provide a very low emissivity surface and scatter a lot of radiation out of the end. ZEMAX simulations show this could increase the flux on a PD by 60-100x.
There was 40V across the heater and around 0.21A being drawn. The #9005 HgCdTe photo-detector was placed at one end of the cylinder to measure the far-IR. (Bear in mind this is a 1mmx1mm detector in an open aperture of approximately 490 mm^2), The measured voltage difference between OFF and the steady-state ON solution, after a 5000x gain stage, was around 270mV. This corresponds to 0.054mV at the photo-diode. Using the responsivity of the PD ~= 0.05V/W then this corresponds to about 10mW incident on the PD.
I've been trying to measure the ring heater transfer function (current to emitted power) by sweeping the supply voltage and measuring the emitted power with a photodector positioned right next to the ring heater.
Last night the voltage was sweeping with a 1000mV setting on the SR785 which was fed into the Voltage Control of the Kepco Bipolar Operational Power Supply/Amplifier which was biased around 10V.
The results are very, very strange. The magnitude of the transfer function decreases at lower frequency. I'll post the data just as soon as I can (ASCII dumps 13 and 14 on the disk from the SR785).
The circuit looks like this:
SR785 drive ----> Amplifier ----> Ring Heater : Photodetector ---> SR560 (5000x gain) ----> SR785 input
This is wrong. It turns out the SR785 was wired up incorrectly.
I implemented an access point for LDAS to pull data from the TCS lab EPICS frame archive (fb4:/frames) via rsync. The setup is analogous to what is already running at the 40m for automated backups. Here are the implementation details in case we want to replicate this in other W. Bridge labs.
Two lab machines are needed, the frame builder machine (fb4; 10.0.1.156) and a second machine to handle the network interfacing with the outside world (tcs-ws; 10.0.1.168).
1. Set up an NFS mount on tcs-ws to remotely access the frame archive on fb4.
i. NFS server-side setup:
a. Install the required packages
controls@fb4:~$ sudo apt-get install rpcbind nfs-common nfs-kernel-server
b. Add the following line to the file /etc/exports
c. Restart the NFS-related services
controls@fb4:~$ sudo /etc/init.d/rpcbind restart
controls@fb4:~$ sudo /etc/init.d/nfs-common restart
controls@fb4:~$ sudo /etc/init.d/nfs-kernel-server restart
ii. NFS client-side setup:
controls@tcs-ws:~$ sudo apt-get install rpcbind nfs-common
b. Add the following line to the file /etc/fstab
10.0.1.156:/frames /fb4/frames nfs rw,nofail,sync,hard,intr 0 0
c. Create the directory for the mount point, then set ownership and permissions
controls@tcs-ws:~$ sudo mkdir /fb4/frames
controls@tcs-ws:~$ sudo chmod -R 775 /fb4
controls@tcs-ws:~$ sudo chown -R controls.root /fb4
c. Mount the new network drive
controls@tcs-ws:~$ sudo mount -a
2. Configure the rsync daemon on tcs-ws.
i. Create a new file named /etc/rsyncd.conf with the following content. These settings match those of the 40m setup.
max connections = 10
read only = yes
log file = /var/tmp/rsyncd.log
list = yes
uid = controls
gid = controls
use chroot = yes
strict modes = yes
pid file = /var/run/rsyncd.pid
comment = For LDAS access to TCS lab frame files
read only = yes
path = /fb4/frames
hosts allow = ldas-grid.ligo.caltech.edu,localhost
ii. Kill, then restart the rsync daemon. The daemon may not be already running.
controls@tcs-ws:~$ sudo kill `cat /var/run/rsyncd.pid`
controls@tcs-ws:~$ sudo rsync --daemon
3. Open a port through the gateway firewall for LDAS to access.
To do this, configure a new port forwarding on the linksys gateway router in the usual way (access the router settings via http://10.0.1.1 from the web browser of any subnet machine). For the TCS lab, the external-facing gateway port 2046 is forwarded to port 873 of tcs-ws (the standard rsync port).
Security is handled by the tcs-ws rsync daemon. Its config file allows outside access to only the hostname ldas-grid.ligo.caltech.edu, and that access is read-only and restricted to the /fb4/frames directory.
For testing purposes, another outside machine name can be temporarily appended to the "hosts allow" parameter of /etc/rsyncd.conf. For example, I appended my office desktop machine. From the outside machine, the connectability of the rsync server can be tested with:
user@outside-hostname:~$rsync -dt rsync://22.214.171.124:2046/ldasaccess
If successful, the command will return an output similar to
drwxr-xr-x 4096 2017/08/28 16:13:31 .
drwxr-xr-x 4096 2017/11/14 02:30:38 full
drwxr-xr-x 4096 2017/08/28 16:13:38 trend
showing the contents of the frame archive.
After much effort trying to get a MATLAB routine to compile in C I discovered the following pieces of information.
1. CentOS will not install a gcc compiler more recent than 4.1.2 with yum install. This is circa 2007. If you want a more recent compiler it must be installed manually.
2. To compile and link C programs that call the MATLAB engine, they must be compiled in MATLAB using the mex command. Every version of MATLAB after R2008b requires the gcc compiler 4.2.3.
3. Building gcc 4.2.3 takes a lot more than 1 hour of compile time. I accidentally killed the build process and gave it up as a lost cause.
Here's a plot of the 15-day output of the SLED.
Currently there is an 980nm FC/APC fiber-optic patch-cord attached to the SLED. It occurred to me this morning that even though the patch cord is angle-cleaved, there may be some back-reflection than desired because the SLED output is 830nm (or thereabouts) while the patch cord is rated for 980nm.
I'm going to turn off the SLED until I get an 830nm patch-cord and try it then.
Correction: I removed the fiber-optic connector and put the plastic cap back on the SLED output. The mode over-lap (in terms of area) from the reflection off the cap with the output from the fiber is about 1 part in 1000. So even with 100% reflection, there is less than the 0.3% danger level coupled back into the fiber. The SLED is on again.
I turned off the SLED for 10s and reset the current set-point voltage (read using a mutlimeter and probing a couple of pins at the back of the driver board). The initial voltage when the test started on Monday was 0.111V when the SLED was engaged. This drooped to 0.109V over the week and there was a corresponding (but possible not resulting) drop in on-board photo-diode voltage. When the SLED was disengaged the set-point current control voltage dropped to 0.104V. I turned the LP pot on the front of the SLED driver board until the multimeter read 0.106V and re-engaged the SLED. The curernt set-point voltage then read 0.111V, occasionally popping up to 0.112V for a moment or two.
The DC Power Supply to the SLED reads 8.9V with 0.26A current being drawn.
Here's the data from the last 2 1/2 days of running the SLED. The decrease in photo-current measured by the on-board photo-detector is consistent with the decrease in the current set-point and the delivered current, but it is not clear why these should be changing.
Strictly speaking I should add some analysis that shows that delta_PD_voltage_measured = delta_I_set_measured * [delta_PD_voltage/delta_I_set (I_set)]_calculated ...
I've attached the Acceptance Test Report data from SUPERLUM for this SLED. I've also determined the expected percentage decrease in power/photo-current per mA drop in forward current.
The measured decrease in forward current over the last 2 1/2 days is around 1.4mA from around 111mA. The expected drop in power is thus (4.5% per mA)*(1.4mA) = 6.3%.
The drop in photo-current is around 37.5mA to 35mA = 2.5mA. The percentage drop is around 100*(2.5mA)/(36.3mA) = 6.9%.
Therefore, the drop in measured power is consistent with what we would expect given the decrease in forward current (which is consistent with the drop in the set point). Why the set-point is dropping is still a mystery.
Verified that the test-point for the current limit pot on the driver (Wavelength Electronics - LDTC 0520) was at 0.5V. Driver is set to INTERNAL set point at the moment. This is down about 10% below the current limited point.
Voltage across TP7 and TP9 = 0.970V = LD Current Mon
Voltage across TP2 and TP3 = 0.017V = LD P Mon
--- Hartmann sensor ---
-set the sampling rate on the CCD to 16HZ. With the current alignment and intensity this gives as maximum intensity of around 3850 out of 4095. Thus the pixels are not saturated.
- centroid_image located some of the spots - see attached image of spots where those located by the algorithm and circled. I need to play with the threshold level and spot_radius to get this to work properly.
For Wednesday, June 16:
For Thursday, June 17:
Today I attended a basic laser safety training orientation, the second Introduction to LIGO lecture, a Summer Research Student Safety Orientation, and an Orientation for Non-Students living on campus (lots of mandatory meetings today). I met with Dr. Willems and Dr. Brooks in the morning and went over some background information regarding the project, then in the afternoon I got an idea of where I should progress from here from talking with Dr. Brooks. I read over the paper "Adaptive thermal compensation of test masses in advanced LIGO" and the LIGO TCS Preliminary Design document, and did some further reading in the Brooks thesis.
I'm making a little bit of progress with accessing the Hartmann lab computer with Xming but got stuck, and hopefully will be able to sort that out in the morning and progress to where I want to be (I wasn't able to get much further than that, since I can't access the Hartmann computer in the lab currently due to laser authorization restrictions). I'm currently able to remotely open an X terminal on the server but wasn't able to figure out how to then be able to log in to the Hartmann computer. I can do it via SSH on that terminal, of course, but am having the same access restrictions that I was getting when I was logging in to the Hartmann computer via SSH directly from my laptop (i.e. I can log in to the Hartmann computer just fine, and access the camera and framegrabber programs, but for the vast majority of the stuff on there, including MATLAB, I don't have permissions for some reason and just get 'access denied'). I'm sure that somebody who actually knows something about this stuff will be able to point out the problem and point me in the right direction fairly quickly (I've never used SSH or the X Window system before, which is why it's taking me quite a while to do this, but it's a great learning experience so far at least).
Goals for tomorrow: get that all sorted out and learn how to be able to fully access the Hartmann computer remotely and run MATLAB off of it. Familiarize myself with the camera program. Set the camera into test pattern mode and use the 'take' programs to retrieve images from it. Familiarize myself with the 'take' programs a bit and the various options and settings of them and other framegrabber programs. Get MATLAB running and use fread to import the image data arrays I take with the proper data representation (uint16 for each array entry). Then, set the camera back to recording actual images, take those images from the framegrabber and save them, then import them into MATLAB. I should familiarize myself with the various settings of the camera at this stage, as well.
Today I spoke with Dr. Brooks and got a rough outline of what my experiment for the next few weeks will entail. I'll be getting more of the details and getting started a bit more, tomorrow, but today I had a more thorough look around the Hartmann lab and we set up a few things on the optical table. The OLED is now focused through a microscope to keep the beam from diverging quite as much before it hits the sensor, and the beam is roughly aligned to shine onto the Hartmann plate. The Hartmann images currently look like this (on a color scale of intensity):
Where this image was taken with the camera set to exposure time 650 microseconds, frequency 58Hz. The visible 'streaks' on the image are believed to possibly be an artifact of the camera's data acquisition process.
I tested to see whether the same 'flickering' is present in images under this setup.
For frequency kept at 58Hz, the following statistics were found from a 200x200 pixel box within series of 10 images taken at different exposure times. Note that the range on the plot has been reduced to the region near the relevant feature, and that this range is not being changed from image to image:
5000 microseconds. Note that the background level is approaching the level of the feature:
6000 microseconds. Note that the axis setup is not restricted to the same region, and that the background level exceeds the level range of the feature. This demonstrates that the 'feature' disappears from the plot when the plot does not include the specific range of ~115-130:
When images containing the feature intensities are averaged over a greater number of images, the plot takes on the following appearance (for a 200x200 box within a series of 100 images, 3000us exposure time):
This pattern changes a bit when averaged over more images. It looks as though this could, perhaps, just be the result of the decrease in the standard deviation of the standard deviations in each pixel resulting from the increased number of images being considered for each pixel (that is, the line being less 'spread out' in the y-axis direction).
To demonstrate that frequency doesn't have any effect, I got the following plots from images where I set the camera to different frequencies then set the exposure time to 3000us (I wouldn't expect this to have any effect, given the previous images, but these appear to demonstrate that the 'feature' does not vary with time):
Set to 30Hz:
Set to 1Hz:
To make sure that something weird wasn't going on with my algorithm, I did the following: I constructed a 10-component vector of random numbers. Then, I concatenated that vector besides itself ten times. Then, I concatenated that vector into a 3D array by scaling the 2D vector with ten different integer multiples, ensuring that the standard deviations of each row would be integer multiples of each other when the standard deviation was found along the direction of the random change (I chose the integer multiples to ensure that some of these values would fall within the range of 115-130). Thus, if my function wasn't making any weird mistakes, I would end up with a linear plot of standard deviation vs. mean, with a slope of 1. When the array was inputted into the function with which the previous plots were found, the output plot was indeed observed to be linear, and a least squares regression of the mean/deviation data confirmed that the slope was exactly 1 and the intercept exactly 0. So I'm pretty certain that the feature observed in these plots is not any sort of 'artifact' of the algorithm used to analyze the data (and all the functions are pretty simple, so I wouldn't expect it to be, but it doesn't hurt to double-check).
I would conjecture from all of this that the observed feature in the plots is the result of some property of the CCD array or other element of the camera. It does not appear to have any dependence on exposure time or to scale with the relative overall intensity of the plots, and, rather, seems to depend on the actual digital number read out by the camera. This would suggest to me, at first glance, that the behavior is not the result of a physical process having to do with the wavefront.
EDIT: Some late-night conjecturing: Consider the following,
I don't know how the specific analog-to-digital conversion onboard the camera works, but I got to thinking about ADCs. I assume, perhaps incorrectly, that it works on roughly the same idea as the Flash ADCs that I dealt with back in my Digital Electronics class -- that is, I don't know if it has the same structure (a linear resistor ladder hooked up to comparators which compare the ladder voltages to the analog input, then uses some comb logic circuit which inputs the comparator outputs and outputs a digital level) but I assume that it must, at some level, be comparing the analog input to a number of different voltage thresholds, considering the highest 'threshold' that the analog input exceeds, then outputting the digital level corresponding to that particular threshold voltage.
Now, consider if there was a problem with such an ADC such that one of the threshold voltages was either unstable or otherwise different than the desired value (for a Flash ADC, perhaps this could result from a problem with the comparator connected to that threshold level, for example). Say, for example, that the threshold voltage corresponding to the 128th level was too low. In that case, an analog input voltage which should be placed into the 127th level could, perhaps, trip the comparator for the 128th level, and the digital output would read 128 even when the analog input should have corresponded to 127.
So if such an ADC was reading a voltage (with some noise) near that threshold, what would happen? Say that the analog voltage corresponded to 126 and had noise equivalent to one digital level. It should, then, give readings of 125, 126 or 127. However, if the voltage threshold for the 128th level was off, it would bounce between 125, 126, 127 and 128 -- that is, it would appear to have a larger standard deviation than the analog voltage actually possessed.
Similarly, consider an analog input voltage corresponding to 128 with noise equivalent to one digital level. It should read out 127, 128 and 129, but with the lower-than-desired threshold for 128 it would perhaps read out only 128 and 129 -- that is, the standard deviation of the digital signal would be lower for points just above 128.
This is very similar to the sort of behavior that we're seeing!
Thinking about this further, I reasoned that if this was what the ADC in the camera was doing, then if we looked in the image arrays for instances of the digital levels 127 and 128, we would see too few instances of 127 and too many instances of 128 -- several of the analog levels which should correspond to 127 would be 'misread' as 128. So I went back to MATLAB and wrote a function to look through a 1024x1024xN array of N images and, for every integer between an inputted minimum level and maximum level, find the number of instances of that level in the images. Inputting an array of 20 Hartmann sensor images, along with minimum and maximum levels of 50 and 200, gave the following:
Look at that huge spike at 128! This is more complex of behavior than my simple idea which would result in 127 having "too few" values and 128 having "too many", but to me, this seems consistent with the hypothesis that the voltage threshold for the 128th digital level is too low and is thus giving false output readings of 128, and is also reducing the number of correct outputs for values just below 128. And assuming that I'm thinking about the workings of the ADC correctly, this is consistent with an increase in the standard deviation in the digital level for values with a mean just below 128 and a lower standard deviation for values with a mean just above 128, which is what we observe.
This is my current hypothesis for why we're seeing that feature in the plots. Let me know what you think, and if that seems reasonable.
So in addition to taking steps towards starting to set stuff up for the experiment in the lab, I spent a good deal of the day figuring out how to use the pre-existing code for finding the centroids in spot images. I spent quite a bit of time trying to use an outdated version of the code that didn't work for the actual captured images, and then once I was directed towards the right version I was hindered for a little while by a bug.
The 'bug' turns out to be something very simple, yet relatively subtle. In the function centroid_images.m in '/opt/EDTpdv/hartmann/src/', the function was assuming a threshold of 0 with my images, even though it has not long before been working with an image that Dr. Brooks loaded. Looking through the code, I noticed that before finding the threshold using the MATLAB function graythresh, several adjustments were made so as to subtract out the background and normalize the array. After estimating and subtracting a background, the function divides the entries of the image array by the maximum value in the image so as to normalize this. For arrays composed of numbers represented as doubles, this is fine. However, the function that I wrote to import my image arrays into MATLAB outputs an image array with integer data. So when the function divided my integer image arrays by the maximum values in the array, it rounded every value in the array to the nearest integer -- that is, the "normalized" array only contained ones and zeros. The function graythresh views this as a black and white image, and thus outputs a threshold of 0.
To remedy this, I edited centroid_images.m to convert the image array into an array of doubles near the very beginning of the function. The only new line is simply "image=double(image);", and I made a note of my edit in a comment above that line. The function started working for me after I did that.
I then wrote a function which automatically centroids an input image and then plots the centroids as scatter-plot of red circles over the image. For an image taken off of the Hartmann camera, it gave the following:
Zoomed in on the higher-intensity peaks, the centroids look good. They're a little offset, but that could just be an artifact of the plotting procedure; I can't say for certain either way. They all appear offset by the same amount, though:
One problem is that, for spots with a much lower relative intensity than the maximum intensity peak, the centroid appears to be offset:
Better centering of the beam and more even illumination of the Hartmann plate could mitigate this problem, perhaps.
I also wrote a function which inputs two image matrices and outputs vector field plots representing the shift in each centroid from the first to the second images. To demonstrate that I could use this function to display the shifting of the centroids from a change in the wavefront, I translated the fiber mount of the SLED in the direction of the optical axis by about 6 turns of the z-control knob (corresponding to a translation of about 1.9mm, according to the user's guide for the fiber aligner). This gave the following images:
Before the translation:
This led to a displacement of the centroids shown as follows:
Note that the magnitudes of the actual displacements are small, making the shift difficult to see. However, when we scale the displacement vectors up, we can get much more readily visible Direction vectors (having the same direction as the actual displacement vectors, but not the same magnitude):
This was a very rough sort of measurement, since exposure time, focus of the microscope optic, etc. were not adjusted, and the centroids are compared between single images rather than composite images, meaning that random noise could have quite an effect, especially for the lower-magnitude displacements. However, this plot appears to show the centroids 'spreading out', which is as expected for moving the SLED closer to the sensor along the optical axis.
The following MATLAB functions were written for this (both attached):
centroidplot.m -- calls centroid_image and plots the data
centroidcompare.m -- calls centroid_image twice for two inputs matrices, using the first matrix's centroid output structure as a reference for the second. Does a vector field plot from the displacements and reference positions in the second output centroids structure.
In order to conduct future optical experiments with the SLED and to be able to predict the behavior of the beam as it propagates across the table and through various optics, it is necessary to know the properties of the beam. The spot size, divergence angle, and radius of curvature are all of interest if we wish to be able to predict the pattern which should appear on the Hartmann sensor given a certain optical layout.
Mathematica was used to simplify this integral, and it showed it to be equivalent to:
where Erfc() is the complementary error function. Note that for fixed z, this intensity is a function only of xm. If an experiment was carried out to measure the intensity of the beam blocked by a plate from x=-inf to x=xm for multiple values of xm, it would therefore be possible via regression analysis to compute the best-fit values of A, w, and x0 for the measured values of Ipd and xm. This would give us A, w and x0 for that z-value. By repeating this process for multiple values of z, we could therefore find the behavior of these parameters as a function of z.
The razor blade was mounted on a New Focus 9091 Translational Stage, the relative displacement of which in the x-direction was measured with the Vernier micrometer mounted on the base. Tape was placed on the front of the razor so as to block light from passing through any of its holes. The portion of the beam not blocked by the razor then passed through a lens which was used to focus the beam back onto a PDA1001A Large Area Silicon Photodiode, the voltage output of which was monitored using a Fluke digital multimeter. The ruler stayed securely clamped onto the optical table (except when it was translated in the x-direction once during the experiment, as described later).
A MATLAB function 'gsbeam.m' was written to replicate the function:
(note that the width calculated from the 26th measurement is not included in the regression calculation or included on this plot. The width parameter was calculated as being exactly the same as it was for the 25th measurement, despite the other parameters varying between the measurements. I suspect that the beam size was starting to exceed the dimensions blocked by the razor and that this caused this problem, and that would be easy to check, but I have yet to do it. Regardless, the fit looks good from just the other 25 measurements)
In the previous log, I describe the direct measurement of the fiber output beam using the Hartmann sensor with the plate removed. In order to analyze how these properties might change as a function of time, we left the camera running over the holiday weekend, Dr. Brooks having written a bash script which took images from the sensor every 500 seconds. This morning I wrote a MATLAB script to automatically analyze all of these images and plot the fit parameters as a function of time (weekendbeamtime.m, attached). Note that the formatiing of a few of the following graphs was edited manually after being outputted by the program (just to note why the plots look different than the code might imply).
The following plots were made:
Amplitude as a function of time:
Amplitude again, focused in with more analysis:
Centroid Displacement (note the axis values, it's fairly zoomed in):
Note that these values were converted into radians by approximating the fiber-output/CCD distance and dividing this from the displacement in mm (after converting from pixels). This distance was approximated by assuming a divergence angle of 0.085 and a beam size of ~5.1mm (being a value inbetween the horizontal and vertical beam sizes calculated). This gave a value of ~60mm, which was confirmed as plausible by a quick examination in the lab.
In the first three plots, there are obvious temporary effects which seem to cause the values to fluctuate much more rapidly than they do for the rest of the duration. It is suspected that this could be related to temperature changes within the sensor as the camera begins taking images. Further investigation (tomorrow) will investigate these effects further, while collecting temperature data.
As I started setting up my next experiment, I noticed that the beam size from the SLED appeared to be larger than expected from previous analysis. It was therefore necessary to conduct further experiments to characterize the divergence angle of the beam.
First, I set up the photodetector attached to an SLED and mounted a razor blade on a translational stage, in the same manner as done previously. All of these components were the exact same ones used in the previous beam size experiment. The only differences in the components of the apparatus were as follows: first, the photodetector was placed considerably closer to the SLED source than was done previously. Second, a different lens was used to focus the light onto the photodetector. Lens LX082 from the lenskit was used, which is a one-inch lens of focal length f=50.20mm.
Experiment 1: Columnated Beam Size Measurement
Before repeating the previous experiment, the following experiment was done: the beam was columnated by placing the lens 50.20mm away from the source and then adjusting until columnation was observed. Columnation was confirmed by setting a mirror in the optical path of the beam directing it to the other side of the room. The position of the lens along the optical axis was adjusted until the beam exiting the lens did not change in size across the length of the table and appeared to be roughly the same size as the spot on the opposite side of the room (as gauged roughly by the apparent size on an IR card and through an IR viewer).
Then,the translational stage onto with the laser was mounted was placed after the lens against the ruler clamped to the table, and beam size was measured using the same experimental procedure used to find the width in the previous experiment. The only variation in the experimental procedure was that measurements were not taken strictly at 0.5V intervals; rather, intensity readings were taken for 28 different intensity outputs. The following measurements were collected:
When fit to gsbeam.m using lsqcurvefit, this yielded a width of 4.232mm. Since the beam is columnated through the lens, we know that it is approximately f=50.2mm from the source. Thus the divergence angle is approximately 0.084.
At this point, to double-check that the discrepency between this value and the previous experiment was not a result of a mistake in the function, I wrote a simpler function to go through the steps of using lsqcurvefit and plotting the fit curve versus the data automatically, 'manualbeam.m' (attached), which simply fits a curve to one set of data from a constant z-value. Using this one-by-one on each z-value in the previous experiment, it was shown that the slope of the widths was still ~0.05, so this discrepency was not the result of a mistake in the previous function somewhere.
Experiment 2: Blocked Beam Analysis 2
I then placed the razor before the lens in the beampath and repeated the previous experiment exactly. See the previous eLog for details on experimental procedure. Sets of measurements were taken at 6 different z-values, and widths were found using manualbeam.m in MATLAB. A curve of the calculated widths versus the z-position of the stage on the ruler is below:
Note that this appears to be consistant with the first experiment.
Experiment 3: Direct Beam Measurements on CCD
The front-plate of the Hartmann sensor was replaced with the new invar design (on a related note, the thread on the front plate needs a larger chamfer). In doing this, the Hartmann plate was removed. The sensor was moved much closer to the SLED along the optical axis, and an optical filter of OD 0.7 was screwed into the new frontplate. This setup allows for the direct imaging of the intensity of the beam, as shown below:
The spots and distortions on the image are from dust and other blemishes on the optical filter, as was confirmed by rotating the filter and observing the subsequent rotation of each feature.
Note that in some images, there may be a jump in intensity in the middle of the image. This is believed to be due to a inconsistant gain between the two sides of the image.
The means of the intensities of each row and each column will be Gaussian, and thus can be fit to a Gaussian using lsqcurvefit. Function 'gauss_beam1D.m' was written and this function was fit to using function 'autogaussfit1', which automatically imports the data from .raw files, fits Gaussians to the means of each row and column, and plots everything.
An example of the fit for the means of the columns of one image is as follows:
And for the rows:
Note that for all the fits, the fitting generally looks a little better along the row than along the column (which is true here, as well).
The following procedure was used to calculate the change of the beam width as a function of distance: the left edge of the base of the Hartmann sensor was measured against a ruler which was clamped to the table. The ruler position z was recorded. Then, preliminary images would be taken and the exposure time would be adjusted as needed. The exposure time was then noted. Then, an image was taken and curves were fit to it, and the width was calculated. This was done for 15 different positions of the Hartmann sensor along the optical axis.
The calculated widths vs. displacements plot from this can be seen below:
Note that the row width and column width are not the same, implying that the beam is not circularly symmetric and is thusly probably off alignment by a little bit. Also, the calculated slopes are different than the value of 0.085 acquired from the previous two measurements. Further investigation into the beam size and divergence angle is required to finally put this question to rest.
A quick write-up on recent work can be found at: Google Docs
I can't find a Tex interpreter or any other sort of equation editor on the eLog, is why I kept it on Google Docs for now instead of transferring it over.
[JC, Chub, Radhika]
Chub and I ordered a few parts from McMaster in order build a handrail-like stopper to keep the dewar from falling over. We also cut off the excess 8020 which was leaning over the table to fit. To hold down the support for the Dewar, Radhika and I decided to use C-clamps from the EE shop.
In anticipation of the point absorber SURF project, I cleaned up the server rack and installed a new workstation today.
The workstation replaces the old one, whose hard drive had failed, with a more powerful machine. The hostname (tcs-ws), IP address (10.0.1.168), user name (controls), and standard password (written in the secret place) are all the same as before.
I moved the control consol from its old spot in the back corner of the lab to the bench beside the rack. This is a more convenient location because the Hartmann sensor realtime GUIs can now be easily seen from the optical tables. I mounted the HWS machine in the rack as well and reconnected the video multiplexer to all the machines.
I tested the Hartmann sensor Python software and confirmed it to be working. It required a minor bug fix to the realtime gradient field GUI code. It seems that since this script was last run, the input data file type has switched from pickled numpy to HDF5.