source: MML/trunk/mml/setpv.m @ 4

Last change on this file since 4 was 4, checked in by zhangj, 11 years ago

Initial import--MML version from SOLEIL@2013

File size: 41.0 KB
Line 
1function ErrorFlag = setpv(varargin)
2%SETPV - Setpoint change of the online system or model
3%
4%  FamilyName Method
5%  ErrorFlag = setpv(Family, Field, NewSP, DeviceList, WaitFlag)
6%
7%  Data Structure
8%  ErrorFlag = setpv(DataStructure, WaitFlag)
9%
10%  ChannelName (EPICS/TANGO) Method
11%  ErrorFlag = setpv(TangoName, NewSP, WaitFlag)
12%  ErrorFlag = setpv(ChannelName, NewSP, WaitFlag)
13%  ErrorFlag = setpv(ChannelName, Field, NewSP, WaitFlag)
14%
15%  CommonName Method
16%  ErrorFlag = setpv(CommonNames, NewSP, WaitFlag)
17%  ErrorFlag = setpv(CommonNames, Field, NewSP, WaitFlag)
18%  ErrorFlag = setpv(Family, Field, NewSP, CommonNames, WaitFlag)
19%
20%  INPUTS
21%  1. Family - FamilyName
22%              Data Structure
23%              Channel Name or matrix of Channel Names (see note #5)
24%              Tango Name or matrix of Tango Names
25%              AcceleratorObject
26%              Use Family=[] in CommonName method to search all Families
27%              (or Cell Array of inputs)
28%
29%  2. Field - AcceleratorObject Field name ('Monitor', 'Setpoint', etc)
30%             {Default: 'Monitor' or '' for ChannelNames method}
31%             If Family is a cell array then Field must be a cell array
32%
33%  3. NewSP - New Setpoints or cell array of Setpoints
34%             Note: Present, only LabCA can handle string setpoints.  String setpoints
35%                   will fail if hw2physics or physics2hw are needed.
36%
37%  4. DeviceList - ([Sector Device #] or [element #]) {Default or empty list: whole family}
38%                  Note: all numerical inputs must be column vectors
39%     CommonName - Common name can replace a DeviceList (scalar or vector outputs)
40%
41%  5. WaitFlag - 0    -> return immediately {Default}
42%                > 0  -> wait until ramping is done then adds an extra delay equal to WaitFlag
43%                = -1 -> wait until ramping is done
44%                = -2 -> wait until ramping is done then adds an extra delay for fresh data
45%                        from the BPMs
46%                = -3 -> wait until ramping is done then adds an extra delay for fresh data
47%                        from the tune measurement system
48%                = -4 -> wait until ramping is done then wait for a carriage return
49%     Note: For channel names, it is assumed the ramp time is immediate.
50%
51%  6. Units flag overrides
52%     'Physics'  - Use physics  units
53%     'Hardware' - Use hardware units
54%
55%  7. Mode flag overrides
56%     'Online' - Set data online
57%     'Model'  - Set data on the model
58%     'Manual' - Set data manually
59%
60%  8. 'Abs' or 'Absolute'   - Absolute setpoint change {Default}
61%     'Inc' or 'Incremental' - Incremental setpoint change
62%
63%  OUTPUTS
64%  1. ErrorFlag - 0   -> OK
65%                else -> error or warning condition occurred
66%     Note: ErrorFlag is only used if AD.ErrorWarningLevel < 0, otherwise a Matlab error
67%           in issued.  Use try;catch statements to catch the errors.
68%
69%  NOTES
70%  1. For data structure inputs:
71%     Family     = DataStructure.FamilyName (This field must exist)
72%     Field      = DataStructure.Field      (Field can be overridden on the input line)
73%     NewSP      = DataStructure.Data       (NewSP can be overridden on the input line)
74%     DeviceList = DataStructure.DeviceList (DeviceList can be overridden on the input line)
75%     Units      = DataStructure.Units      (Units can be overridden on the input line)
76%     (The Mode field is ignored!)
77%
78%  2. The number of colomns of NewSP and DeviceList must be equal,
79%     or NewSP must be a scalar.  If NewSP is a scalar, then all
80%     devices in DeviceList will be set to the same value.
81%
82%  3. When using cell array all inputs must be the same size cell array
83%     and the output will also be a cell array.  Field and WaitFlag can be
84%     cells but they don't have to be.
85%
86%  4. ChannelName method:
87%     a. Always Online!
88%     b. The optional Field input is added as a .Field to the channel name
89%     c. If use setpv(ChannelName, NewSP, WaitFlag) then NewSP must a numeric.
90%        Use setpv(ChannelName, '',NewSP, WaitFlag) if NewSP is a string.
91%
92%  5. For cell array inputs:
93%     a. Input 1 defines the maximum size of all cells
94%     b. The cell array size must be 1 or equal to the number of cell in input #1
95%     c. WaitFlag can be a cell but it doesn't have to be.
96%
97%  6. WaitFlag
98%     a. If no change is seen on the AM then an error will occur.  The tolerance for this
99%        may need to be changed depending on the accelerator (edit the end of this function to do so)
100%     b. The delay for WaitFlag = -2 is in the AD.  It is often better to use the FreshDataFlag when
101%        getting BPM data but the data must to noisy for this to work.
102%
103%  7. Strings - when setting string the Field input must exist otherwise the setpoint will be
104%               confused for a Field.
105%
106%  8. If say Golden is a software field in the MML structure in the BPMx family, then
107%     setpv('BPMx','Golden', NewValue, DeviceList) will set the data in that field.
108%
109%  EXAMPES
110%  1. setpv('HCM','Setpoint',1.23);               Sets the entire HCM family to 1.23
111%  2. setpv({'HCM','VCM'},'Setpoint',{10.4,5.3}); Sets the entire HCM family to 10.4 and VCM family to 5.3
112%  3. setpv('HCM','Setpoint',1.23,[1 3]);    Simple DeviceList method
113%  4. setpv('HCM','Setpoint',1.23, 3);       Simple ElementList method
114%  5. setpv(AO('HCM'),'Setpoint',1.5,[1 2]);     If AO is a properly formatted AcceleratorObject Structure
115%                                                    then this sets the 1st sector, 2nd element to 1.5
116%  6. setpv('HCM','Setpoint',1.23,'1CX3');   CommonName method with Family specified (spear3 naming convection)
117%  7. setpv([],'Setpoint',1.23,'1CX3');      CommonName method without Family (spear3 naming convection)
118%
119%  See also getam, getsp, getpv, setsp, steppv, stepsp, setpvmodel, setpvonline
120%
121%  Written by Greg Portmann
122
123
124% Defaults
125WaitFlagDefault = 0;
126FieldDefault = 'Setpoint';
127
128
129%%%%%%%%%%%%%%%%%
130% Input Parsing %
131%%%%%%%%%%%%%%%%%
132Field = FieldDefault;
133IncrementalFlag = 0;
134DeviceList = [];
135WaitFlag = [];
136ModeFlag = '';
137UnitsFlag = '';
138InputFlags = {};
139InputFlags2 = {};
140
141for i = length(varargin):-1:1
142    if isstruct(varargin{i})
143        % Ignor structures
144    elseif iscell(varargin{i})
145        % Ignor cells
146    elseif isa(varargin{i},'AccObj')
147        AccObj1 = struct(varargin{i});
148        Families = fieldnames(AccObj1);
149        j = 0;
150        for k = 1:length(Families)
151            if ~isempty(AccObj1.(Families{k}))
152                j = j + 1;
153                tmpcell{j} = AccObj1.(Families{k});
154            end
155        end
156        if length(tmpcell) == 1
157            varargin{i} = tmpcell{1};
158        else
159            varargin{i} = tmpcell;
160        end
161    elseif strcmpi(varargin{i},'struct')
162        % Remove and ignor
163        varargin(i) = [];
164    elseif strcmpi(varargin{i},'numeric')
165        % Remove and ignor
166        varargin(i) = [];
167    elseif strcmpi(varargin{i},'simulator') || strcmpi(varargin{i},'model')
168        ModeFlag = 'SIMULATOR';
169        InputFlags = [InputFlags varargin(i)];
170        varargin(i) = [];
171    elseif strcmpi(varargin{i},'Online')
172        ModeFlag = 'Online';
173        InputFlags = [InputFlags varargin(i)];
174        varargin(i) = [];
175    elseif strcmpi(varargin{i},'Manual')
176        ModeFlag = 'Manual';
177        InputFlags = [InputFlags varargin(i)];
178        varargin(i) = [];
179    elseif strcmpi(varargin{i},'Special')
180        ModeFlag = 'Special';
181        InputFlags = [InputFlags varargin(i)];
182        varargin(i) = [];
183    elseif strcmpi(varargin{i},'physics')
184        UnitsFlag = 'Physics';
185        InputFlags = [InputFlags varargin(i)];
186        varargin(i) = [];
187    elseif strcmpi(varargin{i},'hardware')
188        UnitsFlag = 'Hardware';
189        InputFlags = [InputFlags varargin(i)];
190        varargin(i) = [];
191    elseif strcmpi(varargin{i},'Inc') || strcmpi(varargin{i},'Incremental')
192        IncrementalFlag = 1;
193        InputFlags = [InputFlags varargin(i)];
194        varargin(i) = [];
195    elseif strcmpi(varargin{i},'Abs') || strcmpi(varargin{i},'Absolute')
196        IncrementalFlag = 0;
197        InputFlags = [InputFlags varargin(i)];
198        varargin(i) = [];
199    elseif strcmpi(varargin{i},'String')
200        % Remove and ignor
201        varargin(i) = [];
202    elseif strcmpi(varargin{i},'Retry')
203        InputFlags = [InputFlags varargin(i)];
204        InputFlags2 = [InputFlags2 varargin(i)];
205        varargin(i) = [];
206    elseif strcmpi(varargin{i},'NoRetry')
207        InputFlags = [InputFlags varargin(i)];
208        InputFlags2 = [InputFlags2 varargin(i)];
209        varargin(i) = [];
210    end
211end
212
213if isempty(varargin)
214    error('Not enough inputs');
215end
216
217Family = varargin{1};
218
219
220%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221% CELL OR CELL ARRAY INPUT %
222%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223if iscell(varargin{1})
224    % Iterate on each cell
225    % ErrorFlag = setpv(Family, Field, NewSP, DeviceList, WaitFlag)
226    % ErrorFlag = setpv(DataStructure, WaitFlag)
227    % ErrorFlag = setpv(ChannelName, NewSP)
228    % ErrorFlag = setpv(Family, Field, NewSP, CommonNames, WaitFlag)
229
230    % Set everything with WaitFlag==0
231    DoItAgainFlag = 0;
232    ErrorFlag = 0;
233    for i = 1:size(varargin{1},1)
234        for j = 1:size(varargin{1},2)
235
236            % Build the input line
237            for k = 1:length(varargin)
238                if ~iscell(varargin{k})
239                    Inputs1{1,k} = varargin{k};
240                elseif length(varargin{k}) == 1
241                    Inputs1{1,k} = varargin{k}{1};
242                elseif (size(varargin{k},1) == size(varargin{1},1)) && (size(varargin{k},2) == size(varargin{1},2))
243                    Inputs1{1,k} = varargin{k}{i,j};
244                else
245                    error('When using cells, all the cells must be the same size or length 1 (repeated).');
246                end
247            end
248
249            % Remove WaitFlag on first set if WaitFlag~=0 on any cell
250            if isstruct(varargin{1}{i,j})
251                if length(Inputs1) >= 2
252                    if ischar(Inputs1{2})
253                        % Inputs1{2} might be 'setpoint' due to setsp
254                        if length(Inputs1) >= 3
255                            if Inputs1{3} ~= 0
256                                DoItAgainFlag = 1;
257                                Inputs1{2} = 0;
258                            end
259                            Inputs1(3) = [];
260                        else
261                            DoItAgainFlag = 1;
262                        end
263                    else
264                        if Inputs1{2} ~= 0
265                            DoItAgainFlag = 1;
266                            Inputs1{2} = 0;
267                        end
268                    end
269                else
270                    DoItAgainFlag = 1;
271                end
272            elseif length(Inputs1) == 2
273                % For ChannelName just set once
274            elseif length(Inputs1) == 3
275                DoItAgainFlag = 1;
276                Inputs1{4} = [];
277                Inputs1{5} = 0;
278            elseif length(Inputs1) == 4
279                DoItAgainFlag = 1;
280                Inputs1{5} = 0;
281            elseif length(Inputs1) >= 5
282                if Inputs1{5} ~= 0
283                    DoItAgainFlag = 1;
284                    Inputs1{5} = 0;
285                end
286            end
287           
288            % Make the setpoint change
289            ErrorFlagNew = setpv(Inputs1{:}, InputFlags{:});
290            ErrorFlag = ErrorFlag | any(ErrorFlagNew);
291        end
292    end
293
294    % Wait for the waitflag
295    if DoItAgainFlag
296        for i = 1:size(varargin{1},1)
297            for j = 1:size(varargin{1},2)
298
299                % Build the input line
300                for k = 1:length(varargin)
301                    if ~iscell(varargin{k})
302                        Inputs1{1,k} = varargin{k};
303                    elseif length(varargin{k}) == 1
304                        Inputs1{1,k} = varargin{k}{1};
305                    elseif (size(varargin{k},1) == size(varargin{1},1)) && (size(varargin{k},2) == size(varargin{1},2))
306                        Inputs1{1,k} = varargin{k}{i,j};
307                    else
308                        error('When using cells, all the cells must be the same size or length 1 (repeated).');
309                    end
310                end
311
312                % Make the setpoint change
313                ErrorFlagNew = setpv(Inputs1{:}, InputFlags{:});
314                ErrorFlag = ErrorFlag | any(ErrorFlagNew);
315            end
316        end
317    end
318
319    return
320end
321%%%%%%%%%%%%%%%%%%
322% End cell input %
323%%%%%%%%%%%%%%%%%%
324
325
326
327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328% COMMONNAME - Commonname input with no family input %
329%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330if isempty(Family)
331    % Common names with Family = []
332    % [], Field, NewSP, CommonNames
333   
334    if length(varargin) >= 2
335        if ischar(varargin{2})
336            Field = varargin{2};
337            varargin(2) = [];
338        end
339    end
340    if isempty(Field)
341        Field = FieldDefault;
342    end
343    if length(varargin) >= 2
344        NewSP = varargin{2};
345    else
346        error('New setpoint not found on input line');
347    end
348    if length(varargin) >= 3
349        CommonNames = varargin{3};
350    else
351        CommonNames = [];
352    end
353    if length(varargin) >= 4
354        WaitFlag = varargin{4};
355    end
356    if isempty(WaitFlag)
357        WaitFlag = WaitFlagDefault;
358    end
359
360    if size(NewSP,1) == 1
361        % Set all elements to same value
362        NewSP = ones(size(CommonNames,1),1) * NewSP;
363    elseif size(NewSP,1) == size(CommonNames,1)
364        % Input OK
365    else
366        error('Size of NewSP must be equal to the number of Commonnames or a scalar!');
367    end
368
369    % Convert all the common names to Family and Device lists
370    [DeviceList, Family, ErrorFlag] = common2dev(CommonNames, Field);
371
372    % If all the families are the same then compress them
373    FamilyTest = unique(Family, 'rows');
374
375    if size(FamilyTest, 1) == 1
376        % 1 Family, Multiple devices are ok
377        ErrorFlag = setpv(FamilyTest, Field, NewSP, DeviceList, WaitFlag, InputFlags{:});
378    else
379        % Multiple families (loop)
380        % It has to be in a loop for the simulator and to pickup special functions
381        for i = 1:size(Family,1)
382            ErrorFlag1 = setpv(Family(i,:), Field, NewSP(i,:), DeviceList(i,:), 0, InputFlags{:});
383            ErrorFlag = ErrorFlag | ErrorFlag1;
384        end
385        if WaitFlag
386            for i = 1:size(Family,1)
387                ErrorFlag1 = setpv(Family(i,:), Field, NewSP(i,:), DeviceList(i,:), WaitFlag, InputFlags{:});
388                ErrorFlag = ErrorFlag | ErrorFlag1;
389            end
390        end
391    end
392   
393    return
394end
395%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396% End CommonName input with no family input %
397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398
399
400
401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
402% Parce inputs depending on Data structure, AO structure, Family, ChannelName method %
403%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404if isstruct(Family)
405    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406    % STRUCTURE INPUTS - Data structure or AO structure %
407    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
408    if isfield(varargin{1},'FamilyName') && isfield(varargin{1},'Field')
409        % setpv(DataStruct, Field, NewSP, WaitFlag)
410        %   Select FamilyName, DeviceList, Units from the structure (if not on the input line)
411        %   Mode in the structure is ignored
412        Family = varargin{1}.FamilyName;
413
414        % The only input for a Data Structure can Field and WaitFlag
415        Field = '';
416        if length(varargin) >= 2
417            if ischar(varargin{2})
418                Field = varargin{2};
419                varargin(2) = [];
420            end
421        end
422        if isempty(Field)
423            Field = varargin{1}.Field;
424        end
425
426        NewSP = varargin{1}.Data;
427        DeviceList = varargin{1}.DeviceList;
428
429        if length(varargin) >= 2
430           WaitFlag = varargin{2};
431        end
432
433        %if length(varargin) >= 2
434        %    NewSP = varargin{2};
435        %else
436        %    NewSP = varargin{1}.Data;
437        %end
438        %if length(varargin) >= 3
439        %    DeviceList = varargin{3};
440        %else
441        %    DeviceList = varargin{1}.DeviceList;
442        %end
443        %if length(varargin) >= 4
444        %    WaitFlag = varargin{4};
445        %end
446
447        [FamilyIndex, AO] = isfamily(Family);
448
449        % Change Units to the data structure units (command-line override comes latter)
450        if isfield(AO, Field)
451            AO.(Field).Units = varargin{1}.Units;
452        end
453       
454        if FamilyIndex == 0
455            error('Unknown family in the data structure');
456        end
457
458    elseif isfield(varargin{1},'FamilyName')
459        % AO structure - use the AO structure directly
460        % setpv(AO, Field, NewSP, DeviceList, WaitFlag)
461
462        Field = '';
463        if length(varargin) >= 2
464            if ischar(varargin{2})
465                Field = varargin{2};
466                varargin(2) = [];
467            end
468        end
469        if length(varargin) >= 2
470            NewSP = varargin{2};
471        else
472            error('New setpoint not found on input line');
473        end
474        if length(varargin) >= 3
475            DeviceList = varargin{3};
476        else
477            DeviceList = varargin{1}.DeviceList;
478            iStatus = find(varargin{1}.Status == 0);
479            DeviceList(iStatus,:) = [];
480        end
481        if length(varargin) >= 4
482            WaitFlag = varargin{4};
483        end
484
485        FamilyIndex = 1;
486        AO = Family;
487
488    else
489        error('Input #1 of unknown type');
490    end
491
492else
493
494    % Family or ChannelName/TangoName is the only thing left
495    [FamilyIndex, AO] = isfamily(Family);
496
497    if FamilyIndex
498
499        %%%%%%%%%%%%%%
500        % FamilyName %
501        %%%%%%%%%%%%%%
502        if length(varargin) >= 2
503            if ischar(varargin{2})
504                Field = varargin{2};
505                varargin(2) = [];
506            end
507        end
508        if isempty(Field)
509            Field = FieldDefault;
510        end
511        if length(varargin) >= 2
512            NewSP = varargin{2};
513        else
514            error('New setpoint not found on input line');
515        end
516        if length(varargin) >= 3
517            DeviceList = varargin{3};
518        end
519        if length(varargin) >= 4
520            WaitFlag = varargin{4};
521        end
522        if isempty(WaitFlag)
523            WaitFlag = WaitFlagDefault;
524        end
525
526    else
527
528        % Look to see if it's a channel name or a common name
529        % Just check the first name so it's a faster test
530        [DeviceListTest, FamilyTest] = common2dev(Family(1,:));
531
532        if ~isempty(FamilyTest)
533            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534            % Common names where the family was the common name %
535            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
536           
537            % The DeviceList should not be on the input line!
538
539            if length(varargin) >= 2
540                if ischar(varargin{2})
541                    Field = varargin{2};
542                    varargin(2) = [];
543                end
544            end
545            if isempty(Field)
546                Field = FieldDefault;
547            end
548            if length(varargin) >= 2
549                NewSP = varargin{2};
550            else
551                error('New setpoint not found on input line');
552            end
553            if length(varargin) >= 3
554                WaitFlag = varargin{3};
555            end
556            if isempty(WaitFlag)
557                WaitFlag = WaitFlagDefault;
558            end
559
560            CommonNames = Family;
561
562            if size(NewSP,1) == 1
563                % Set all elements to same value
564                NewSP = ones(size(CommonNames,1),1) * NewSP;
565            elseif size(NewSP,1) == size(CommonNames,1)
566                % Input OK
567            else
568                error('Size of NewSP must be equal to the number of Commonnames or a scalar!');
569            end
570
571            % Convert all the common names to Family and Device lists
572            [DeviceList, Family, ErrorFlag] = common2dev(CommonNames);
573
574            % If all the families are the same then compress them
575            FamilyTest = unique(Family, 'rows');
576
577            if size(FamilyTest, 1) == 1
578                % 1 Family, Multiple devices are ok
579                ErrorFlag = setpv(FamilyTest, Field, NewSP, DeviceList, WaitFlag, InputFlags{:});
580            else
581                % Multiple families (loop)
582                % It has to be in a loop for the simulator and to pickup special functions
583                for i = 1:size(Family,1)
584                    ErrorFlag1 = setpv(Family(i,:), Field, NewSP(i,:), DeviceList(i,:), 0, InputFlags{:});
585                    ErrorFlag = ErrorFlag | ErrorFlag1;
586                end
587                if WaitFlag
588                    for i = 1:size(Family,1)
589                        ErrorFlag1 = setpv(Family(i,:), Field, NewSP(i,:), DeviceList(i,:), WaitFlag, InputFlags{:});
590                        ErrorFlag = ErrorFlag | ErrorFlag1;
591                    end
592                end
593            end
594                   
595            % Return for common names
596           return
597           
598        else
599
600            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
601        % CHANNEL NAME or TANGO NAME - Online Only %
602            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603
604            % setpv(ChannelName, Field, NewSP, WaitFlag)
605            % setpv(ChannelName, Field, NewSP)
606            % setpv(ChannelName, NewSP, WaitFlag)  % NewSP cannot be string for this case
607            % setpv(ChannelName, NewSP)
608            Field = '';
609            if length(varargin) == 2
610                % setpv(ChannelName, NewSP)
611                NewSP = varargin{2};
612            elseif length(varargin) >= 3
613                if ischar(varargin{2})
614                    Field = varargin{2};
615                    varargin(2) = [];
616                end
617                NewSP = varargin{2};
618            end
619
620            if length(varargin) >= 3
621                WaitFlag = varargin{3};
622            else
623                WaitFlag = [];
624            end
625            if isempty(WaitFlag)
626                WaitFlag = WaitFlagDefault;
627            end
628
629            % Don't set NaN's for now???
630            %iNaN = find(isnan(NewSP));
631            %if ~isempty(iNaN)
632            %    Family(iNaN,:) = [];
633            %    NewSP(iNaN,:) = [];
634            %end
635
636        % Can't use overrides with channel / TANGO name method
637            if ~isempty(UnitsFlag)
638            error('You cannot change the units when using channel or attribute names.')
639            end
640            if ~(isempty(ModeFlag) | strcmpi(ModeFlag, 'Online'))
641                error('Channel or Tango names only have an ''Online'' Mode.')
642            end
643
644        % Get rid of repeated & blank channel or attribute names
645            [Family, i] = unique(Family, 'rows');
646            if size(NewSP,1) ~= 1
647                NewSP = NewSP(i,:);
648            end
649            if isempty(deblank(Family(1,:)))
650                Family(1,:) = [];
651                if size(NewSP,1) ~= 1
652                    NewSP(1,:) = [];
653                end
654            end
655
656            % Add Field to Family.Field
657            if ~isempty(Field)
658                Family = strcat(Family, ['.',Field]);
659            end
660           
661            % Incremental change in the setpoint
662            if IncrementalFlag
663                % Note: ModeFlag, UnitsFlag are ignored for channel name inputs
664                %NewSP = NewSP + getpv(Family);
665                if size(NewSP,2) == 1
666                    SPpresent = getpvonline(Family, '', 1);
667                else
668                    SPpresent = getpvonline(Family);
669                end
670                NewSP = NewSP + SPpresent;
671            else
672                if size(NewSP,1) == 1 && size(Family,1) > 1
673                    % Set all elements to same value
674                    NewSP = NewSP * ones(size(Family,1),1);
675                end
676            end
677
678
679            %%%%%%%%%%%%
680            % Set data %
681            %%%%%%%%%%%%
682            % Could add N-Steps here???
683            ErrorFlag = setpvonline(Family, NewSP);
684
685
686            % Add a delay based on the WaitFlag
687            if WaitFlag > 0
688                sleep(WaitFlag);
689            elseif WaitFlag == -2
690                [N, BPMDelay] = getbpmaverages;
691                BPMDelay = 2.2 * max(BPMDelay);
692                if ~isempty(BPMDelay)
693                    sleep(BPMDelay);
694                end
695            elseif WaitFlag == -3
696                TuneDelay = getfamilydata('TuneDelay');
697                if ~isempty(TuneDelay)
698                    sleep(TuneDelay);
699                end
700            elseif WaitFlag == -4
701                tmp = input('   Setpoint changed.  Hit return ready. ');
702            end
703
704            return
705        end
706    end
707end
708% End input selection:  data structure, AO structure, family, commonname, and channelname method
709
710
711
712%%%%%%%%%%%%%%%%%%%%%%%%%
713% SET DATA FOR FAMILIES %
714%%%%%%%%%%%%%%%%%%%%%%%%%
715
716% Family = FamilyName or AO structure with DeviceList or CommonName List
717
718if isempty(DeviceList)                   % This is a very important line, it determines the default behavior
719    DeviceList = family2dev(Family);     % Default behavior comes from family2dev
720    %DeviceList = family2dev(Family,1);  % Good status only
721    %DeviceList = AO.DeviceList;         % All devices
722end
723
724% If DeviceList is a string it's a common name list
725if ischar(DeviceList)
726    DeviceList = common2dev(DeviceList, AO);
727end
728
729% Convert DeviceList format to ElementList format
730if (size(DeviceList,2) == 1)
731    DeviceList = elem2dev(Family, DeviceList);
732end
733
734if isempty(WaitFlag)
735    WaitFlag = WaitFlagDefault;
736end
737
738
739% Look for command-line over rides
740if ~isempty(UnitsFlag)
741    AO.(Field).Units = UnitsFlag;
742end
743if ~isempty(ModeFlag)
744    AO.(Field).Mode = ModeFlag;
745end
746
747
748if size(NewSP,1) == 1 && size(DeviceList,1) > 1
749    % Set all elements to same value
750    NewSP = NewSP * ones(size(DeviceList,1),1);
751
752elseif size(NewSP,1) ~= size(DeviceList,1)
753    % This is either an error or NewSP equals the number of power supplies (not magnets)
754    [DeviceList, ii, jj] = unique(DeviceList, 'rows');
755    [TangoNames, i, j] = unique(family2tango(Family, DeviceList), 'rows');
756   
757    if size(NewSP,1) == size(TangoNames,1)
758        NewSP = NewSP(j);
759        NewSP = NewSP(ii);
760    else
761        error('The number of setpoints does not equal the number of magnets or magnet power supplies.');
762    end
763end
764
765
766% Incremental change in the setpoint
767if IncrementalFlag
768    SPold = getpv(Family, Field, DeviceList, AO.(Field).Units, AO.(Field).Mode, InputFlags2{:});
769    if ~any(isnan(SPold))
770        NewSP = NewSP + SPold;
771    else
772        ErrorFlag = -1;
773        return;
774    end
775end
776
777
778% Main call for all applications except ChannelName / TangoName method
779ErrorFlag = local_setpv(AO, Field, NewSP, DeviceList, WaitFlag, InputFlags2{:});
780
781
782%%%%%%%%%%%%%%%%
783% End of setpv %
784%%%%%%%%%%%%%%%%
785return
786
787
788
789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
790%  Main Function for Setting Data using the Accelerator Object  %
791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
792function ErrorFlag = local_setpv(AO, Field, NewSP, DeviceList, WaitFlag, varargin)
793%  INPUTS
794%  1. AO - the ACCELERATOR_OBJECT structure for the called family
795%  2. Field - 'Monitor' or 'Setpoint'
796%  3. NewSP - setpoint values
797%  4. DeviceList - Device list
798%
799%  OUTPUTS
800%  1. ErrorFlag - 0 if OK, else 1
801%
802%  NOTES
803%  1. AO comes directly from the main AcceleratorObject family
804%  2. Field is which field to use
805%  3. DeviceList is which device list to use
806%  4. AO.DeviceList is the entire device list
807%
808%  Note: local_setpv can not be used for channel names
809
810
811TimeOutPeriodOnWaitFlag = 10;  % Seconds of monitor not changing
812ErrorFlag = 0;
813
814
815% Don't set NaN's for now???
816iNaN = find(isnan(NewSP));
817if ~isempty(iNaN)
818    NewSP(iNaN,:) = [];
819    DeviceList(iNaN,:) = [];
820end
821
822
823% Check for empty device list
824if isempty(DeviceList)
825    AM = [];
826    %fprintf('   WARNING:  No devices to get for Family %s\n', AO.FamilyName));
827    return;
828end
829
830
831% Find the index for where the desired data is in the total device list
832DeviceListTotal = AO.DeviceList;
833[DeviceIndex, iNotFound] = findrowindex(DeviceList, DeviceListTotal);
834if length(iNotFound) > 0
835    % Device not found
836    for i = 1:length(iNotFound)
837        fprintf('   No devices to get for Family %s(%d,%d)\n', AO.FamilyName, DeviceList(i,1), DeviceList(i,2));
838    end
839    error(sprintf('%d Devices not found', length(iNotFound)));
840end
841
842
843% If Field is not found in the AO, it is unclear what to do next.
844% I could error here, but it's convenient to try to set
845% EPICS subfields or other simulator fields at this point.
846if ~isfield(AO, Field)
847    % Try to check it online or simulator
848    if isfield(AO, 'Setpoint')
849        Mode = getfamilydata(AO.FamilyName, 'Setpoint', 'Mode');
850    elseif isfield(AO, 'Monitor')
851        Mode = getfamilydata(AO.FamilyName, 'Monitor', 'Mode');
852    else
853        Mode = '';
854    end
855    if strcmpi(Mode,'Simulator') || strcmpi(Mode,'Model')
856        ErrorFlag = setpvmodel(AO.FamilyName, Field, NewSP, DeviceList, 'Physics');
857        return
858    end
859
860
861    % Try changing the suffix of the Monitor or Setpoint field
862    if isfield(AO, 'Setpoint')
863        Tango = family2tango(AO, 'Setpoint', DeviceList);
864    elseif isfield(AO, 'Monitor')
865        Tango = family2tango(AO, 'Monitor', DeviceList);
866    else
867        error(sprintf('Field %s not found for Family %s', Field, AO.FamilyName));
868    end
869   
870    % Get rid of repeated & blank TANGO names
871    [Tango, i] = unique(Tango, 'rows');
872    if size(NewSP,1) ~= 1
873        NewSP = NewSP(i,:);
874    end
875    if isempty(deblank(Tango(1,:)))
876        Tango(1,:) = [];
877        if size(NewSP,1) ~= 1
878            NewSP(1,:) = [];
879        end
880    end
881
882    if any(strcmpi(getfamilydata('Machine'),{'spear3','spear'}))
883        % Change the last ':' Field
884        %i = findstr(Channel(1,:),':');
885        %if ~isempty(i)
886        %    Channel(:,i:end) = [];
887        %end
888        %ChannelNew = strcat(Channel, [':',Field]);
889
890        % Since the location of ":" can be different in each row, loop
891        ChannelNew = [];
892        for j = 1:size(Channel,1)
893            i = findstr(Channel(j,:),':');
894            if isempty(i)
895                % I'm not sure what to do if ":" is missing, I'm just add a ":"
896                ChannelNew = strvcat(ChannelNew, [Channel(j,1:i), ':', Field]);
897            else
898                ChannelNew = strvcat(ChannelNew, [Channel(j,1:i), Field]);
899            end
900        end
901        TangoNew = strcat(Tango, [':',Field]);
902    else
903        % Add a .Field
904        TangoNew = strcat(Tango, ['.',Field]);
905    end
906   
907   
908    ErrorFlag = setpvonline(TangoNew, NewSP, varargin{:});
909
910    if WaitFlag > 0
911        sleep(WaitFlag);
912    elseif WaitFlag == -2
913        [N, BPMDelay] = getbpmaverages;
914        BPMDelay = 2.2 * max(BPMDelay);
915        if ~isempty(BPMDelay)
916            sleep(BPMDelay);
917        end
918    elseif WaitFlag == -3
919        TuneDelay = getfamilydata('TuneDelay');
920        if ~isempty(TuneDelay)
921            sleep(TuneDelay);
922        end
923    elseif WaitFlag == -4
924        tmp = input('   Setpoint changed.  Hit return ready. ');
925    end
926    return
927end
928
929
930% Extract 'Mode'
931if isfield(AO.(Field), 'Mode')
932    Mode = AO.(Field).Mode;
933else
934    Mode = 'Online';
935end
936
937
938% Check if Online should really be special
939if strcmpi(Mode, 'Online')
940   if isfield(AO.(Field), 'SpecialFunctionSet')
941       Mode = 'Special';
942   end
943end
944
945
946if ~isstruct(AO.(Field))
947    % If it's not a structure that just set the field
948    % Hardward and physics get ignored
949    setfamilydata(NewSP, AO.FamilyName, Field, DeviceList);
950   
951elseif strcmpi(Mode,'Online')
952    %%%%%%%%%%
953    % Online %
954    %%%%%%%%%%
955
956
957    % Could add N-Steps here???
958
959   
960    % Change to hardware units if in physics units
961    if strcmpi(AO.(Field).Units, 'Physics')
962        NewSP = physics2hw(AO.FamilyName, Field, NewSP, DeviceList);
963    end
964
965    if  strcmpi(AO.(Field).DataType,'scalar')
966       
967        ErrorFlag = setpvonline(AO.(Field).TangoNames(DeviceIndex,:), NewSP, varargin{:});
968       
969    elseif  strcmpi(AO.(Field).DataType,'vector')
970       
971        % There can only be one Tango name for DataType='Vector'
972        TangName = deblank(AO.(Field).TangoNames(1,:));
973       
974        % Get the vector and only load what is requested
975        FullVector = getpvonline(TangName);
976       
977        if isfield(AO.(Field), 'DataTypeIndex')
978            FullVector(AO.(Field).DataTypeIndex(DeviceIndex)) = NewSP;
979        else
980            FullVector(DeviceIndex) = NewSP;
981        end       
982       
983        % Vectorized put
984        ErrorFlag = setpvonline(TangName, FullVector, varargin{:});
985
986    else       
987        % Not a scalar or vector
988        error(sprintf('Unknown DataType %s for family %s.', AO.(Field).DataType, AO.FamilyName));
989    end
990   
991    %%%%%%%%%%%%%%%%%%%%%%%
992    % WaitFlag Processing %
993    %%%%%%%%%%%%%%%%%%%%%%%
994    if WaitFlag && WaitFlag~=-4
995
996        t00 = gettime;
997        [RunFlag, Delta0, Tol] = getrunflag(AO, Field, DeviceList);
998        %fprintf('RunFlag:%d Delta=%f (Tol=%f)\n',RunFlag, Delta0, Tol);
999        RampRate = getramprate(AO, DeviceList, 'Hardware');
1000
1001        if any(Tol == 0) || isempty(Tol)
1002            % Tol should not be set to zero, but if it is then base time-out on percentage of SP
1003            % This many not be a good criterion and may need to be adjusted based on the machine!!!
1004            TimeoutTol = NewSP / 200;   % .5 percent
1005        else
1006            % Check if the Delta has changed by at least a few tolerances in the last TimeOutPeriodOnWaitFlag seconds
1007            % This many not be a good criterion and may need to be adjusted based on the machine!!!
1008            TimeoutTol = 5 * Tol;
1009
1010            % Or base on the ramprate
1011            %if ~isempty(RampRate) & ~any(isnan(RampRate))
1012            %    RR = max(abs(RampRate));
1013            %    if ~isnan(RR)
1014            %        % Base time-out on .1 what the monitor should have changed in TimeOutPeriodOnWaitFlag seconds
1015            %        TimeoutTol = .1 * RR * TimeOutPeriodOnWaitFlag;
1016            %    end
1017            %end
1018        end
1019
1020        t0  = gettime;
1021        while any(RunFlag)
1022            % Pause a little so that the network doesn't get too thrashed
1023            sleep(.1);
1024
1025            [RunFlag, Delta, Tol] = getrunflag(AO, Field, DeviceList);
1026
1027            % Check if the Delta has changed in the last TimeOutPeriodOnWaitFlag seconds
1028            if gettime-t0 > TimeOutPeriodOnWaitFlag
1029                x = (abs(Delta) > Tol) & (abs(abs(Delta)-abs(Delta0)) <= TimeoutTol);
1030                if any(x)
1031                    TangoName = '';
1032                    for i = 1:length(x)
1033                        if x(i)
1034                            TangoNameNext = family2tango(AO.FamilyName,  DeviceList(i,:));
1035                            if ~strcmp(TangoName, TangoNameNext)
1036                                if isfield(AO,'Monitor') & isfield(AO,'Setpoint')
1037                                    fprintf('   %s(%d,%d) SP-AM > Tol and the monitor does not appear to be changing.\n', AO.FamilyName,  DeviceList(i,1), DeviceList(i,2));
1038                                    SP = getsp(AO.FamilyName,  DeviceList(i,:));
1039                                    AM = getam(AO.FamilyName,  DeviceList(i,:));
1040                                    fprintf('           Setpoint = %f,  Monitor = %f,  SP-AM = %f,  getrunflag Delta = %f,  Tolerance = %f\n', SP, AM, SP-AM, Delta(i), Tol(i));
1041                                else
1042                                    fprintf('   %s(%d,%d) timed-out waiting for run flag to change.\n', AO.FamilyName,  DeviceList(i,1), DeviceList(i,2));
1043                                end
1044                            end
1045                            TangoName = TangoNameNext;
1046                        end
1047                    end
1048
1049                    % Decide whether or not to error on a SP-AM problem
1050                    ErrorWarningLevel = getfamilydata('ErrorWarningLevel');
1051                    if isempty(ErrorWarningLevel) || ErrorWarningLevel >= 0
1052                        error(sprintf('Time-Out:  Monitor did not appear to be changing for the last %.1f seconds.', TimeOutPeriodOnWaitFlag));
1053                    elseif ErrorWarningLevel == -1
1054                        warning('Time-Out:  Monitor did not appear to be changing for the last %.1f seconds.', TimeOutPeriodOnWaitFlag);
1055                    elseif ErrorWarningLevel == -2
1056                        try
1057                            % Make some noise
1058                            %sound(cos(1:10000));
1059                        catch
1060                        end
1061                        CommandInput = questdlg( ...
1062                            {'The run flag is not changing.  This is often a', ...
1063                             'Setpoint-Monitor tolerance problem.  Either manually', ...
1064                             'varify that the magnet is at the proper setpoint and', ...
1065                             ' ', ...
1066                             'Continue - recheck the run condition', ...
1067                             'Stop - issue an error and see if there is error handling', ...
1068                             'Ignore the problem and push on'}, ...
1069                            'SETPV Question', ...
1070                            'Continue', ...
1071                            'Stop', ...
1072                            'Ignore', ...
1073                            'Continue');
1074                        switch CommandInput
1075                            case 'Stop'
1076                                error('SP-AM error in setpv.');
1077                            case 'Continue'
1078                            case 'Ignore'
1079                                RunFlag = 0;
1080                        end
1081                    else % ErrorWarningLevel <= -3
1082                        % Do nothing
1083                        ErrorFlag = -1;
1084                    end
1085                end
1086
1087                % Reset Delta0 and timeout timer
1088                Delta0 = Delta;
1089                t0 = gettime;
1090            end
1091        end
1092
1093        % Add extra delay for continued ramping due to the size of the tolerance
1094        if isempty(Tol) && isempty(Delta0)
1095            % If Tol and Delta) are empty, then WaitFlag is probably not wanted
1096            %if WaitFlag < 0
1097            %    WaitFlag = 0;
1098            %end
1099        else
1100            % In case Tol is large, use the min of Tol and the present Delta SP-AM
1101            if any(isnan(RampRate))
1102                % For lack of a better idea: If the RampRate is not defined, calculate what it has been doing.
1103                iNaN = find(isnan(RampRate));
1104                RampRate(iNaN) = abs(Delta0(iNaN) / (gettime-t00));
1105            end
1106            if isempty(RampRate)
1107                % For lack of a better idea: If the RampRate is not defined, calculate what it has been doing.
1108                RampRate = abs(Delta0 / (gettime-t00));
1109            end
1110            if any(RampRate == 0)
1111            else
1112                T = min([(Tol./RampRate) abs(Delta0./RampRate)],[],2);
1113                if ~isempty(max(T))
1114                    sleep(1.05*max(T));
1115                end
1116            end
1117        end
1118    end
1119   
1120    if WaitFlag && ~strcmpi(Mode,'Simulator')
1121        % Add a delay based on the WaitFlag
1122        if WaitFlag > 0
1123            sleep(WaitFlag);
1124        elseif WaitFlag == -2
1125            [N, BPMDelay] = getbpmaverages;
1126            BPMDelay = 2.2 * max(BPMDelay);
1127            if ~isempty(BPMDelay)
1128                sleep(BPMDelay);
1129            end
1130        elseif WaitFlag == -3
1131            TuneDelay = 2.2 * getfamilydata('TuneDelay');
1132            if ~isempty(TuneDelay)
1133                sleep(TuneDelay);
1134            end
1135        elseif WaitFlag == -4
1136            tmp = input('   Setpoint changed.  Hit return ready. ');
1137        end
1138    end
1139
1140
1141elseif strcmpi(Mode,'Manual')
1142    %%%%%%%%%%%%%%%
1143    % Manual mode %
1144    %%%%%%%%%%%%%%%
1145   
1146    % Change to hardware units if in physics units
1147    if strcmpi(AO.(Field).Units, 'Physics')
1148        NewSP = physics2hw(AO.FamilyName, Field, NewSP, DeviceList);
1149    end
1150
1151    % NewSP is always in hardware units at this point   
1152    for i = 1:length(DeviceIndex)
1153        if strcmpi(AO.(Field).Units, 'Hardware')
1154            fprintf('   Manually set:  %s(%d,%d) = %f [%s]\n', AO.FamilyName, AO.DeviceList(DeviceIndex(i),1), AO.DeviceList(DeviceIndex(i),2), NewSP(i), AO.(Field).HWUnits);
1155        else
1156            NewSP(i) = hw2physics(AO.FamilyName, Field, NewSP(i), AO.DeviceList(DeviceIndex(i),:));
1157            fprintf('   Manually set:  %s(%d,%d) = %f [%s]\n', AO.FamilyName, AO.DeviceList(DeviceIndex(i),1), AO.DeviceList(DeviceIndex(i),2), NewSP(i), AO.(Field).PhysicsUnits);
1158        end
1159    end
1160    if length(NewSP) == 1
1161        input(sprintf('   Set device manually and hit return '));
1162    else
1163        input(sprintf('   Set these devices manually and hit return '));
1164    end   
1165    fprintf('   \n');
1166   
1167elseif strcmpi(Mode,'Special')
1168    %===================================
1169    % Special mode (evaluate a function)
1170    %===================================
1171   
1172    % Could add N-Steps here???
1173
1174    % Change to hardware units if in physics units
1175    if strcmpi(AO.(Field).Units, 'Physics')
1176        NewSP = physics2hw(AO.FamilyName, Field, NewSP, DeviceList);
1177    end
1178   
1179    if isfield(AO.(Field), 'SpecialFunctionSet')
1180        ErrorFlag = feval(AO.(Field).SpecialFunctionSet, AO.FamilyName, Field, NewSP, DeviceList, WaitFlag);
1181    else
1182        error(sprintf('No special function specified for Family %s (setpv).', AO.FamilyName));
1183    end
1184   
1185elseif strcmpi(Mode,'Simulator')
1186    %==================
1187    % AT simulator mode
1188    %==================
1189   
1190    ErrorFlag = setpvmodel(AO, Field, NewSP, DeviceList, AO.(Field).Units);
1191   
1192else
1193    error(sprintf('Unknown mode % for family %s.', Mode, AO.FamilyName));
1194end
1195
1196
Note: See TracBrowser for help on using the repository browser.