diff --git a/rigs/ocpi1.jl b/rigs/ocpi1.jl index 4ac1fad..0609abb 100644 --- a/rigs/ocpi1.jl +++ b/rigs/ocpi1.jl @@ -54,6 +54,8 @@ CAM_CONTROL_CHANS[rig_key] = ocpi1_cam_ctrl_chans CAM_MONITOR_CHANS[rig_key] = ocpi1_cam_mon_chans LAS_CONTROL_CHANS[rig_key] = ocpi1_laschans STIM_CHANS[rig_key] =OrderedSet(ocpi1_stimchans) +GALVO_CONTROL_CHANS[rig_key] = String[] +GALVO_MONITOR_CHANS[rig_key] = String[] FIXED_NAMES[rig_key] = ocpi1_fixed_names FIXED_DAQ_CHANS[rig_key] = ocpi1_fixed_daqchans diff --git a/rigs/ocpi2.jl b/rigs/ocpi2.jl index 20a19be..6b32c03 100644 --- a/rigs/ocpi2.jl +++ b/rigs/ocpi2.jl @@ -3,12 +3,12 @@ push!(RIGS, rig_key) const ocpi2_mappings = Dict("AO0"=>"axial piezo", "AO1"=>"horizontal piezo", - "AO2"=>"analogout3", - "AO3"=>"analogout4", + "AO2"=>"galvo1", + "AO3"=>"galvo2", "AI0"=>"axial piezo monitor", "AI1"=>"horizontal piezo monitor", - "AI2"=>"analogin1", - "AI3"=>"analogin2", + "AI2"=>"galvo1 monitor", + "AI3"=>"galvo2 monitor", "AI4"=>"analogin3", "AI5"=>"analogin4", "AI6"=>"analogin5", @@ -83,7 +83,9 @@ const ocpi2_cam_ctrl_chans = map(x->DEFAULT_NAMES_TO_DAQCHANS[rig_key][x], ["cam const ocpi2_cam_mon_chans = map(x->DEFAULT_NAMES_TO_DAQCHANS[rig_key][x], ["camera1 frame monitor"; "camera2 frame monitor"]) const ocpi2_laschans = map(x->DEFAULT_NAMES_TO_DAQCHANS[rig_key][x], ["405nm laser"; "445nm laser"; "488nm laser"; "514nm laser"; "561nm laser"; "all lasers"]) const ocpi2_stimchans = map(x->DEFAULT_NAMES_TO_DAQCHANS[rig_key][x], ["stimulus$x" for x = 1:15]) -const ocpi2_fixed_names = ["axial piezo", "axial piezo monitor", "horizontal piezo", "horizontal piezo monitor", "camera1", "camera1 frame monitor", "camera2", "camera2 frame monitor", "405nm laser", "445nm laser", "488nm laser", "514nm laser", "561nm laser"] +const ocpi2_galvo_ctrl_chans = map(x->DEFAULT_NAMES_TO_DAQCHANS[rig_key][x], ["galvo1"; "galvo2"]) +const ocpi2_galvo_mon_chans = map(x->DEFAULT_NAMES_TO_DAQCHANS[rig_key][x], ["galvo1 monitor"; "galvo2 monitor"]) +const ocpi2_fixed_names = ["axial piezo", "axial piezo monitor", "horizontal piezo", "horizontal piezo monitor", "camera1", "camera1 frame monitor", "camera2", "camera2 frame monitor", "405nm laser", "445nm laser", "488nm laser", "514nm laser", "561nm laser", "galvo1", "galvo2", "galvo1 monitor", "galvo2 monitor"] const ocpi2_fixed_daqchans = map(x->DEFAULT_NAMES_TO_DAQCHANS[rig_key][x], ocpi2_fixed_names) AO_CHANS[rig_key] = OrderedSet(ocpi2_aochans) @@ -96,6 +98,8 @@ CAM_CONTROL_CHANS[rig_key] = ocpi2_cam_ctrl_chans CAM_MONITOR_CHANS[rig_key] = ocpi2_cam_mon_chans LAS_CONTROL_CHANS[rig_key] = ocpi2_laschans STIM_CHANS[rig_key] =OrderedSet(ocpi2_stimchans) +GALVO_CONTROL_CHANS[rig_key] = ocpi2_galvo_ctrl_chans +GALVO_MONITOR_CHANS[rig_key] = ocpi2_galvo_mon_chans FIXED_NAMES[rig_key] = ocpi2_fixed_names FIXED_DAQ_CHANS[rig_key] = ocpi2_fixed_daqchans diff --git a/src/ImagineInterface.jl b/src/ImagineInterface.jl index 650b595..ee3bd42 100644 --- a/src/ImagineInterface.jl +++ b/src/ImagineInterface.jl @@ -89,6 +89,8 @@ export isfree, getcameramonitors, getlasers, getstimuli, + getgalvos, + getgalvomonitors, hasmonitor, hasactuator, monitor_name, diff --git a/src/convenience.jl b/src/convenience.jl index 1be5fd5..0af432a 100644 --- a/src/convenience.jl +++ b/src/convenience.jl @@ -58,13 +58,20 @@ isstim{T<:ImagineSignal}(com::T) = isstim(daq_channel(com), rig_name(com)) findstimuli{T<:ImagineSignal}(coms::AbstractVector{T}) = find(x->isstim(x), coms) getstimuli{T<:ImagineSignal}(coms::AbstractVector{T}) = view(coms, findstimuli(coms)) +isgalvo{T<:ImagineSignal}(com::T) = iscam(daq_channel(com), rig_name(com)) +findgalvos{T<:ImagineSignal}(coms::AbstractVector{T}) = find(x->iscam(x), coms) +getgalvos{T<:ImagineSignal}(coms::AbstractVector{T}) = view(coms, findcameras(coms)) -hasmonitor{T<:ImagineSignal}(com::T) = iscam(com) || ispos(com) -hasactuator{T<:ImagineSignal}(com::T) = iscammonitor(com) || isposmonitor(com) +isgalvomonitor{T<:ImagineSignal}(com::T) = isgalvomonitor(daq_channel(com), rig_name(com)) +findgalvomonitors{T<:ImagineSignal}(coms::AbstractVector{T}) = find(x->isgalvomonitor(x), coms) +getgalvomonitors{T<:ImagineSignal}(coms::AbstractVector{T}) = view(coms, findgalvomonitors(coms)) + +hasmonitor{T<:ImagineSignal}(com::T) = iscam(com) || ispos(com) || isgalvo(com) +hasactuator{T<:ImagineSignal}(com::T) = iscammonitor(com) || isposmonitor(com) || isgalvomonitor(com) function monitor_name{T<:ImagineSignal}(com::T) if !hasmonitor(com) - error("There is not monitor (input) corresponding to this channel") + error("There is no monitor (input) corresponding to this channel") end if iscam(com) return name(com) * " frame monitor" @@ -80,7 +87,7 @@ end function actuator_name{T<:ImagineSignal}(com::T) if !hasactuator(com) - error("There is not actuator (output) corresponding to this channel") + error("There is no actuator (output) corresponding to this channel") end if iscammonitor(com) return String(split(name(com), " frame monitor")[1]) diff --git a/src/hardware_templates.jl b/src/hardware_templates.jl index 1102ce1..64f4fba 100644 --- a/src/hardware_templates.jl +++ b/src/hardware_templates.jl @@ -26,6 +26,19 @@ function piezo_samplemapper{TL<:HasLengthUnits,TV<:HasVoltageUnits, TU}(p::Abstr return SampleMapper(zero(rawtype), typemax(rawtype), minimum(v), maximum(v), minimum(p), maximum(p), sample_rate) end +function galvo_ctrl_samplemapper{TU}(rawtype=Int16, sample_rate::HasInverseTimeUnits{Int, TU}=10000s^-1) + rad_min = -10.0*deg2rad(1.0)*Unitful.rad #1.0 degrees per volt + rad_max = 10.0*deg2rad(1.0)*Unitful.rad + return SampleMapper(zero(rawtype), typemax(rawtype), -10.0*Unitful.V, 10.0*Unitful.V, rad_min, rad_max, sample_rate) +end + +function galvo_mon_samplemapper{TU}(rawtype=Int16, sample_rate::HasInverseTimeUnits{Int, TU}=10000s^-1) + rad_min = -5.0*deg2rad(2.0)*Unitful.rad #2.0 degrees per volt + rad_max = 5.0*deg2rad(2.0)*Unitful.rad + return SampleMapper(zero(rawtype), typemax(rawtype), -5.0*Unitful.V, 5.0*Unitful.V, rad_min, rad_max, sample_rate) +end + + #Shortcut for creating a generic TTL SampleMapper, assumes TTL level of 3.3V (though this doesn't matter to Imagine, only for visualizing in Julia) #By default the raw samples are true/false values encoded as UInt8. If using an analog channel for TTL signals these default limits should be changed function ttl_samplemapper{U}(rawmin=UInt8(false), rawmax=(UInt8(true)); sample_rate::HasInverseTimeUnits{Int, U}=10000s^-1) @@ -47,6 +60,8 @@ function rigtemplate{U}(rig::String; sample_rate::HasInverseTimeUnits{Int,U} = 1 ao_sampmapper = piezo_samplemapper(PIEZO_RANGES[rig]...; rawtype = Int16, sample_rate = sample_rate) elseif iscam(c, rig) #if using an AO channel to control cameras (not advised, mostly for testing) ao_sampmapper = ttl_samplemapper(zero(Int16), ceil(Int16, typemax(Int16)*3.3/10.0); sample_rate = sample_rate) + elseif isgalvo(c, rig) + ao_sampmapper = galvo_ctrl_samplemapper(Int16, sample_rate) else ao_sampmapper = generic_ao_samplemapper(AO_RANGE[rig]; rawtype = Int16, sample_rate = sample_rate) end @@ -68,6 +83,8 @@ function rigtemplate{U}(rig::String; sample_rate::HasInverseTimeUnits{Int,U} = 1 ai_sampmapper = piezo_samplemapper(PIEZO_RANGES[rig]...; rawtype = Int16, sample_rate = sample_rate) elseif iscammonitor(c, rig) #If using an AI channel for TTL camera inputs ai_sampmapper = ttl_samplemapper(zero(Int16), ceil(Int16, typemax(Int16)*3.3/10.0); sample_rate = sample_rate) + elseif isgalvomonitor(c, rig) + ai_sampmapper = galvo_mon_samplemapper(Int16, sample_rate) else ai_sampmapper = generic_ai_samplemapper(AI_RANGE[rig]; rawtype = Int16, sample_rate = sample_rate) end diff --git a/src/metadata_constants.jl b/src/metadata_constants.jl index 00197d5..79461b1 100644 --- a/src/metadata_constants.jl +++ b/src/metadata_constants.jl @@ -35,6 +35,11 @@ const CAM_MONITOR_CHANS= Dict() const LAS_CONTROL_CHANS= Dict() #Lists of (digital) stimulus daq channels const STIM_CHANS= Dict() +#Lists of galvo control daq channels +const GALVO_CONTROL_CHANS= Dict() +#Lists of galvo monitor daq chans +const GALVO_MONITOR_CHANS= Dict() + #These names aren't allowed to be changed by users when writing command files const FIXED_NAMES = Dict() const FIXED_DAQ_CHANS = Dict() @@ -67,6 +72,8 @@ iscam(daq_chan::String, rig::String) = in(daq_chan, CAM_CONTROL_CHANS[rig]) iscammonitor(daq_chan::String, rig::String) = in(daq_chan, CAM_MONITOR_CHANS[rig]) islas(daq_chan::String, rig::String) = in(daq_chan, LAS_CONTROL_CHANS[rig]) isstim(daq_chan::String, rig::String) = in(daq_chan, STIM_CHANS[rig]) +isgalvo(daq_chan::String, rig::String) = in(daq_chan, GALVO_CONTROL_CHANS[rig]) +isgalvomonitor(daq_chan::String, rig::String) = in(daq_chan, GALVO_MONITOR_CHANS[rig]) #For querying rig camera info function chip_size(rig::String) diff --git a/test/inputs.jl b/test/inputs.jl index ae9473e..0b1284c 100644 --- a/test/inputs.jl +++ b/test/inputs.jl @@ -71,8 +71,8 @@ npulse_laser = count_pulses(getname(do_coms, "488nm laser shutter")) @test nexp_di == nexp_do == hdr["number of frames requested"] @test npulse_laser == hdr["nStacks"] -pos_ao = ustrip(get_samples(getname(ao_coms, "axial piezo"))) -pos_ai = ustrip(get_samples(getname(ai_recs, "axial piezo monitor"))) +pos_ao = ustrip.(get_samples(getname(ao_coms, "axial piezo"))) +pos_ai = ustrip.(get_samples(getname(ai_recs, "axial piezo monitor"))) @test cor(pos_ao, pos_ai) >= 0.97 #Automatic .json, .ai, .di, and .imagine loading diff --git a/test/low_level.jl b/test/low_level.jl index f1d67c5..a7f5746 100644 --- a/test/low_level.jl +++ b/test/low_level.jl @@ -128,12 +128,17 @@ append!(stim_com, "on_off", stim_vec) @test ImagineInterface.get_samples_raw(stim_com, 1, length(stim_com)) == convert(Vector{UInt8}, stim_vec) #this caught an off-by-one error -_cam = getcameras(rigtemplate("ocpi-2"; sample_rate = 1000 * inv(Unitful.s)))[1] +oc2 = rigtemplate("ocpi-2"; sample_rate = 1000 * inv(Unitful.s)) +_cam = getcameras(oc2)[1] c = fill(UInt8(1), 10) c[1] = 0 c[end] = 0 append!(_cam, "c", c) @test ImagineInterface.get_samples_raw(_cam, 10, 10)[1] == false +galvos = getgalvos(oc2) +@test hasmonitor(galvos[1]) && hasmonitor(galvos[2]) +galvo_mons = getgalvomonitors(oc2) +@test hasactuator(galvo_mons[1]) && hasactuator(galvo_mons[2]) #convenience digs = getdigital(allcoms)