source: MML/trunk/mml/hw2physics.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: 17.6 KB
Line 
1function S = hw2physics(Family, Field, value, DeviceList, Energy)
2%HW2PHYSICS - Converts from 'Hardware' units to 'Physics' units
3%  ValPhysics = hw2physics(Family, Field, ValHW, DeviceList, Energy)
4%
5%  For data structure inputs:
6%  ValPhysics = hw2physics(DataStructure, Energy)
7%
8%  HW2PHYSICS converts the values in 'Hardware' units read from PV's
9%  to 'Physics' units using the conversion function and conversion paramaters
10%  stored in the AO fields HW2PhysicsFcn and HW2PhysicsParams
11%
12%  Energy can be anything getenergy accepts, like 'Model' or 'Online' {Default: 'Production'}
13%
14%  INPUTS
15%  1.  Family - Familyname
16%  2.  Field - Typically 'Monitor' or 'Setpoint'
17%  3.  value - Data for conversion
18%  4.  DeviceList - List of devices
19%  5.  Energy - Extra parameter for energy. Default is 'Production'
20%
21%  OUTPUTS
22%  1. S - Result of conversion from hardwareto physics units
23%
24%  NOTES
25%  1. Field is typically 'Monitor' or 'Setpoint'
26%  2. For structure inputs, if the data is already in physics units
27%     then no conversion will be done!
28%  3. Energy may not be dealt with directly in this function, it
29%     depends on how HW2PhysicsFcn deals with energy change.
30%  4. The gain/offset conversions are done in raw2real & real2raw.
31%
32%  See also hw2physic, raw2real, real2raw
33%
34%  Written by A. Terebilo and G. Portmann
35
36S = [];
37
38if nargin < 1
39    error('1 (data structure), 3, or 4 inputs required');
40end
41
42if ischar(Family)
43    if nargin < 3
44        error('3-4 inputs required');
45    end
46    if nargin < 4
47        DeviceList = [];
48    end
49    if isempty(DeviceList)
50        DeviceList = family2dev(Family);
51    end
52    if nargin < 5
53        Energy = 'Production';
54    end
55   
56    if size(DeviceList,1) ~= size(value,1)
57        if size(value,1) == 1
58            value = ones(size(DeviceList,1),1) * value;
59        else
60            error('The length of ValHW must match the number of devices');
61        end
62    end
63   
64    FunctionStr = getfamilydata(Family, Field, 'HW2PhysicsFcn');
65    Params      = getfamilydata(Family, Field, 'HW2PhysicsParams', DeviceList);
66   
67   
68    % First convert to "corrected" hardware units (usually based on LOCO gains)
69    value = raw2real(Family, Field, value, DeviceList);
70
71    if isempty(FunctionStr)
72        if isempty(Params)
73            % No info on how to convert, so use a gain of 1
74            S = value;
75        else
76            % If no function, use a constant scaling
77            for i = 1:size(value,2)
78                S(:,i) = value(:,i) .* Params(:,1);
79            end
80        end
81
82        % Energy scaling this way works for magnets but not BPMs, RF, or maybe other stuff!
83        % So if you want energy scaling do it with a function like amp2k
84        % if ~ismemberof(Family,'BPM')
85        %    if isempty(Energy)
86        %        Energy = getenergy;
87        %    elseif ischar(Energy)
88        %        Energy = getenergy(Energy);
89        %    end
90        %    S(:,i) = S(:,i) * getbrho(getenergy('Production')) / getbrho(Energy);
91        % end
92        if ~ischar(Energy)
93            % Expand to the length of Energy input
94            if size(S,1) == 1
95                S = S * ones(1,size(Energy,2));
96            end
97        end
98
99    else
100        % Use inline or user specified function
101        if isempty(Energy)
102            Energy = getenergy;
103        elseif ischar(Energy)
104            Energy = getenergy(Energy);
105        end
106        if iscell(Params)
107            S = feval(FunctionStr, Family, Field, value, DeviceList, Energy, Params{:});
108        elseif isempty(Params)
109            S = feval(FunctionStr, Family, Field, value, DeviceList, Energy);
110        elseif isstr(Params)
111            S = feval(FunctionStr, Family, Field, value, DeviceList, Energy, Params);
112        else
113            % This will make all elements in the row vector a separate input
114            ParamsList = num2cell(Params,1);
115            S = feval(FunctionStr, Family, Field, value, DeviceList, Energy, ParamsList{:});
116        end
117    end
118
119elseif isstruct(Family)   
120    % Convert entire data structure e.g. response matrix
121    S = Family;
122   
123    for j = 1:size(S,1)
124        for k = 1:size(S,2)
125
126            if isfield(S(j,k),'Monitor') & isfield(S(j,k),'Actuator')
127                % Response matrix structure
128
129                if nargin < 2
130                    %Energy = 'Production';
131                    Energy = S(j,k).GeV;
132                else
133                    Energy = Field;
134                end
135
136                % Note: Chromaticity and Dispersion are special cases
137                if strcmpi(S(j,k).Monitor.FamilyName, 'Chromaticity')
138                    % Chromaticity response matrix
139                    if ~strcmpi(S(j,k).Units, 'Physics')
140                        RF = S(j,k).Monitor.Actuator.Data;
141                        MCF = S(j,k).Monitor.MCF;
142                        S(j,k).Data = - S(j,k).Data * RF(1) * MCF;
143                        S(j,k).Monitor  = hw2physics(S(j,k).Monitor);    % Chromaticity structure (also a response structure)
144                       
145                        ActuatorDeltaHardware = S(j,k).ActuatorDelta;
146                        S(j,k).ActuatorDelta = hw2physics(S(j,k).Actuator.FamilyName, S(j,k).Actuator.Field, S(j,k).ActuatorDelta + S(j,k).Actuator.Data, S(j,k).Actuator.DeviceList, S(j,k).GeV) - ...
147                                               hw2physics(S(j,k).Actuator.FamilyName, S(j,k).Actuator.Field,                        S(j,k).Actuator.Data, S(j,k).Actuator.DeviceList, S(j,k).GeV);
148                        ActuatorScaleFactor = S(j,k).ActuatorDelta ./ ActuatorDeltaHardware;
149                        ActuatorScaleFactor = ActuatorScaleFactor(:)';
150                        S(j,k).Actuator = hw2physics(S(j,k).Actuator, S(j,k).GeV);  % Sextupole
151                       
152                        % Scalar row by the actuator scaling
153                        for i = 1:size(S(j,k).Data,1)
154                            S(j,k).Data(i,:) = S(j,k).Data(i,:) ./ ActuatorScaleFactor;
155                        end
156                       
157                        % Change units and UnitsString fields
158                        if isfield(S(j,k),'Units')
159                            S(j,k).Units = 'Physics';
160                        end
161                        if isfield(S(j,k),'UnitsString')
162                            if isfield(S(j,k).Monitor,'UnitsString') & isfield(S(j,k).Actuator,'UnitsString')
163                                %S(j,k).UnitsString = '(Fractional Tune/(dp/p))/meter^-3';
164                                S(j,k).UnitsString = [S(j,k).Monitor.UnitsString , '/', S(j,k).Actuator.UnitsString];
165                            else
166                                S(j,k).UnitsString = '';
167                            end
168                        end
169                    end
170                elseif strcmpi(S(j,k).Monitor.FamilyName, 'TUNE') & strcmpi(S(j,k).Actuator.FamilyName, 'RF')
171                    % Chromaticity measurement
172                    if ~strcmpi(S(j,k).Units, 'Physics')
173                        RF = S(j,k).Actuator.Data;
174                        MCF = S(j,k).MCF;
175                        S(j,k).Data = - S(j,k).Data * RF(1) * MCF;
176                       
177                        if isfield(S(j,k),'Tune') & isfield(S(j,k),'PolyFit')
178                            p = polyfit(S(j,k).dp, S(j,k).Tune(1,:), 2);
179                            S(j,k).PolyFit(1,:) = p;
180                            % S(j,k).Data(1,1) = p(2);
181                            p = polyfit(S(j,k).dp, S(j,k).Tune(2,:), 2);
182                            S(j,k).PolyFit(2,:) = p;
183                            % S(j,k).Data(2,1) = p(2);
184                        end
185                       
186                        % Convert the Monitor and Actuator fields
187                        %S(j,k).Monitor  = hw2physics(S(j,k).Monitor);   % Tune structure (same in Hardware and Physics)
188                        S(j,k).ActuatorDelta = hw2physics(S(j,k).Actuator.FamilyName, S(j,k).Actuator.Field, S(j,k).ActuatorDelta + S(j,k).Actuator.Data, S(j,k).Actuator.DeviceList, S(j,k).GeV) - ...
189                                               hw2physics(S(j,k).Actuator.FamilyName, S(j,k).Actuator.Field,                        S(j,k).Actuator.Data, S(j,k).Actuator.DeviceList, S(j,k).GeV);
190                        S(j,k).Actuator = hw2physics(S(j,k).Actuator, S(j,k).GeV);  % RF
191
192                        S(j,k).Units = 'Physics';
193                        %S(j,k).UnitsString = '1/(dp/p)';
194                        S(j,k).UnitsString = [S(j,k).Monitor.UnitsString,'/(dp/p)'];
195                    end
196                elseif ismemberof(S(j,k).Monitor.FamilyName, 'BPM') & strcmpi(S(j,k).Actuator.FamilyName, 'RF')
197                    % Dispersion measurement
198                    if ~strcmpi(S(j,k).Units, 'Physics')
199                        % Change to physics units
200                       
201                        % Change the numerator as if it was a BPM (but remove the offset)
202                        d = S(j,k).Monitor;
203                        d.Data = S(j,k).Data + getoffset(S(j,k).Monitor.FamilyName, 'Monitor', S(j,k).Monitor.DeviceList, 'Hardware');
204                        d = hw2physics(d, S(j,k).GeV);
205                        S(j,k).Data = d.Data;
206                       
207                        % Change to denominator to energy shift (dp/p)
208                        RF = S(j,k).Actuator.Data;
209                        MCF = S(j,k).MCF;
210                        S(j,k).Data = -RF(1) * MCF * S(j,k).Data;
211                       
212                        % Change the Monitor and Actuator fields
213                        S(j,k).Monitor  = hw2physics(S(j,k).Monitor, S(j,k).GeV);
214                        S(j,k).ActuatorDelta = hw2physics(S(j,k).Actuator.FamilyName, S(j,k).Actuator.Field, S(j,k).ActuatorDelta + S(j,k).Actuator.Data, S(j,k).Actuator.DeviceList, S(j,k).GeV) - ...
215                                               hw2physics(S(j,k).Actuator.FamilyName, S(j,k).Actuator.Field,                        S(j,k).Actuator.Data, S(j,k).Actuator.DeviceList, S(j,k).GeV);
216                        S(j,k).Actuator = hw2physics(S(j,k).Actuator, S(j,k).GeV);
217
218                        S(j,k).Units = 'Physics';
219                        S(j,k).UnitsString = [S(j,k).Monitor.UnitsString,'/(dp/p)'];
220                    end
221                   
222                else
223                    % Typical response matrix  (usually orbit/corrector)
224                    % Need to determine the hw2physics scaling for delta monitor / delta actuator
225                   
226                    % Only change units if in 'Hardware' units
227                    if strcmpi(S(j,k).Actuator.Units, 'Hardware')                       
228                        % Convert .ActuatorDelta
229                        ActuatorDeltaHW = S(j,k).ActuatorDelta;
230                       
231                        % Scale Factor without energy scaling (since physics units are the same at all energies)
232                        S(j,k).ActuatorDelta = hw2physics(S(j,k).Actuator.FamilyName, S(j,k).Actuator.Field, S(j,k).ActuatorDelta + S(j,k).Actuator.Data, S(j,k).Actuator.DeviceList, S(j,k).GeV) - ...
233                                               hw2physics(S(j,k).Actuator.FamilyName, S(j,k).Actuator.Field,                        S(j,k).Actuator.Data, S(j,k).Actuator.DeviceList, S(j,k).GeV);
234
235                        % Physics units / HW units
236                        ActuatorScaleFactor = S(j,k).ActuatorDelta ./ ActuatorDeltaHW;
237                        ActuatorScaleFactor = ActuatorScaleFactor(:)';
238           
239                        % Convert .Actuator field
240                        S(j,k).Actuator = hw2physics(S(j,k).Actuator, S(j,k).GeV);
241                       
242                        %ActuatorData = S(j,k).Actuator.Data;
243                        %S(j,k).Actuator = physics2hw(S(j,k).Actuator);
244                        %if any(ActuatorData == 0)
245                        %    ActuatorScaleFactor = hw2physics(S(j,k).Actuator.FamilyName, S(j,k).Actuator.Field, 1, S(j,k).Actuator.DeviceList, S(j,k).GeV);
246                        %else
247                        %    ActuatorScaleFactor = S(j,k).Actuator.Data ./ ActuatorData;
248                        %end
249                    else
250                        % Don't include energy scaling of actuator if already in physics units
251                        ActuatorScaleFactor = 1; %Energy/S(j,k).GeV;
252                        ActuatorDeltaHW = S(j,k).ActuatorDelta;
253                    end
254                   
255
256                    % Only change units if in 'Hardware' units
257                    if strcmpi(S(j,k).Monitor.Units, 'Hardware')                       
258                        % Just to get an approximate scaling for the monitor size
259                        %MonitorDeltaHW = max(abs(S(j,k).Data(:,1) * ActuatorDeltaHW(1)));
260                        %MonitorDelta = hw2physics(S(j,k).Monitor.FamilyName, S(j,k).Monitor.Field, MonitorDeltaHW + S(j,k).Monitor.Data, S(j,k).Monitor.DeviceList, S(j,k).GeV) - ...
261                        %               hw2physics(S(j,k).Monitor.FamilyName, S(j,k).Monitor.Field,                  S(j,k).Monitor.Data, S(j,k).Monitor.DeviceList, S(j,k).GeV);
262                        %%MonitorDelta = hw2physics(S(j,k).Monitor.FamilyName, S(j,k).Monitor.Field, MonitorDeltaHW, S(j,k).Monitor.DeviceList, Energy) - getoffset(S(j,k).Monitor.FamilyName, S(j,k).Monitor.Field, 'Hardware');
263                        %
264                        %MonitorScaleFactor = MonitorDelta ./ MonitorDeltaHW;
265                        %MonitorScaleFactor = MonitorScaleFactor(:);
266                       
267                        % hw2physics must be linear for this to work, but the other methods have issues with small numbers
268                        %MonitorScaleFactor = hw2physics(S(j,k).Monitor.FamilyName, S(j,k).Monitor.Field, 1+getoffset(S(j,k).Monitor.FamilyName, S(j,k).Monitor.Field), S(j,k).Monitor.DeviceList, S(j,k).GeV, 'Hardware');                     
269                        MonitorScaleFactor = hw2physics(S(j,k).Monitor.FamilyName, S(j,k).Monitor.Field, 1, S(j,k).Monitor.DeviceList, S(j,k).GeV) - ...
270                                             hw2physics(S(j,k).Monitor.FamilyName, S(j,k).Monitor.Field, 0, S(j,k).Monitor.DeviceList, S(j,k).GeV);
271
272                        % Convert .Monitor field
273                        S(j,k).Monitor = hw2physics(S(j,k).Monitor, S(j,k).GeV);
274                       
275                        %MonitorData = S(j,k).Monitor.Data;
276                        %S(j,k).Monitor = physics2hw(S(j,k).Monitor);
277                        %if any(MonitorData == 0)
278                        %    % This might introduce an error if physics2hw is nonlinear
279                        %    MonitorScaleFactor = hw2physics(S(j,k).Monitor.FamilyName, S(j,k).Monitor.Field, 1, S(j,k).Monitor.DeviceList, S(j,k).GeV);
280                        %else
281                        %    MonitorScaleFactor = S(j,k).Monitor.Data ./ MonitorData;
282                        %end
283                    else
284                        MonitorScaleFactor = 1;
285                    end
286
287                   
288                    % Scalar column by the monitor scaling
289                    for i = 1:size(S(j,k).Data,2)
290                        S(j,k).Data(:,i) = MonitorScaleFactor .* S(j,k).Data(:,i);
291                    end
292                    %S(j,k).MonitorScaleFactor = MonitorScaleFactor;
293                   
294                    % Scalar row by the actuator scaling
295                    for i = 1:size(S(j,k).Data,1)
296                        S(j,k).Data(i,:) = S(j,k).Data(i,:) ./ ActuatorScaleFactor;
297                    end
298                    %S(j,k).ActuatorScaleFactor = ActuatorScaleFactor;
299                   
300                    S(j,k).GeV = Energy;
301
302                    % Change units and unitsstring fields
303                    if isfield(S(j,k),'Units')
304                        S(j,k).Units = 'Physics';
305                    end
306                    if isfield(S(j,k),'UnitsString')
307                        if isfield(S(j,k).Monitor,'UnitsString') && isfield(S(j,k).Actuator,'UnitsString')
308                            S(j,k).UnitsString = [ ...
309                                    S(j,k).Monitor.UnitsString , '/', ...
310                                    S(j,k).Actuator.UnitsString];
311                            %S(j,k).UnitsString = [ ...
312                            %        getfamilydata(S(j,k).Monitor.FamilyName,  S(j,k).Monitor.Field,  'PhysicsUnits') , '/', ...
313                            %        getfamilydata(S(j,k).Actuator.FamilyName, S(j,k).Actuator.Field, 'PhysicsUnits')];
314                        else
315                            S(j,k).UnitsString = '';
316                        end
317                    end
318                end
319
320            elseif isfield(S(j,k),'FamilyName') & isfield(S(j,k),'Field')
321                % Data structure
322
323                if nargin < 2
324                    if isfield(S(j,k), 'GeV')
325                        Energy = S(j,k).GeV;
326                    else
327                        Energy = 'NoEnergyScaling';
328                        %Energy = 'Production';
329                    end
330                else
331                    Energy = Field;
332                end
333
334                % Only change units if in 'Hardware' units
335                if ~strcmpi(S(j,k).Units, 'Physics')
336                    % First convert to "corrected" hardware units
337                    S(j,k) = raw2real(S(j,k)); % Done in hw2physics for FamilyName inputs
338                   
339                    S(j,k).Data = hw2physics(S(j,k).FamilyName, S(j,k).Field, S(j,k).Data, S(j,k).DeviceList, Energy);
340                    S(j,k).Units = 'Physics';
341                    S(j,k).UnitsString = getfamilydata(S(j,k).FamilyName, S(j,k).Field, 'PhysicsUnits');
342                end
343               
344            else
345                error('Unknown data structure type');
346            end
347        end
348    end
349   
350elseif iscell(Family)
351    error('Cell array inputs not programmed yet');
352   
353else
354    error('Input #1 type unknown');
355end
356
357
Note: See TracBrowser for help on using the repository browser.