Sample C. Software that interpolated around focus pixels (each 14-bits) in certain Canon cameras (EOS-M was what I was using).
// need for StructLayout
using int16_t = System.Int16;
using int32_t = System.Int32;
using int64_t = System.Int64;
using int8_t = System.Byte;
using pixelType = System.Byte;
using uint16_t = System.UInt16;
using uint32_t = System.UInt32;
using uint64_t = System.UInt64;
using uint8_t = System.Byte;
namespace FocusPixelFixer
{
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
/// <summary>
/// The raw helper.
/// </summary>
internal static class RAWHelper
{
#region Methods
/// <summary>
/// The read struct.
/// </summary>
/// <param name="buffer">
/// The buffer.
/// </param>
/// <typeparam name="T">
/// </typeparam>
/// <returns>
/// The <see cref="T"/>.
/// </returns>
internal static T ReadStruct<T>(this byte[] buffer) where T : struct
{
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
var result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return result;
}
#endregion
}
/// <summary>
/// The program.
/// </summary>
internal class Program
{
// STRUCTS OF RAW
// END STRUCTS FOR RAW
// private pixelType[, ,] RGBData = new pixelType[0, 0, 0]; // see above -> using pixelType = System.Byte;
#region Static Fields
/// <summary>
/// The bit reverse table.
/// </summary>
public static readonly byte[] BitReverseTable =
{
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50,
0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8,
0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04,
0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4,
0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c,
0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82,
0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32,
0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46,
0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6,
0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e,
0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71,
0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99,
0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25,
0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d,
0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3,
0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b,
0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb,
0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67,
0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f,
0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f,
0xbf, 0x7f, 0xff
};
#endregion
#region Public Methods and Operators
/// <summary>
/// The reverse with lookup table.
/// </summary>
/// <param name="toReverse">
/// The to reverse.
/// </param>
/// <returns>
/// The <see cref="byte"/>.
/// </returns>
public static byte ReverseWithLookupTable(byte toReverse)
{
return BitReverseTable[toReverse];
}
#endregion
// main
#region Methods
/// <summary>
/// The interpolate around focus pixels.
/// </summary>
/// <param name="ReaderSource">
/// The reader source.
/// </param>
/// <param name="WriterTarget">
/// The writer target.
/// </param>
/// <param name="iFrameCount">
/// The i frame count.
/// </param>
/// <param name="Footer">
/// The footer.
/// </param>
private static void InterpolateAroundFocusPixels(
BinaryReader ReaderSource,
BinaryWriter WriterTarget,
int iFrameCount,
raw_footer Footer)
{
// *************************
// LOOP THROUGH FRAMES
// *************************
Parallel.For(
1,
iFrameCount,
iFrameNumber =>
{
var PixelData = new ushort[Footer.yRes, Footer.xRes];
var FrameBuffer = new byte[Footer.frameSize];
/* read RAW block into byte[] array */
ReaderSource.BaseStream.Position = Footer.frameSize * iFrameNumber; // goto frame
ReaderSource.Read(FrameBuffer, 0, Footer.frameSize); // read into FrameBuffer
var framebytescopy = ProcessFrame(PixelData, FrameBuffer, Footer);
WriterTarget.BaseStream.Seek(Footer.frameSize * iFrameNumber, SeekOrigin.Begin);
WriterTarget.Write(framebytescopy);
Console.WriteLine("Processed frame " + iFrameNumber + " of " + iFrameCount);
});
Console.WriteLine("Done!");
}
/// <summary>
/// The main.
/// </summary>
/// <param name="args">
/// The args.
/// </param>
private static void Main(string[] args)
{
string FileNameNoDots = null;
if (args.Length <= 0)
{
return;
}
// Filename dropped onto exe
string FileName = args[0];
if (!File.Exists(FileName))
{
return;
}
FileNameNoDots = FileName.ToLower().Replace(".raw", "_fpfix.raw");
if (File.Exists(FileNameNoDots))
{
File.Delete(FileNameNoDots);
}
Console.WriteLine("Please wait, creating copy of RAW file");
Console.WriteLine("Copying to: " + FileNameNoDots + string.Empty);
File.Copy(FileName, FileNameNoDots);
// Assume we're okay at this point, so start converting!
// Open source File
BinaryReader ReaderSource;
ReaderSource = new BinaryReader(File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.Read));
// Open target File
var writeStream = File.OpenWrite(FileNameNoDots);
var WriterTarget = new BinaryWriter(writeStream);
// Get number of frames to process
/* file footer data, see g3gg0's MLV viewer for more sophistication */
raw_footer Footer;
var headerSize = Marshal.SizeOf(typeof(raw_footer)); // how much to read into "buf"
var buf = new byte[headerSize]; // will hold the footer data
ReaderSource.BaseStream.Position = ReaderSource.BaseStream.Length - headerSize; // get us to end of file before footer
var myread = ReaderSource.Read(buf, 0, headerSize); // no error checking here
Footer = RAWHelper.ReadStruct<raw_footer>(buf); // read binary data into our footer struct
ReaderSource.BaseStream.Position = 0; // go back to beginning of file
Console.WriteLine("Frame width: " + Footer.xRes + string.Empty);
Console.WriteLine("Frame height: " + Footer.yRes + string.Empty);
Console.WriteLine("Frame size: " + Footer.frameSize + string.Empty);
Console.WriteLine("Frame count: " + Footer.frameCount + string.Empty);
// ********************************
// Interpolate around Focus Pixels
// ********************************
InterpolateAroundFocusPixels(ReaderSource, WriterTarget, Footer.frameCount, Footer);
// Finish up
ReaderSource.Close();
WriterTarget.Close();
}
// main
/// <summary>
/// The process frame.
/// </summary>
/// <param name="PixelData">
/// The pixel data.
/// </param>
/// <param name="FrameBuffer">
/// The frame buffer.
/// </param>
/// <param name="Footer">
/// The footer.
/// </param>
/// <returns>
/// The <see cref="byte[]"/>.
/// </returns>
private static unsafe byte[] ProcessFrame(ushort[,] PixelData, byte[] FrameBuffer, raw_footer Footer)
{
var framebool = new bool[(Footer.xRes * Footer.yRes * 14)];
// From g3gg0's MLV project. Reads RAW frame into ushorts. I wrote
// different approach to write them back.
var pitch = (Footer.xRes * 14) / 8; // for example, 2,240 with a 1,280 width at 14bits width
var pos = 0; // Footer.frameSize* iFrameNumber;
fixed (byte* pSrc = FrameBuffer)
{
for (var y = 0; y < Footer.yRes; y++)
{
for (var x = 0; x < Footer.xRes; x++)
{
// dest[y, x] = BitExtract(pSrc, pos, x, bpp);
var value = 0;
var src_pos = x * 14 / 16;
var byteNum = pos + (2 * src_pos);
var bits_to_left = ((14 * x) - (16 * src_pos)) % 16;
var shift_right = 16 - 14 - bits_to_left;
value = (int)pSrc[byteNum] | (((int)pSrc[byteNum + 1]) << 8);
if (shift_right >= 0)
{
value >>= shift_right;
}
else
{
var val2 = (int)pSrc[byteNum + 2] | (((int)pSrc[byteNum + 3]) << 8);
value <<= -shift_right;
value |= val2 >> (16 + shift_right);
}
value &= (1 << 14) - 1;
PixelData[y, x] = (ushort)value;
}
pos += pitch; // advance pitch above, or 2,240 bits for 1280x720
}
}
ushort CPInterpolated = 0;
// Create BitArray from the array.
var framebits = new BitArray(framebool);
var xFocusDots = FocusDots.xFocusDots;
var LRNext = 2;
var TBNext = 2;
// *******************************************************
for (var p = 0; p < xFocusDots.Length / 2; p++)
{
var x = xFocusDots[p, 0];
var y = xFocusDots[p, 1];
if (x <= 2 || y <= 2)
{
continue;
}
// BOUNDS CHECKING!
// If we DO NOT have another line of those pixels, like from 720
// then we need to not look for it, and take current value
if (Footer.xRes - x < 3)
{
LRNext = 0;
}
if (Footer.yRes - y < 3)
{
TBNext = 0;
}
// Let's nail our suspect onto a cross of red pixels
var CP = (double)PixelData[y, x]; // Center pixel
var LP = (double)PixelData[y, x - LRNext]; // Left
var RP = (double)PixelData[y, x + LRNext]; // Right
var TP = (double)PixelData[y + TBNext, x]; // Top
var BP = (double)PixelData[y - TBNext, x]; // Bottom
var AvgLR = (LP + RP) / 2; // average left right
var AvgTB = (TP + BP) / 2; // average vertical
CPInterpolated = 0;
// If differs by more then 10% left right
if (Math.Abs((CP / AvgLR) - 1) > 0.05)
{
// Remember, we interpolate using the perpindicular line (top/bottom), assuminge this might be a line
CPInterpolated = (ushort)AvgTB;
}
// If differs by more then 10% left right
if (Math.Abs((CP / AvgTB) - 1) > 0.05)
{
// Perpindicular cross line
CPInterpolated = (ushort)AvgLR;
}
// If we don't have a vert or horizontal setting, make it an average of all
if (CPInterpolated == 0)
{
PixelData[y, x] = (ushort)((LP + RP + TP + BP) / 4.0);
}
// We found a distortion so blend in...
if (CPInterpolated > 0)
{
PixelData[y, x] = CPInterpolated;
}
}
// if x and y > 2
// We not have the frame adjusted through it's PixelData[,] representation
// So now let's write that to a copy of the frame
var frameBitCount = 0;
// Replace these bits with each of our 14 bit raw pixel values
for (var y = 0; y < Footer.yRes; y++)
{
for (var x = 0; x < Footer.xRes; x++)
{
for (var shift = 13; shift >= 0; shift--)
{
framebits[frameBitCount] = 1 == ((PixelData[y,x] >> shift) & 0x1);
frameBitCount++;
}
}
}
var size = framebits.Length / 8 + (framebits.Length % 8 == 0 ? 0 : 1);
// We now need to write all the bits of our frame into bytes
var framebytes = new byte[size];
framebits.CopyTo(framebytes, 0);
// Create copy, because we need to swap bytes
var framebytescopy = new byte[size];
for (var fc = 0; fc < framebytes.Length; fc = fc + 2)
{
framebytescopy[fc] = ReverseWithLookupTable(framebytes[fc + 1]);
framebytescopy[fc + 1] = ReverseWithLookupTable(framebytes[fc]);
}
return framebytescopy;
}
#endregion
/// <summary>
/// The raw_footer.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct raw_footer
{
/// <summary>
/// The magic.
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string magic;
/// <summary>
/// The x res.
/// </summary>
public short xRes;
/// <summary>
/// The y res.
/// </summary>
public short yRes;
/// <summary>
/// The frame size.
/// </summary>
public int frameSize;
/// <summary>
/// The frame count.
/// </summary>
public int frameCount;
/// <summary>
/// The frame skip.
/// </summary>
public int frameSkip;
/// <summary>
/// The source fpsx 1000.
/// </summary>
public int sourceFpsx1000;
/// <summary>
/// The reserved 3.
/// </summary>
public int reserved3;
/// <summary>
/// The reserved 4.
/// </summary>
public int reserved4;
/// <summary>
/// The raw_info.
/// </summary>
public raw_info_2 raw_info;
}
/// <summary>
/// The raw_info_2.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct raw_info_2
{
/// <summary>
/// The api_version.
/// </summary>
public int api_version; // increase this when changing the structure
/// <summary>
/// The buffer.
/// </summary>
public uint buffer; // points to image data
/// <summary>
/// The height.
/// </summary>
public int height;
/// <summary>
/// The width.
/// </summary>
public int width;
/// <summary>
/// The pitch.
/// </summary>
public int pitch;
/// <summary>
/// The frame_size.
/// </summary>
public int frame_size;
/// <summary>
/// The bits_per_pixel.
/// </summary>
public int bits_per_pixel; // 14
/// <summary>
/// The black_level.
/// </summary>
public int black_level; // autodetected
/// <summary>
/// The white_level.
/// </summary>
public int white_level; // somewhere around 13000 - 16000, varies with camera, settings etc
/// <summary>
/// The jpeg.
/// </summary>
public raw_info_crop2 jpeg;
/// <summary>
/// The active_area.
/// </summary>
public raw_info_active_area2 active_area;
/// <summary>
/// The exposure_bias.
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public int[] exposure_bias; // DNG Exposure Bias (idk what's that)
/// <summary>
/// The cfa_pattern.
/// </summary>
public int cfa_pattern; // stick to 0x02010100 (RGBG) if you can
/// <summary>
/// The calibration_illuminant 1.
/// </summary>
public int calibration_illuminant1;
/// <summary>
/// The color_matrix 1.
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)]
public int[] color_matrix1; // DNG Color Matrix
/// <summary>
/// The dynamic_range.
/// </summary>
public int dynamic_range; // EV x100, from analyzing black level and noise (very close to DxO)
}
/// <summary>
/// The raw_info_active_area 2.
/// </summary>
private struct raw_info_active_area2
{
#region Fields
/// <summary>
/// The x 1.
/// </summary>
public int x1;
/// <summary>
/// The x 2.
/// </summary>
public int x2;
/// <summary>
/// The y 1.
/// </summary>
public int y1;
/// <summary>
/// The y 2.
/// </summary>
public int y2;
#endregion
}
/// <summary>
/// The raw_info_crop 2.
/// </summary>
private struct raw_info_crop2
{
#region Fields
/// <summary>
/// The height.
/// </summary>
public int height; // DNG JPEG size
/// <summary>
/// The width.
/// </summary>
public int width; // DNG JPEG size
/// <summary>
/// The x.
/// </summary>
public int x; // DNG JPEG top left corner
/// <summary>
/// The y.
/// </summary>
public int y; // DNG JPEG top left corner
#endregion
}
} // class
} // namespace
Python code which controls a Sony camera through USB and 2 stepper motors in my DigiTiler invention
# Tkinter python 2.7, or tkinter 3.x
# pip install pyserial
from Tkinter import *
import sys
import glob
import serial
import time
# Defaults
h_step_value_default = "8100"
v_step_value_default = "5500"
h_tiles_default = "7"
v_tiles_default = "7"
timeformove = "1000" # eventually make config option
# instance tkinter
master = Tk()
poll = False
master.title("DigiTiler Control")
sendsteps = StringVar()
sendstring = StringVar()
strVersion = StringVar()
global comPort
global comPortName
global serial_list
global motor_moves_on
# for debugging movements, turn motors off
motor_moves_on = True
comPort = serial.Serial()
comPortName = ""
######## CODE ###########
# we need to put in top so buttons know
running = True
# So we can break out of loop if motors go off course
def start():
"""Enable scanning by setting the global flag to True."""
global running
running = True
def stop():
"""Stop scanning by setting the global flag to False."""
global running
running = False
def motors_disable():
comPort = serial.Serial(comPortName, timeout=1.0) # 1 second timeout!
comPort.write('EM,0,0\r'.encode('ascii')) # disable motors
def h_step_forward():
#comPortName = ser_list_ports_entry.get()
comPort = serial.Serial(comPortName, timeout=1.0) # 1 second timeout!
sendsteps = h_step_entry.get()
print(sendsteps)
sendstring = 'sm,'+timeformove+','+sendsteps+',0,\r'
print(sendstring)
comPort.write(sendstring.encode('ascii'))
strVersion = comPort.readline()
status_entry.delete(0, END)
status_entry.insert(50, strVersion)
#Update OFFSETS
offset = int(str(h_offset_entry.get()))
#print("offset is: "+str(offset))
hstep = int(h_step_entry.get())
offset = offset + hstep
h_offset_entry.delete(0, END)
h_offset_entry.insert(0,str(offset))
#serialPort.close()
def h_step_back():
comPort = serial.Serial(comPortName, timeout=1.0) # 1 second timeout!
sendsteps = h_step_entry.get()
sendsteps = "-"+sendsteps
print(sendsteps)
sendstring = 'sm,' + timeformove + ',' + sendsteps + ',0,\r'
print(sendstring)
comPort.write(sendstring.encode('ascii'))
strVersion = comPort.readline()
status_entry.delete(0, END)
status_entry.insert(50, strVersion)
# Update OFFSETS
offset = int(str(h_offset_entry.get()))
# print("offset is: "+str(offset))
hstep = int(h_step_entry.get()) * -1
offset = offset + hstep
h_offset_entry.delete(0, END)
h_offset_entry.insert(0, str(offset))
def v_step_forward():
comPort = serial.Serial(comPortName, timeout=1.0) # 1 second timeout!
sendsteps = v_step_entry.get()
print(sendsteps)
sendstring = 'sm,' + timeformove + ',0,' + sendsteps + '\r'
print(sendstring)
comPort.write(sendstring.encode('ascii'))
strVersion = comPort.readline()
status_entry.delete(0, END)
status_entry.insert(50, strVersion)
# Update OFFSETS
offset = int(str(v_offset_entry.get()))
# print("offset is: "+str(offset))
vstep = int(v_step_entry.get())
offset = offset + vstep
v_offset_entry.delete(0, END)
v_offset_entry.insert(0, str(offset))
def v_step_back():
comPort = serial.Serial(comPortName, timeout=1.0) # 1 second timeout!
sendsteps = v_step_entry.get()
sendsteps = "-"+sendsteps
print(sendsteps)
sendstring = 'sm,' + timeformove + ',0,' + sendsteps + '\r'
print(sendstring)
comPort.write(sendstring.encode('ascii'))
strVersion = comPort.readline()
status_entry.delete(0, END)
status_entry.insert(50, strVersion)
# Update OFFSETS
offset = int(str(v_offset_entry.get()))
# print("offset is: "+str(offset))
vstep = int(v_step_entry.get()) *-1
offset = offset + vstep
v_offset_entry.delete(0, END)
v_offset_entry.insert(0, str(offset))
def h_step_default():
pass
def v_step_default():
pass
#Offsets
def h_offset_center():
comPort = serial.Serial(comPortName, timeout=1.0) # 1 second timeout!
# set opposite to go back; that is *-1
hmove = int(h_offset_entry.get()) * -1
sendsteps = str(hmove)
print(sendsteps)
sendstring = 'sm,' + timeformove + ',' + sendsteps + ',0,\r'
print(sendstring)
comPort.write(sendstring.encode('ascii'))
strVersion = comPort.readline()
status_entry.delete(0, END)
status_entry.insert(50, strVersion)
# Update OFFSETS
h_offset_entry.delete(0, END)
h_offset_entry.insert(0, str("0"))
# serialPort.close()
def h_offset_fullleft():
pass
def h_offset_fullright():
pass
def v_offset_center():
comPort = serial.Serial(comPortName, timeout=1.0) # 1 second timeout!
# set opposite to go back; that is *-1
vmove = int(v_offset_entry.get()) * -1
sendsteps = str(vmove)
print(sendsteps)
sendstring = 'sm,' + timeformove + ',0,' + sendsteps + '\r'
print(sendstring)
comPort.write(sendstring.encode('ascii'))
strVersion = comPort.readline()
status_entry.delete(0, END)
status_entry.insert(50, strVersion)
# Update OFFSETS
v_offset_entry.delete(0, END)
v_offset_entry.insert(0, str("0"))
def v_offset_top():
pass
def v_offset_bottom():
pass
### DATA ###
def save_current_values():
pass
### SERIEAL ####
def list_serial_ports():
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
serial_list = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
serial_list.append(port)
except (OSError, serial.SerialException):
pass
#ser_list_ports_entry.insert(20,serial_list)
# Put into optionmenu
dropdownvariable = StringVar()
dropdownvariable.set(serial_list[0])
ser_list_optionmenu = OptionMenu(master, dropdownvariable, *serial_list, command=ser_port_selected)
ser_list_optionmenu.grid(row=1, column=2, padx=4, pady=4)
return serial_list
def ser_test_port():
# we now get through optionmenu
#comPortName = ser_list_ports_entry.get()
print("comPortName is: "+comPortName)
comPort = serial.Serial(comPortName, timeout=1.0) # 1 second timeout!
comPort.write('v\r'.encode('ascii'))
strVersion = comPort.readline()
status_entry.delete(0, END)
status_entry.insert(50, strVersion)
#serialPort.close()
def shutter_fire():
time.sleep(1.5)
# fire shutter
comCMD = 'S2,24000,5\r'.encode('ascii')
print(comCMD)
comPort.write(comCMD)
time.sleep(.450)
comCMD = 'S2,12000,5\r'.encode('ascii')
comPort.write(comCMD)
strVersion = comPort.readline()
status_entry.delete(0, END)
status_entry.insert(50, strVersion)
time.sleep(.5) # wait half a second before moving
##########################
### RUN ROUTINES TILING
###########################
def run_RLBT():
shotnumber = 1
if running==True:
# Put camera in start position
# fire first shutter
# Open PORT
if comPortName != "":
comPort = serial.Serial(comPortName, timeout=1.0) # 1 second timeout!
global comPort
time.sleep(3) # wait for board to catchup or first shutter doesn't fire
# defaults
hstep = h_step_entry.get()
vstep = v_step_entry.get()
htiles = int(h_tiles_entry.get())
vtiles = int(v_tiles_entry.get())
# Row, or horizontal movements
for r in range(1,(htiles+1)):
# are moving horizontally forward or backwards?
if r % 2 == 0: # EVEN row
# HORIZONTAL
hmove = str(int(hstep) * -1) # reverse
else: # ODD row
hmove = hstep # forward
# Set depending on odd/even row
vmove = vstep # default
# Now go through vertical tiles (on each row)
for c in range(1, (vtiles+1)):
# FIRE SHUTTER always
if motor_moves_on:
shutter_fire()
print("Shot: " + str(shotnumber))
shotnumber += 1
# ONLY MOVE CAMERA if not at end, if at end
# we'll leave that outside loop
if c != vtiles:
print('Tile '+str(r)+','+str(c)+' H-Step='+str(hmove))
# Move
sendstring = 'sm,' + timeformove + ',' + str(hmove) + ',0,\r'
if motor_moves_on:
time.sleep(.250) # wait quarter of a second
comPort.write(sendstring.encode('ascii'))
strVersion = comPort.readline()
status_entry.delete(0, END)
status_entry.insert(50, strVersion)
# check for stop in VERTICAL LOOP
master.update()
if not running:
break
# We're at the end of a row, so move up, but only if not at end
if r != htiles:
print('Tile ' + str(r) + ' V-Step=' + str(vmove))
# Move
sendstring = 'sm,' + timeformove + ',0,' + str(vmove) + '\r'
if motor_moves_on:
time.sleep(.250) # wait quarter of a second
comPort.write(sendstring.encode('ascii'))
strVersion = comPort.readline()
status_entry.delete(0, END)
status_entry.insert(50, strVersion)
# check for stop HORIZONTAL
master.update()
if (running == False):
break
status_entry.delete(0,END)
status_entry.insert(0,"Tiling done")
comPort.close()
def ser_port_selected(selected_opt):
global comPortName
comPortName = selected_opt
print("comPortName is now: "+comPortName)
def quit():
running = False
if comPort is not None:
try:
comPort.close()
except serial.SerialException:
pass
master.destroy()
#########################
onrow = 1
# First Row Group description
ser_list_ports_btn = Button(master, text='Get Serial Ports', command=list_serial_ports)
ser_test_port_btn = Button(master, text='Test Port', command=ser_test_port)
ser_list_ports_btn.grid(row=onrow, column=1,padx=4,pady=4)
# optionmenu in column 2 !
ser_test_port_btn.grid(row=onrow, column=3,padx=4,pady=4)
# List Serial Ports
onrow+=1
onrow+=1
# Group description
g1_lbl = Label(master, text="Tile distance values for steppers")
g1_lbl.grid(row=onrow, column=2)
onrow+=1
# H-Step
h_step_lbl = Label(master, text="H Step")
h_step_entry = Entry(master)
h_step_entry.insert(10,h_step_value_default)
h_step_btn_forward = Button(master, text='Forward', command=h_step_forward)
h_step_btn_back = Button(master, text='Back', command=h_step_back)
h_step_btn_default = Button(master, text='Default', command=h_step_default)
h_step_lbl.grid(row=onrow,column=1,padx=4,pady=4)
h_step_entry.grid(row=onrow, column=2,padx=4,pady=4)
h_step_btn_forward.grid(row=onrow, column=3,padx=4,pady=4)
h_step_btn_back.grid(row=onrow, column=4,padx=4,pady=4)
h_step_btn_default.grid(row=onrow, column=5,padx=4,pady=4)
onrow+=1
# V-Step
v_step_lbl = Label(master, text="V Step")
v_step_entry = Entry(master)
v_step_entry.insert(10,v_step_value_default)
v_step_btn_forward = Button(master, text='Up', command=v_step_forward)
v_step_btn_back = Button(master, text='Down', command=v_step_back)
v_step_btn_default = Button(master, text='Default', command=v_step_default)
v_step_lbl.grid(row=onrow,column=1,padx=4,pady=4)
v_step_entry.grid(row=onrow, column=2,padx=4,pady=4)
v_step_btn_forward.grid(row=onrow, column=3,padx=4,pady=4)
v_step_btn_back.grid(row=onrow, column=4,padx=4,pady=4)
v_step_btn_default.grid(row=onrow, column=5,padx=4,pady=4)
onrow+=1
# Second Row Group description
g2_lbl = Label(master, text="Widths (H and V) in Tiles")
g2_lbl.grid(row=onrow, column=2)
onrow+=1
# H Tiles
h_tiles_lbl = Label(master, text="H Tiles")
h_tiles_entry = Entry(master)
h_tiles_entry.insert(2,h_tiles_default)
h_tiles_lbl.grid(row=onrow,column=1,padx=4,pady=4)
h_tiles_entry.grid(row=onrow, column=2,padx=4,pady=4)
onrow+=1
# V Tiles
v_tiles_lbl = Label(master, text="V Tiles")
v_tiles_entry = Entry(master)
v_tiles_entry.insert(2,v_tiles_default)
v_tiles_lbl.grid(row=onrow,column=1,padx=4,pady=4)
v_tiles_entry.grid(row=onrow, column=2,padx=4,pady=4)
onrow+=1
############## OFFSETS ####################
# Group description
g1_lbl = Label(master, text="Current Offsets")
g1_lbl.grid(row=onrow, column=2)
onrow+=1
# H-Offset
h_offset_lbl = Label(master, text="H Offset")
h_offset_entry = Entry(master)
h_offset_entry.insert(0,"0")
h_offset_btn_center = Button(master, text='Center', command=h_offset_center)
h_offset_btn_fullleft = Button(master, text='<< Left', command=h_offset_fullleft)
h_offset_btn_fullright = Button(master, text='Right >>', command=h_offset_fullright)
h_offset_lbl.grid(row=onrow,column=1,padx=4,pady=4)
h_offset_entry.grid(row=onrow, column=2,padx=4,pady=4)
h_offset_btn_center.grid(row=onrow, column=3,padx=4,pady=4)
h_offset_btn_fullleft.grid(row=onrow, column=4,padx=4,pady=4)
h_offset_btn_fullright.grid(row=onrow, column=5,padx=4,pady=4)
onrow+=1
# V-Offset
v_offset_lbl = Label(master, text="V Offset")
v_offset_entry = Entry(master)
v_offset_entry.insert(0,"0")
v_offset_btn_center = Button(master, text='Center', command=v_offset_center)
v_offset_btn_top = Button(master, text='<< Top', command=v_offset_top)
v_offset_btn_bottom = Button(master, text='Bottom >>', command=v_offset_bottom)
v_offset_lbl.grid(row=onrow,column=1,padx=4,pady=4)
v_offset_entry.grid(row=onrow, column=2,padx=4,pady=4)
v_offset_btn_center.grid(row=onrow, column=3,padx=4,pady=4)
v_offset_btn_top.grid(row=onrow, column=4,padx=4,pady=4)
v_offset_btn_bottom.grid(row=onrow, column=5,padx=4,pady=4)
onrow+=1
### RUN ROUTINES ####
run_RLBT_btn = Button(master, text='Run R-L-B-T', command=run_RLBT)
run_LRTB_btn = Button(master, text='Run L-R-T-B')
stop_btn = Button(master,text='STOP!',command=stop)
motors_disable_btn = Button(master,text='Motors Disable',command=motors_disable)
shutter_fire_btn = Button(master,text='Fire Shutter',command=shutter_fire)
run_RLBT_btn.grid(row=onrow,column=1,padx=4,pady=4,sticky=W+E+N+S)
run_LRTB_btn.grid(row=onrow,column=2,padx=4,pady=4,sticky=W+E+N+S)
stop_btn.grid(row=onrow,column=3,padx=4,pady=4,sticky=W+E+N+S)
motors_disable_btn.grid(row=onrow,column=4,padx=4,pady=4,sticky=W+E+N+S)
shutter_fire_btn.grid(row=onrow,column=5,padx=4,pady=4,sticky=W+E+N+S)
onrow+=1
### STATUS ###
status_entry = Entry(master)
status_entry.grid(row=onrow,column=0,columnspan=6,padx=4,pady=4,sticky=W+E+N+S)
status_entry.insert(50,"Status...")
onrow+=1
# Final Buttons
# 3rd Row, column 0 and 1
#Button(master, text='Save Current Values', command=save_current_values).grid(row=onrow, column=1, sticky=W, padx=10, pady=4)
Button(master, text='Quit', command=quit).grid(row=onrow, column=1, sticky=W, padx=10, pady=4)
# Pack
mainloop( )