PageRenderTime 34ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/ATF2/FlightSim/watchdogApps/apertures/apertures.m

http://atf2flightsim.googlecode.com/
MATLAB | 499 lines | 449 code | 7 blank | 43 comment | 77 complexity | c8613204055078bc0902fb67896a9b81 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause
  1. function [stat output] = apertures(cmd,varargin)
  2. % [stat output] = apertures(cmd)
  3. % Watchdog function for watching orbit in apertures
  4. %
  5. % 100510 JLN change data.alarm=false to data.alarm=0, so this watchdog
  6. % is consistent with the others
  7. persistent pars data lastupdate
  8. stat{1}=1; output=[];
  9. % Make sure initialised
  10. if isempty(pars) && ~isequal(cmd,'init')
  11. [stat pars]=initPars; if stat{1}~=1; return; end;
  12. data=initData;
  13. end
  14. % Methods
  15. switch lower(cmd)
  16. case 'init'
  17. [stat pars]=initPars; if stat{1}~=1; return; end;
  18. data=initData;
  19. case 'reset'
  20. [stat pars]=initPars('reset'); if stat{1}~=1; return; end;
  21. data=initData('reset');
  22. case 'isalarm'
  23. if isempty(lastupdate) || etime(clock,lastupdate)>pars.updateRate
  24. [stat data]=updateStatus(pars,data);
  25. if stat{1}~=1; return; end;
  26. lastupdate=clock;
  27. end
  28. output=data.alarm;
  29. case 'getpars'
  30. output=pars;
  31. case 'setpars'
  32. if nargin>0
  33. stat=checkPars(varargin{1});
  34. if stat{1}==1
  35. pars=setPars(pars,varargin{1});
  36. end
  37. end
  38. case 'update'
  39. pars.forceUpdate=true;
  40. [stat data]=updateStatus(pars,data);
  41. pars.forceUpdate=false;
  42. if stat{1}~=1; return; end;
  43. output=data;
  44. % data.alarm
  45. case 'getdata'
  46. output=data;
  47. case 'save'
  48. if isdir(fullfile('userData','guiData'))
  49. save(fullfile('userData','guiData','apertures.mat'),'pars','data');
  50. end
  51. case 'new'
  52. if nargin==3
  53. [stat pars data]=genNewAp(pars,data,varargin{1},varargin{2});
  54. end
  55. case 'bpmcheck'
  56. if nargin~=2
  57. error('need 2 input arguments')
  58. end
  59. [bpmind instrind]=bpmCheck(varargin{1});
  60. output=[bpmind; instrind];
  61. otherwise
  62. stat{1}=-1; stat{2}='Unknown command';
  63. return
  64. end
  65. %% Internal functions
  66. function stat=checkPars(pars) %#ok<INUSD>
  67. stat{1}=1;
  68. function [stat pars data]=genNewAp(pars,data,bl_ind,name)
  69. global BEAMLINE
  70. stat{1}=1;
  71. try
  72. pars.active=true;
  73. pars.(name).active=false;
  74. bpmind=findcells(BEAMLINE,'Class','MONI');
  75. if bl_ind<=0 || bl_ind>length(BEAMLINE)
  76. stat{1}=-1; stat{2}='Invalid beamline index';
  77. return
  78. end
  79. pars.(name).targetInd=bl_ind;
  80. pars.(name).bpmind=find(bpmind>pars.(name).targetInd,pars.nbpm);
  81. [pars.(name).bpmind pars.(name).bpminstr] =bpmCheck(pars.(name).bpmind);
  82. pars.(name).reforbit='default';
  83. pars.(name).shape='ellipse';
  84. pars.(name).xoff=0; pars.(name).yoff=0;
  85. pars.(name).xpoff=0; pars.(name).ypoff=0;
  86. pars.(name).xwid=1e-3; pars.(name).xpwid=1e-3;
  87. pars.(name).ywid=1e-3; pars.(name).ypwid=1e-3;
  88. pars.(name).xrot=0; pars.(name).yrot=0;
  89. pars=apCalc(pars,name);
  90. data.(name).alarm=0;
  91. catch
  92. stat{1}=-1; stat{2}=sprintf('Error creating new aperture: %s',lasterr);
  93. end
  94. function pars=setPars(pars,parsin)
  95. global INSTR
  96. bpmind_change={}; bpminstr_change={}; apchange={};
  97. apchangelist={'xoff' 'xpoff' 'yoff' 'ypoff' 'xwid' 'ywid' 'xpwid' 'ypwid' 'xrot' 'yrot' 'shape'};
  98. % Update new pars fields
  99. if isstruct(parsin)
  100. pf=fieldnames(parsin);
  101. for ipf=1:length(pf)
  102. if isstruct(parsin.(pf{ipf}))
  103. pf2=fieldnames(parsin.(pf{ipf}));
  104. for ipf2=1:length(pf2)
  105. if strcmp(pf2{ipf2},'bpmind')
  106. bpmind_change{end+1}=pf{ipf};
  107. elseif strcmp(pf2{ipf2},'bpminstr')
  108. bpminstr_change{end+1}=pf{ipf};
  109. elseif ismember(pf2{ipf2},apchangelist)
  110. apchange{end+1}=pf{ipf};
  111. end
  112. pars.(pf{ipf}).(pf2{ipf2})=parsin.(pf{ipf}).(pf2{ipf2});
  113. end
  114. else
  115. pars.(pf{ipf})=parsin.(pf{ipf});
  116. end
  117. end
  118. end
  119. % Check for changes in bpm indicies
  120. if ~isempty(bpmind_change)
  121. for iap=1:length(bpmind_change)
  122. [pars.(bpmind_change{iap}).bpmind pars.(bpmind_change{iap}).bpminstr]=bpmCheck(pars.(bpmind_change{iap}).bpmind);
  123. end
  124. end
  125. if ~isempty(bpminstr_change)
  126. for iap=1:length(bpminstr_change)
  127. pars.(bpminstr_change{iap}).bpmind=arrayfun(@(x) INSTR{x}.Index,pars.(bpminstr_change{iap}).bpminstr);
  128. [pars.(bpminstr_change{iap}).bpmind pars.(bpmind_change{iap}).bpminstr]=bpmCheck(pars.(bpminstr_change{iap}).bpmind);
  129. end
  130. end
  131. % recalc apertures if needed
  132. if ~isempty(apchange)
  133. for iap=1:length(apchange)
  134. pars=apCalc(pars,apchange{iap});
  135. end
  136. end
  137. function [stat pars]=initPars(varargin)
  138. global BEAMLINE INSTR
  139. stat{1}=1;
  140. % Test for reset command
  141. if nargin && isequal(varargin{1},'reset')
  142. reset=true;
  143. else
  144. reset=false;
  145. end
  146. % Load pars from last session if existing
  147. if isdir(fullfile('userData','watchdogData')) && exist(fullfile('userData','watchdogData','apertures.mat'),'file') && ~reset
  148. load(fullfile('userData','watchdogData','apertures.mat'),'pars');
  149. else % initialise here
  150. pars.active=true;
  151. pars.guiActive=false;
  152. pars.bpmave=10;
  153. pars.nbpm=5;
  154. pars.maxrms=3;
  155. pars.minq=0.5;
  156. pars.updateRate=60; % s
  157. pars.whichICT='ICTDUMP';
  158. pars.forceUpdate=false;
  159. bh=findcells(BEAMLINE,'Name','BH*XB');
  160. bpmind=findcells(BEAMLINE,'Class','MONI');
  161. nohw=arrayfun(@(x) INSTR{x}.Index,findcells(INSTR,'Class','NOHW'));
  162. bpmind=bpmind(~ismember(bpmind,nohw));
  163. pars.bpmind=bpmind;
  164. % ============== Septum
  165. pars.Septum.active=false;
  166. pars.Septum.targetInd=findcells(BEAMLINE,'Name','BS1XB');
  167. pars.Septum.bpmind=bpmind(find(bpmind>pars.Septum.targetInd,pars.nbpm));
  168. [pars.Septum.bpmind pars.Septum.bpminstr]=bpmCheck(pars.Septum.bpmind);
  169. pars.Septum.reforbit='default';
  170. pars.Septum.shape='ellipse';
  171. pars.Septum.xoff=0; pars.Septum.yoff=0;
  172. pars.Septum.xpoff=0; pars.Septum.ypoff=0;
  173. pars.Septum.xwid=1e-3; pars.Septum.xpwid=1e-3;
  174. pars.Septum.ywid=1e-3; pars.Septum.ypwid=1e-3;
  175. pars.Septum.xrot=0; pars.Septum.yrot=0;
  176. pars=apCalc(pars,'Septum');
  177. % ============== BH1X
  178. pars.BH1X.active=false;
  179. pars.BH1X.targetInd=bh(1);
  180. pars.BH1X.bpmind=bpmind(find(bpmind>pars.BH1X.targetInd,pars.nbpm));
  181. [pars.BH1X.bpmind pars.BH1X.bpminstr]=bpmCheck(pars.BH1X.bpmind);
  182. pars.BH1X.reforbit='default';
  183. pars.BH1X.shape='ellipse';
  184. pars.BH1X.xoff=0; pars.BH1X.yoff=0;
  185. pars.BH1X.xpoff=0; pars.BH1X.ypoff=0;
  186. pars.BH1X.xwid=1e-3; pars.BH1X.xpwid=1e-3;
  187. pars.BH1X.ywid=1e-3; pars.BH1X.ypwid=1e-3;
  188. pars.BH1X.xrot=0; pars.BH1X.yrot=0;
  189. pars=apCalc(pars,'BH1X');
  190. % ============== BH2X
  191. pars.BH2X.active=false;
  192. pars.BH2X.targetInd=bh(2);
  193. pars.BH2X.bpmind=bpmind(find(bpmind>pars.BH2X.targetInd,pars.nbpm));
  194. [pars.BH2X.bpmind pars.BH2X.bpminstr]=bpmCheck(pars.BH2X.bpmind);
  195. pars.BH2X.reforbit='default';
  196. pars.BH2X.shape='ellipse';
  197. pars.BH2X.xoff=0; pars.BH2X.yoff=0;
  198. pars.BH2X.xpoff=0; pars.BH2X.ypoff=0;
  199. pars.BH2X.xwid=1e-3; pars.BH2X.xpwid=1e-3;
  200. pars.BH2X.ywid=1e-3; pars.BH2X.ypwid=1e-3;
  201. pars.BH2X.xrot=0; pars.BH2X.yrot=0;
  202. pars=apCalc(pars,'BH2X');
  203. % ============== BH3X
  204. pars.BH3X.active=false;
  205. pars.BH3X.targetInd=bh(3);
  206. pars.BH3X.bpmind=bpmind(find(bpmind>pars.BH3X.targetInd,pars.nbpm));
  207. [pars.BH3X.bpmind pars.BH3X.bpminstr]=bpmCheck(pars.BH3X.bpmind);
  208. pars.BH3X.reforbit='default';
  209. pars.BH3X.shape='ellipse';
  210. pars.BH3X.xoff=0; pars.BH3X.yoff=0;
  211. pars.BH3X.xpoff=0; pars.BH3X.ypoff=0;
  212. pars.BH3X.xwid=1e-3; pars.BH3X.xpwid=1e-3;
  213. pars.BH3X.ywid=1e-3; pars.BH3X.ypwid=1e-3;
  214. pars.BH3X.xrot=0; pars.BH3X.yrot=0;
  215. pars=apCalc(pars,'BH3X');
  216. % ============= KEX2
  217. pars.KEX2.active=false;
  218. pars.KEX2.targetInd=findcells(BEAMLINE,'Name','IP02');
  219. pars.KEX2.bpmind=bpmind(find(bpmind>pars.KEX2.targetInd,pars.nbpm));
  220. [pars.KEX2.bpmind pars.KEX2.bpminstr]=bpmCheck(pars.KEX2.bpmind);
  221. pars.KEX2.reforbit='default';
  222. pars.KEX2.shape='ellipse';
  223. pars.KEX2.xoff=0; pars.KEX2.yoff=0;
  224. pars.KEX2.xpoff=0; pars.KEX2.ypoff=0;
  225. pars.KEX2.xwid=1e-3; pars.KEX2.xpwid=1e-3;
  226. pars.KEX2.ywid=1e-3; pars.KEX2.ypwid=1e-3;
  227. pars.KEX2.xrot=0; pars.KEX2.yrot=0;
  228. pars=apCalc(pars,'KEX2');
  229. % ============= Form response matricies
  230. [stat pars]=getRmat(pars); if stat{1}~=1; return; end;
  231. end
  232. function data=initData(varargin)
  233. % Test for reset command
  234. if nargin && isequal(varargin{1},'reset')
  235. reset=true;
  236. else
  237. reset=false;
  238. end
  239. % Load data from last session if existing
  240. if isdir(fullfile('userData','watchdogData')) && exist(fullfile('userData','watchdogData','apertures.mat'),'file') && ~reset
  241. load(fullfile('userData','watchdogData','apertures.mat'),'data');
  242. else % initialise here
  243. end
  244. %
  245. % 100510 JLN change all of these from false (logical) to 0 (double)
  246. %
  247. data.alarm=0;%false; % start with alarm state being false
  248. data.Septum.alarm=0;%false;
  249. data.BH1X.alarm=0;%false;
  250. data.BH2X.alarm=0;%false;
  251. data.BH3X.alarm=0;%false;
  252. data.KEX2.alarm=0;%false;
  253. function [stat data]=updateStatus(pars,data)
  254. global INSTR
  255. stat{1}=1; %#ok<NASGU>
  256. % Update response matrix
  257. [stat pars]=getRmat(pars); if stat{1}~=1; return; end;
  258. % Get BPM readings
  259. if strcmp(pars.whichICT,'ICTDUMP')
  260. w_ict=0;
  261. elseif strcmp(pars.whichICT,'ICT1X')
  262. w_ict=1;
  263. else
  264. stat{1}=-1; stat{2}='Invalid ICT choice'; return;
  265. end
  266. % Check there is enough bpm data
  267. [stat bsize]=FlHwUpdate('buffersize');
  268. if stat{1}~=1 || bsize<pars.bpmave
  269. stat{2}='Not enough buffered bpm data or not available';
  270. return
  271. end
  272. % Get averaged bpm readings
  273. [stat bpmdata]=FlHwUpdate('bpmave',pars.bpmave,0,[pars.minq,pars.maxrms,w_ict,0]); if stat{1}~=1; return; end;
  274. % Loop over all apertures
  275. pf=fieldnames(pars); data.alarm=0;
  276. for ipf=1:length(pf)
  277. if isfield(pars.(pf{ipf}),'targetInd') && (pars.(pf{ipf}).active || pars.forceUpdate)
  278. % Treat upstream bpms seperately
  279. us=pars.(pf{ipf}).bpmind<pars.(pf{ipf}).targetInd;
  280. ds=~us;
  281. % Pull out BPM data of interest and get difference from gold orbit
  282. try
  283. if isequal(pars.(pf{ipf}).reforbit,'default')
  284. bpmx_ref=arrayfun(@(x) INSTR{x}.ref(1),pars.(pf{ipf}).bpminstr(ds))';
  285. bpmsx_ref=arrayfun(@(x) INSTR{x}.referr(1),pars.(pf{ipf}).bpminstr(ds))';
  286. bpmy_ref=arrayfun(@(x) INSTR{x}.ref(2),pars.(pf{ipf}).bpminstr(ds))';
  287. bpmsy_ref=arrayfun(@(x) INSTR{x}.referr(2),pars.(pf{ipf}).bpminstr(ds))';
  288. else
  289. bpmx_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(ds),1);
  290. bpmy_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(ds),2);
  291. bpmsx_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(ds),4);
  292. bpmsy_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(ds),5);
  293. end
  294. catch
  295. stat{1}=-1; stat{2}='No reference orbit defined'; return;
  296. end
  297. if any(isnan(bpmx_ref)) || any(isnan(bpmy_ref))
  298. stat{1}=-1; stat{2}='bad reference orbit';
  299. return
  300. end
  301. bpmx=bpmdata{1}(1,pars.(pf{ipf}).bpminstr(ds))'-bpmx_ref; bpmsx=sqrt(bpmdata{1}(4,pars.(pf{ipf}).bpminstr(ds))'.^2+bpmsx_ref.^2);
  302. bpmy=bpmdata{1}(2,pars.(pf{ipf}).bpminstr(ds))'-bpmy_ref; bpmsy=sqrt(bpmdata{1}(5,pars.(pf{ipf}).bpminstr(ds))'.^2+bpmsy_ref.^2);
  303. if any(isnan(bpmx)) || any(isnan(bpmy))
  304. stat{1}=-1; stat{2}='bad bpm readings';
  305. return
  306. end
  307. % Store bpm data
  308. data.(pf{ipf}).bpm=[bpmx bpmy]; data.(pf{ipf}).bpm_error=[bpmsx bpmsy];
  309. % Get estimated orbit at aperture(s) including error estimate based on bpm
  310. % readings RMS
  311. [data.(pf{ipf}).pos,data.(pf{ipf}).error,mse]=lscov([pars.(pf{ipf}).Rx(ds,:);pars.(pf{ipf}).Ry(ds,:)],[bpmx;bpmy],1./[bpmsx;bpmsy].^2);
  312. data.(pf{ipf}).error=data.(pf{ipf}).error*sqrt(1/mse);
  313. % Update alarm (true if outside aperture) % major alarm if pos outside,
  314. % minor if error bar outside
  315. ax=data.(pf{ipf}).pos(1); apx=data.(pf{ipf}).pos(2);
  316. asx=data.(pf{ipf}).error(1); apsx=data.(pf{ipf}).error(2);
  317. ay=data.(pf{ipf}).pos(3); apy=data.(pf{ipf}).pos(4);
  318. asy=data.(pf{ipf}).error(3); apsy=data.(pf{ipf}).error(4);
  319. data.(pf{ipf}).alarm=0;
  320. if pars.(pf{ipf}).active
  321. if ~inpolygon(ax,apx,pars.(pf{ipf}).aper_x,pars.(pf{ipf}).aper_xp) || ...
  322. ~inpolygon(ay,apy,pars.(pf{ipf}).aper_y,pars.(pf{ipf}).aper_yp)
  323. data.(pf{ipf}).alarm=2;
  324. data.alarm=2;
  325. elseif ~inpolygon(ax+asx,apx+apsx,pars.(pf{ipf}).aper_x,pars.(pf{ipf}).aper_xp) || ...
  326. ~inpolygon(ax-asx,apx-apsx,pars.(pf{ipf}).aper_x,pars.(pf{ipf}).aper_xp) || ...
  327. ~inpolygon(ax-asx,apx+apsx,pars.(pf{ipf}).aper_x,pars.(pf{ipf}).aper_xp) || ...
  328. ~inpolygon(ax+asx,apx-apsx,pars.(pf{ipf}).aper_x,pars.(pf{ipf}).aper_xp) || ...
  329. ~inpolygon(ay+asy,apy+apsy,pars.(pf{ipf}).aper_x,pars.(pf{ipf}).aper_xp) || ...
  330. ~inpolygon(ay-asy,apy-apsy,pars.(pf{ipf}).aper_x,pars.(pf{ipf}).aper_xp) || ...
  331. ~inpolygon(ay+asy,apy-apsy,pars.(pf{ipf}).aper_x,pars.(pf{ipf}).aper_xp) || ...
  332. ~inpolygon(ay-asy,apy+apsy,pars.(pf{ipf}).aper_x,pars.(pf{ipf}).aper_xp) && data.(pf{ipf}).alarm~=2
  333. data.(pf{ipf}).alarm=1;
  334. if data.alarm~=2; data.alarm=1; end;
  335. end
  336. else
  337. data.alarm=0;
  338. end
  339. % Deal with upstream fitting
  340. if any(us)
  341. dsbpm=find(pars.(pf{ipf}).bpmind<pars.(pf{ipf}).targetInd, 1, 'last' );
  342. if isempty(dsbpm)
  343. stat{1}=-1; stat{2}='Must be one downstream bpm provided!';
  344. return
  345. end
  346. try
  347. if isequal(pars.(pf{ipf}).reforbit,'default')
  348. bpmx_ref=arrayfun(@(x) INSTR{x}.ref(1),pars.(pf{ipf}).bpminstr(us))';
  349. bpmsx_ref=arrayfun(@(x) INSTR{x}.referr(1),pars.(pf{ipf}).bpminstr(us))';
  350. bpmy_ref=arrayfun(@(x) INSTR{x}.ref(2),pars.(pf{ipf}).bpminstr(us))';
  351. bpmsy_ref=arrayfun(@(x) INSTR{x}.referr(2),pars.(pf{ipf}).bpminstr(us))';
  352. dsbpmx_ref=arrayfun(@(x) INSTR{x}.ref(1),pars.(pf{ipf}).bpminstr(dsbpm))';
  353. dsbpmsx_ref=arrayfun(@(x) INSTR{x}.referr(1),pars.(pf{ipf}).bpminstr(dsbpm))';
  354. dsbpmy_ref=arrayfun(@(x) INSTR{x}.ref(2),pars.(pf{ipf}).bpminstr(dsbpm))';
  355. dsbpmsy_ref=arrayfun(@(x) INSTR{x}.referr(2),pars.(pf{ipf}).bpminstr(dsbpm))';
  356. else
  357. bpmx_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(us),1);
  358. bpmsx_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(us),4);
  359. bpmy_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(us),2);
  360. bpmsy_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(us),5);
  361. dsbpmx_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(dsbpm),1);
  362. dsbpmsx_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(dsbpm),4);
  363. dsbpmy_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(dsbpm),2);
  364. dsbpmsy_ref=pars.(pf{ipf}).reforbit(pars.(pf{ipf}).bpminstr(dsbpm),5);
  365. end
  366. catch
  367. stat{1}=-1; stat{2}='No reference orbit defined'; return;
  368. end
  369. bpmx=bpmdata{1}(1,pars.(pf{ipf}).bpminstr(us))'-bpmx_ref; bpmsx=sqrt(bpmdata{1}(4,pars.(pf{ipf}).bpminstr(us))'.^2+bpmsx_ref.^2);
  370. bpmy=bpmdata{1}(2,pars.(pf{ipf}).bpminstr(us))'-bpmy_ref; bpmsy=sqrt(bpmdata{1}(5,pars.(pf{ipf}).bpminstr(us))'.^2+bpmsy_ref.^2);
  371. dsbpmx=bpmdata{1}(1,pars.(pf{ipf}).bpminstr(dsbpm))'-dsbpmx_ref; dsbpmsx=sqrt(bpmdata{1}(4,pars.(pf{ipf}).bpminstr(dsbpm))'.^2+dsbpmsx_ref.^2);
  372. dsbpmy=bpmdata{1}(2,pars.(pf{ipf}).bpminstr(dsbpm))'-dsbpmy_ref; dsbpmsy=sqrt(bpmdata{1}(5,pars.(pf{ipf}).bpminstr(dsbpm))'.^2+dsbpmsy_ref.^2);
  373. % Store bpm data
  374. data.(pf{ipf}).bpm_us=[bpmx bpmy]; data.(pf{ipf}).bpm_error_us=[bpmsx bpmsy];
  375. % Get estimated orbit at aperture(s) including error estimate
  376. [data.(pf{ipf}).pos_us,data.(pf{ipf}).error_us]=fwdprop(bpmx,bpmsx,bpmy,bpmsy,dsbpmx,dsbpmsx,dsbpmy,dsbpmsy,pars.(pf{ipf}).Rij,pars.(pf{ipf}).Rik);
  377. end
  378. elseif isfield(pars.(pf{ipf}),'targetInd')
  379. data.(pf{ipf}).alarm=0;
  380. end
  381. end
  382. function [Xj,sigmaXj]=fwdprop(xi,sxi,yi,syi,xk,sxk,yk,syk,Rij,Rik)
  383. N = length(xi); Xj=zeros(4,1); sigmaXj=zeros(4,1);
  384. for i=1:length(xi)
  385. a=Rik{i}(1,2)-(Rik{i}(1,4)*Rik{i}(3,2))/Rik{i}(3,4);
  386. b=Rik{i}(3,4)-(Rik{i}(3,2)*Rik{i}(1,4))/Rik{i}(1,2);
  387. c=(Rik{i}(3,1)*Rik{i}(1,4))/Rik{i}(3,4)-Rik{i}(1,1);
  388. d=(Rik{i}(1,1)*Rik{i}(3,2))/Rik{i}(1,2)-Rik{i}(3,1);
  389. e=(Rik{i}(1,4)*Rik{i}(3,3))/Rik{i}(3,4)-Rik{i}(1,3);
  390. f=(Rik{i}(1,3)*Rik{i}(3,2))/Rik{i}(1,2)-Rik{i}(3,3);
  391. g=Rik{i}(3,2)/(b*Rik{i}(1,2));
  392. h=Rik{i}(1,4)/(a*Rik{i}(3,4));
  393. for i_ind=1:4
  394. Mi(i_ind,1)=Rij{i}(i_ind,1)+(Rij{i}(i_ind,2)/a)*c+(Rij{i}(i_ind,4)/b)*d;
  395. Mi(i_ind,2)=Rij{i}(i_ind,3)+(Rij{i}(i_ind,2)/a)*e+(Rij{i}(i_ind,4)/b)*f;
  396. Mi(i_ind,3)=Rij{i}(i_ind,2)/a - Rij{i}(i_ind,4)*g;
  397. Mi(i_ind,4)=Rij{i}(i_ind,4)/b - Rij{i}(i_ind,2)*h;
  398. end
  399. Xj = Xj + Mi * [xi(i);yi(i);xk;yk] ;
  400. sigmaXj = sigmaXj + Mi.^2 * [sxi(i);syi(i);sxk;syk].^2 ;
  401. end
  402. Xj=Xj/N;
  403. sigmaXj = sqrt(sigmaXj/N);
  404. function [stat pars]=getRmat(pars)
  405. stat{1}=1;
  406. pf=fieldnames(pars);
  407. for ipf=1:length(pf)
  408. if isstruct(pars.(pf{ipf})) && isfield(pars.(pf{ipf}),'targetInd') && (pars.(pf{ipf}).active || pars.forceUpdate)
  409. % Using specific list?
  410. if ~isfield(pars.(pf{ipf}),'bpmind')
  411. error('bpmind not defined for aperture: %s',pf{ipf})
  412. end
  413. pars.(pf{ipf}).Rx=zeros(length(pars.(pf{ipf}).bpmind),4);
  414. pars.(pf{ipf}).Ry=zeros(length(pars.(pf{ipf}).bpmind),4);
  415. for ibpm=1:length(pars.(pf{ipf}).bpmind)
  416. if pars.(pf{ipf}).targetInd<pars.(pf{ipf}).bpmind(ibpm)
  417. [stat,R]=RmatAtoB(pars.(pf{ipf}).targetInd,pars.(pf{ipf}).bpmind(ibpm));
  418. if stat{1}~=1
  419. return
  420. end
  421. pars.(pf{ipf}).Rx(ibpm,:)=[R(1,1) R(1,2) R(1,3) R(1,4)];
  422. pars.(pf{ipf}).Ry(ibpm,:)=[R(3,1) R(3,2) R(3,3) R(3,4)];
  423. else
  424. dsbpm=pars.(pf{ipf}).bpmind(find(pars.(pf{ipf}).bpmind>pars.(pf{ipf}).targetInd,1));
  425. if isempty(dsbpm)
  426. stat{1}=-1; stat{2}='Must be one downstream bpm provided!';
  427. return
  428. end
  429. [stat,R]=RmatAtoB(pars.(pf{ipf}).bpmind(ibpm),pars.(pf{ipf}).targetInd);
  430. if stat{1}~=1
  431. return
  432. end
  433. [stat,R2]=RmatAtoB(pars.(pf{ipf}).bpmind(ibpm),dsbpm);
  434. if stat{1}~=1
  435. return
  436. end
  437. pars.(pf{ipf}).Rij{ibpm}=R;
  438. pars.(pf{ipf}).Rik{ibpm}=R2;
  439. end
  440. end
  441. end
  442. end
  443. function pars=apCalc(pars,apName)
  444. pars.(apName).aper_x=[];
  445. pars.(apName).aper_xp=[];
  446. pars.(apName).aper_y=[];
  447. pars.(apName).aper_yp=[];
  448. if strcmp(pars.(apName).shape,'ellipse')
  449. a1=1/pars.(apName).xwid^2; a2=1/pars.(apName).ywid^2;
  450. b1=1/pars.(apName).xpwid^2; b2=1/pars.(apName).ypwid^2;
  451. c1=-(pars.(apName).xrot/45)*sqrt(a1*b1)/2;
  452. c2=-(pars.(apName).yrot/45)*sqrt(a2*b2)/2;
  453. [pars.(apName).aper_x,pars.(apName).aper_xp]=ellipse([a1 c1;c1 b1],0,0);
  454. [pars.(apName).aper_y,pars.(apName).aper_yp]=ellipse([a2 c2;c2 b2],0,0);
  455. elseif strcmp(pars.(apName).shape,'rectangle')
  456. pars.(apName).aper_x=[linspace(-pars.(apName).xwid,pars.(apName).xwid,1000) ones(1,1000).*pars.(apName).xwid ...
  457. linspace(pars.(apName).xwid,-pars.(apName).xwid,1000) -ones(1,1000).*pars.(apName).xwid];
  458. pars.(apName).aper_xp=[ones(1,1000).*pars.(apName).xpwid linspace(pars.(apName).xpwid,-pars.(apName).xpwid,1000) ...
  459. ones(1,1000).*-pars.(apName).xpwid linspace(-pars.(apName).xpwid,pars.(apName).xpwid,1000)];
  460. pars.(apName).aper_y=[linspace(-pars.(apName).ywid,pars.(apName).ywid,1000) ones(1,1000).*pars.(apName).ywid ...
  461. linspace(pars.(apName).ywid,-pars.(apName).ywid,1000) -ones(1,1000).*pars.(apName).ywid];
  462. pars.(apName).aper_yp=[ones(1,1000).*pars.(apName).ypwid linspace(pars.(apName).ypwid,-pars.(apName).ypwid,1000) ...
  463. ones(1,1000).*-pars.(apName).ypwid linspace(-pars.(apName).ypwid,pars.(apName).ypwid,1000)];
  464. xang=(pars.(apName).xrot/180)*pi; yang=(pars.(apName).yrot/180)*pi;
  465. ROTx=[cos(xang) -sin(xang); sin(xang) cos(xang)];
  466. ROTy=[cos(yang) -sin(yang); sin(yang) cos(yang)];
  467. newAper_x=ROTx*[pars.(apName).aper_x; pars.(apName).aper_xp];
  468. pars.(apName).aper_x=newAper_x(1,:); pars.(apName).aper_xp=newAper_x(2,:);
  469. newAper_y=ROTy*[pars.(apName).aper_y; pars.(apName).aper_yp];
  470. pars.(apName).aper_y=newAper_y(1,:); pars.(apName).aper_yp=newAper_y(2,:);
  471. end
  472. pars.(apName).aper_x=pars.(apName).aper_x+pars.(apName).xoff;
  473. pars.(apName).aper_xp=pars.(apName).aper_xp+pars.(apName).xpoff;
  474. pars.(apName).aper_y=pars.(apName).aper_y+pars.(apName).yoff;
  475. pars.(apName).aper_yp=pars.(apName).aper_yp+pars.(apName).ypoff;
  476. function [bpmind instrind]=bpmCheck(bpmind)
  477. global INSTR
  478. % check HW exists and want to use bpm list
  479. % get bpm info from BPM Tool
  480. instrind=[];
  481. [stat data] = FlBpmToolFn('GetData');
  482. if stat{1}~=1
  483. return
  484. end
  485. goodbpm=data.global.hw & data.global.use;
  486. goodinst=ismember(cellfun(@(x) x.Index,INSTR),bpmind);
  487. instrind=find(goodbpm & goodinst);
  488. if isempty(instrind)
  489. bpmind=[];
  490. else
  491. bpmind=arrayfun(@(x) INSTR{x}.Index,instrind);
  492. end