-
Notifications
You must be signed in to change notification settings - Fork 0
/
takeExposure.m
151 lines (138 loc) · 5.92 KB
/
takeExposure.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
function takeExposure(Unit,Cameras,ExpTime,Nimages, InPar)
% Take one or many exposures from one or many local or remote cameras,
% using nonblocking calls to start exposing.
% If requested, wait till the mount has finished slewing, the focusers
% moving and the camera shooting
%
% Package: +obs.@unitCS
% Input : - a vector of camera indices [all cameras if omitted]
% - Exposure time [s]. If provided this will override
% the Camera.ExpTime, and the Camera.ExpTime
% will be set to this value.
% - Number of images to obtain. Default is 1.
% * ...,key,val,... :
% 'WaitFinish' - default is false (to reduce delays)
% 'ImType' - (passed along to write image file), default is 'sci'
% If empty, will not be changed.
% 'Object' - (passed along to write image file), default is NaN.
% If NaN will insert field name based on
% coordinate name.
% If empty, will insert empty object.
% 'MinExpTimeForSave' - default is 5 [sec]. .SaveOnDisk
% will be temporarily turned off if
% ExpTime is smaller than that.
% (BUG - doesn't happen)
% TAKE CARE, Unit.Camera{i}.classCommand('waitFinish') may timeout
% because of no reply, if the messenger timeout is shorter than
% ExpTime. Consider using the method readyToExpose(...,true,timeout)
% for finer control.
% argument parsing
arguments
Unit
Cameras = [];
ExpTime = [];
Nimages = 1;
InPar.WaitFinish logical = false;
InPar.ImType = 'sci';
InPar.Object = NaN;
InPar.MinExpTimeForSave = 5;
end
if isempty(Cameras)
Cameras = (1:numel(Unit.Camera));
end
Ncam = numel(Cameras);
if isempty(ExpTime)
ExpTime=zeros(size(Cameras));
for i=1:numel(Cameras)
ExpTime(i) = Unit.Camera{Cameras(i)}.classCommand('ExpTime');
end
else
if numel(ExpTime)==1
ExpTime=repmat(ExpTime,size(Cameras));
end
for i=1:numel(Cameras)
Unit.Camera{Cameras(i)}.classCommand('ExpTime=%f;',ExpTime(i));
end
end
if ~isempty(InPar.ImType)
% update ImType
for Icam=1:1:Ncam
Unit.Camera{Cameras(Icam)}.classCommand(sprintf('ImType=''%s'';',InPar.ImType));
end
end
% update Object
if isnan(InPar.Object)
% If Object is NaN then will set the object name to coordinates
Coo = Unit.Mount.classCommand('j2000;');
InPar.Object = sprintf('%03d%+03d',round(mod(Coo(1),360)), round(Coo(2)));
end
for Icam=1:1:Ncam
Unit.Camera{Cameras(Icam)}.classCommand(sprintf('Object=''%s'';',InPar.Object));
end
if Nimages>1 && min(ExpTime) < InPar.MinExpTimeForSave
Unit.reportError([sprintf('If Nimages>1 then ExpTime must be above %g s',...
InPar.MinExpTimeForSave),...
'; camera.SaveOnDisk will be turned off for all cameras involved']);
% keep the previous SaveOnDisk status
saving=false(size(Cameras));
for i=Cameras
saving(i)=Unit.Camera{i}.classCommand('SaveOnDisk;');
Unit.Camera{i}.classCommand('SaveOnDisk=false;');
% however, this seems to have had no effect inside
% unitCS.treatNewImage. Why? some issue of snapshotting the
% object at the moment of creation of the listener, or
% something intricate else?
end
end
% end argument parsing
% wait before starting, if asked to
if InPar.WaitFinish
Unit.Mount.classCommand('waitFinish;');
% wait sequentially for each camera, because camera.waitFinish
% has been implemented scalarly. No big deal however, because
% at the end we'll proceed only when the last of the busy cameras
% is free, no matter the order of checking
% NOTE: THIS IS PROBLEMATIC WITH REMOTE OBJECTS
for i=Cameras
Unit.Focuser{i}.classCommand('waitFinish;');
Unit.Camera{i}.classCommand('waitFinish;');
end
end
% start acquisition on each of the local cameras, using nonblocking
% methods, and of the remote ones, using blind sends for maximum speed.
% This difference prevents the use of .classCommand() for both
for i=Cameras
CamStatus=Unit.Camera{i}.classCommand('CamStatus;');
if strcmp(CamStatus,'idle')
if isa(Unit.Camera{i},'obs.remoteClass')
remotename=Unit.Camera{i}.RemoteName;
if Nimages>1
Unit.Camera{i}.Messenger.send(sprintf('%s.takeLive(%d)',remotename,Nimages));
else
Unit.Camera{i}.Messenger.send(sprintf('%s.takeExposure',remotename));
end
else
if Nimages>1
Unit.Camera{i}.takeLive(Nimages);
else
Unit.Camera{i}.takeExposure;
end
end
% otherwise it would be just:
% if Nimages>1
% Unit.Camera{i}.classCommand('takeLive(%d)',Nimages);
% else
% Unit.Camera{i}.classCommand('takeExposure');
% end
else
Unit.reportError('Camera %d status is "%s", cannot take exposures!',...
i,CamStatus)
end
end
% restore the previous SaveOnDisk status if needed
if Nimages>1 && min(ExpTime) < InPar.MinExpTimeForSave
for i=Cameras
Unit.Camera{i}.classCommand('SaveOnDisk=%d;',saving(i));
end
end
end