Changeset 105 for trunk


Ignore:
Timestamp:
Jun 24, 2010, 5:28:55 PM (15 years ago)
Author:
sommeria
Message:

Bug fix

Location:
trunk/src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/find_field_indices.m

    r89 r105  
    22%    group the variables  into 'fields' with common dimensions
    33%------------------------------------------------------------------------
    4 % function [DimVarIndex,CellVarIndex,NbDim,VarType]=find_field_indices(Data)
     4% function  [CellVarIndex,NbDim,VarType,errormsg]=find_field_indices(Data)
    55%
    66% OUTPUT:
     
    1919%      .scalar: scalar field (default)
    2020%      .coord: vector of indices of coordinate variables corresponding to matrix dimensions
     21% errormsg: error message
    2122%   
    2223% INPUT:
  • trunk/src/get_field/PLOT.m

    r89 r105  
    88end
    99[SubField,errormsg]=read_get_field(hget_field);
     10% SubField.VarAttribute{1}
     11% SubField.VarAttribute{2}
     12% SubField.VarAttribute{3}
     13%
     14% SubField.VarDimName{1}
     15% SubField.VarDimName{2}
     16% SubField.VarDimName{3}
     17
    1018if ~isempty(errormsg)
    1119    msgbox_uvmat('ERROR',['error in read_get_field/PLOT input:' errormsg])
  • trunk/src/mouse_motion.m

    r104 r105  
    7171            haxes=hchild(ichild);
    7272            xy=get(haxes,'CurrentPoint');%xy(1,1),xy(1,2): current x,y positions in axes coordinates
    73             mouse.X=xy(1,1);
    74             mouse.Y=xy(1,2);
    75             u_mouse=[];
    76             v_mouse=[];
    77             w_mouse=[];
    78             A_mouse=[];
    79             c_text=[];
    80             f_text=[];
    81             ff_text=[];     
    82             ivec=[];
    8373            AxeData=get(haxes,'UserData');% data attached to the axis
    84             if isfield(AxeData,'Drawing')&& ~isempty(AxeData.Drawing) 
     74            if isfield(AxeData,'Drawing')&& ~isempty(AxeData.Drawing)
    8575                test_draw=~isequal(AxeData.Drawing,'off');
    8676            end
    8777            test_zoom_draw=test_draw && isequal(AxeData.Drawing,'zoom')&& isfield(AxeData,'CurrentOrigin') && isequal(get(gcf,'SelectionType'),'normal');
    88             test_object=test_draw && isfield(AxeData,'CurrentObject') && ~isempty(AxeData.CurrentObject) && ishandle(AxeData.CurrentObject);       
    89              if ~test_edit && ~test_zoom_draw && ~test_ruler
    90                  pointershape='crosshair';%set pointer with cross shape (default when mouse is over an axis)
    91              end
    92             if isfield(AxeData,'X') && isfield(AxeData,'Y') && isfield(AxeData,'Mesh')% test on the existence of a vector field in the current axis
    93                 if ~isempty(AxeData.Mesh)
    94                     flag_vec=(AxeData.X<(xy(1,1)+AxeData.Mesh/3) & AxeData.X>(xy(1,1)-AxeData.Mesh/3)) & ...%flagx=1 for the vectors with x position selected by the mouse
    95                           (AxeData.Y<(xy(1,2)+AxeData.Mesh/3) & AxeData.Y>(xy(1,2)-AxeData.Mesh/3));%f
    96                     ivec=find(flag_vec,1);% search the (first) selected vector index ivec
    97                     hhh=findobj(haxes,'Tag','vector_marker');
    98                     if ~isempty(ivec)
    99                         if ~test_object % mark the vectors with a circle in the absence of other operations
    100                             if  ~test_create && ~test_edit && ~test_ruler
    101                                 pointershape='arrow'; %mouse indicates  the detection of a vector
    102                                 if isempty(hhh)
    103                                      hstack=findobj(allchild(0),'Type','figure');%current stack order of figures in matlab
    104                                     axes(haxes)
    105                                     rectangle('Curvature',[1 1],...
    106                       'Position',[AxeData.X(ivec)-AxeData.Mesh/2 AxeData.Y(ivec)-AxeData.Mesh/2 AxeData.Mesh AxeData.Mesh],'EdgeColor','m',...
    107                       'LineStyle','-','Tag','vector_marker');
    108                                     set(0,'Children',hstack);%put back the initial figure stack after plot creation
     78            test_object=test_draw && isfield(AxeData,'CurrentObject') && ~isempty(AxeData.CurrentObject) && ishandle(AxeData.CurrentObject);
     79            if ~test_edit && ~test_zoom_draw && ~test_ruler
     80                pointershape='crosshair';%set pointer with cross shape (default when mouse is over an axis)
     81            end
     82            if isfield(AxeData,'ListVarName')
     83                [CellVarIndex,NbDim,VarType]=find_field_indices(AxeData);
     84                if isfield(AxeData,'Mesh') && ~isempty(AxeData.Mesh)
     85                    text_displ_1='';
     86                    text_displ_2='';
     87                    text_displ_3='';
     88                    text_displ_4='';
     89                    for icell=1:numel(CellVarIndex)%look for all physical fields
     90                        if NbDim(icell)==2 % select 2D field
     91                            if ~isempty(VarType{icell}.coord_x) && ~isempty(VarType{icell}.coord_y)%case of unstructured data
     92                                eval(['X=AxeData.' AxeData.ListVarName{VarType{icell}.coord_x} ';'])
     93                                eval(['Y=AxeData.' AxeData.ListVarName{VarType{icell}.coord_y} ';'])
     94                                flag_vec=(X<(xy(1,1)+AxeData.Mesh/3) & X>(xy(1,1)-AxeData.Mesh/3)) & ...%flagx=1 for the vectors with x position selected by the mouse
     95                                    (Y<(xy(1,2)+AxeData.Mesh/3) & Y>(xy(1,2)-AxeData.Mesh/3));%f
     96                                ivec=find(flag_vec,1);% search the (first) selected vector index ivec
     97                                hhh=findobj(haxes,'Tag','vector_marker');
     98                                if ~isempty(ivec)
     99                                    if ~test_object && ~test_create && ~test_edit && ~test_ruler% mark the vectors with a circle in the absence of other operations
     100                                        pointershape='arrow'; %mouse indicates  the detection of a vector
     101                                        if isempty(hhh)
     102                                            hstack=findobj(allchild(0),'Type','figure');%current stack order of figures in matlab
     103                                            axes(haxes)
     104                                            rectangle('Curvature',[1 1],...
     105                                                'Position',[X(ivec)-AxeData.Mesh/2 Y(ivec)-AxeData.Mesh/2 AxeData.Mesh AxeData.Mesh],'EdgeColor','m',...
     106                                                'LineStyle','-','Tag','vector_marker');
     107                                            set(0,'Children',hstack);%put back the initial figure stack after plot creation
     108                                        else
     109                                            set(hhh,'Visible','on')
     110                                            set(hhh,'Position',[X(ivec)-AxeData.Mesh/2 Y(ivec)-AxeData.Mesh/2 AxeData.Mesh AxeData.Mesh])
     111                                        end
     112                                    end
     113                                    for ivar=1:numel(CellVarIndex{icell})
     114                                        VarName=AxeData.ListVarName{CellVarIndex{icell}(ivar)};
     115                                        eval(['VarVal=AxeData.' VarName '(ivec);'])
     116                                        var_text=[VarName '=' num2str(VarVal,3) ','];
     117                                        if isequal(ivar,VarType{icell}.coord_x)||isequal(ivar,VarType{icell}.coord_y)||isequal(ivar,VarType{icell}.coord_z)
     118                                            text_displ_1=[text_displ_1 var_text];
     119                                        elseif isequal(ivar,VarType{icell}.vector_x)||isequal(ivar,VarType{icell}.vector_y)||isequal(ivar,VarType{icell}.vector_z)
     120                                            text_displ_3=[text_displ_3 var_text];
     121                                        else
     122                                            text_displ_4=[text_displ_4 var_text];
     123                                        end
     124                                    end
    109125                                else
    110                                     set(hhh,'Visible','on')
    111                                     set(hhh,'Position',[AxeData.X(ivec)-AxeData.Mesh/2 AxeData.Y(ivec)-AxeData.Mesh/2 AxeData.Mesh AxeData.Mesh])
     126                                    if ~isempty(hhh)
     127                                        set(hhh,'Visible','off')
     128                                    end
     129                                end
     130                            elseif numel(VarType{icell}.coord) >=2 %structured coordinates
     131                                eval(['y=AxeData.' AxeData.ListVarName{VarType{icell}.coord(1)} ';'])
     132                                eval(['x=AxeData.' AxeData.ListVarName{VarType{icell}.coord(2)} ';'])
     133                                nxy(1)=numel(y);
     134                                nxy(2)=numel(x);
     135                                MaxAY=max(y(1),y(end));
     136                                MinAY=min(y(1),y(end));
     137                                if (xy(1,1)>x(1))&(xy(1,1)<x(end))&(xy(1,2)<MaxAY)&(xy(1,2)>MinAY)
     138                                    indx0=1+round((nxy(2)-1)*(xy(1,1)-x(1))/(x(end)-x(1)));% index x of pixel
     139                                    indy0=1+round((nxy(1)-1)*(xy(1,2)-y(1))/(y(end)-y(1)));% index y of pixel
     140                                    if indx0>=1 & indx0<=nxy(2) & indy0>=1 & indy0<=nxy(1)
     141                                        text_displ_2=['i='  num2str(indx0) ',j=' num2str(indy0) ','];
     142                                        for ivar=1:numel(CellVarIndex{icell})
     143                                            VarName=AxeData.ListVarName{CellVarIndex{icell}(ivar)};
     144                                            eval(['VarVal=AxeData.' VarName '(indy0,indx0);'])
     145                                            var_text=[VarName '=' num2str(VarVal,3) ','];
     146                                            text_displ_2=[text_displ_2 var_text];
     147                                        end
     148                                    end
    112149                                end
    113150                            end
    114151                        end
    115                         mouse.X=AxeData.X(ivec);
    116                         mouse.Y=AxeData.Y(ivec);
    117                         u_mouse=AxeData.U(ivec);%displacement
    118                         v_mouse=AxeData.V(ivec);
    119                         w_mouse=0; %default
    120                         if isfield(AxeData,'W') & length(AxeData.W)>=ivec
    121                             w_text=[',  w=' num2str(AxeData.W(ivec),3)];
    122                         else
    123                             w_text='';
     152                    end
     153                end
     154                if strcmp(text_displ_1,'')
     155                    text_displ_1=['x=' num2str(xy(1,1)) ',y=' num2str(xy(1,2))];
     156                end
     157                if isfield(AxeData,'Z')
     158                    text_displ_1=[text_displ_1 num2str(AxeData.Z)]; %generaliser au cas avec angle
     159                end
     160                if isfield(AxeData,'ObjectCoord') && size(AxeData.ObjectCoord,2)==3
     161                    text_displ_1=[text_displ_1 num2str(AxeData.ObjectCoord(1,3))]; %generaliser au cas avec angle
     162                end
     163                %images
     164                if strcmp(text_displ_2,'')&&isfield(AxeData,'A')&&isfield(AxeData,'AX')&&isfield(AxeData,'AY')
     165                    y=AxeData.AY;
     166                    x=AxeData.AX;
     167                    nxy=size(AxeData.A);
     168                    MaxAY=max(y(1),y(end));
     169                    MinAY=min(y(1),y(end));
     170                    if (xy(1,1)>x(1))&(xy(1,1)<x(end))&(xy(1,2)<MaxAY)&(xy(1,2)>MinAY)
     171                        indx0=1+round((nxy(2)-1)*(xy(1,1)-x(1))/(x(end)-x(1)));% index x of pixel
     172                        indy0=1+round((nxy(1)-1)*(xy(1,2)-y(1))/(y(end)-y(1)));% index y of pixel
     173                        if indx0>=1 & indx0<=nxy(2) & indy0>=1 & indy0<=nxy(1)
     174                            text_displ_2=['i='  num2str(indx0) ',j=' num2str(indy0) ',A=' num2str(AxeData.A(indy0,indx0,:))];
    124175                        end
    125                         if ~isfield(AxeData,'CName')
    126                             AxeData.CName='C';%REVOIR
    127                         end
    128                         c_text=[', ' AxeData.CName '=' num2str(AxeData.C(ivec),3)];
    129                         if isfield(AxeData,'F')&length(AxeData.F)>=ivec
    130                             f_text=[',  f=' num2str(AxeData.F(ivec),3)];
    131                         else
    132                             f_text='';
    133                         end
    134                         if isfield(AxeData,'FF')&length(AxeData.FF)>=ivec
    135                             ff_text=[',  ff=' num2str(AxeData.FF(ivec),3)];
    136                         else
    137                             ff_text='';
    138                         end
    139                     else
    140                         if ~isempty(hhh)
    141                             set(hhh,'Visible','off')
    142                         end
    143                     end
    144                 end
    145             end
    146             if isfield(AxeData,'Z')
    147                 mouse.Z=AxeData.Z; %generaliser au cas avec angle
    148             end
    149             if isfield(AxeData,'ObjectCoord') & size(AxeData.ObjectCoord,2)==3
    150                 mouse.Z=AxeData.ObjectCoord(1,3); %generaliser au cas avec angle
    151             end
    152             testscal= isfield(AxeData,'A')& isfield(AxeData,'AX')& isfield(AxeData,'AY');%test the existence of an image (or scalar represented by an image)
    153                if testscal
    154                    testscal=~isempty(AxeData.A)&~isempty(AxeData.AX)& ~isempty(AxeData.AY);
    155                end
    156             if testscal%test the existence of an image (or scalar represented by an image)
    157                 nxy=size(AxeData.A);
    158                 MaxAY=max(AxeData.AY(1),AxeData.AY(end));
    159                 MinAY=min(AxeData.AY(1),AxeData.AY(end));
    160                 if (xy(1,1)>AxeData.AX(1))&(xy(1,1)<AxeData.AX(end))&(xy(1,2)<MaxAY)&(xy(1,2)>MinAY)
    161                     indx0=1+round((nxy(2)-1)*(xy(1,1)-AxeData.AX(1))/(AxeData.AX(end)-AxeData.AX(1)));% index x of pixel
    162                     indy0=1+round((nxy(1)-1)*(xy(1,2)-AxeData.AY(1))/(AxeData.AY(end)-AxeData.AY(1)));% index y of pixel
    163                     if indx0>=1 & indx0<=nxy(2) & indy0>=1 & indy0<=nxy(1)
    164                         A_mouse=AxeData.A(indy0,indx0,:);
    165                     end
    166                 end
    167             end
    168             %coordinate transform if proj_coord differs from menu_coord
    169             if isfield(AxeData,'CoordType')
    170                   mouse.CoordType=AxeData.CoordType;
    171             end
    172             if isfield(AxeData,'CoordUnit')
    173                   mouse.CoordUnit=AxeData.CoordUnit;
    174             end
    175             if isfield(mouse,'CoordType')
    176                 if isequal(mouse.CoordType,'px')
    177                     mouse.CoordUnit='px';
    178                 end
    179             else
    180                 mouse.CoordUnit='';%default     
    181             end     
    182             text_displ_1=['x=' num2str(mouse.X,4) ',y=' num2str(mouse.Y,4)];
    183             if isfield(mouse,'Z')&~isempty(mouse.Z)
    184                 text_displ_1=[text_displ_1 ',z=' num2str(mouse.Z,3)];
    185             end
    186             if isfield(mouse,'CoordUnit')
    187                  text_displ_1=[text_displ_1 ' ' mouse.CoordUnit];
    188             end
    189             if ~isempty(ivec)
    190                 text_displ_4=['vec#=' num2str(ivec)];
    191             end
    192             if ~isempty(u_mouse)
    193                 text_displ_3=['u=' num2str(u_mouse,3) ',v=' num2str(v_mouse,3) w_text ];
    194                 if  isfield(mouse,'CoordUnit')
    195                     if isequal(mouse.CoordUnit,'px')
    196                         text_displ_3=[text_displ_3 '  ' mouse.CoordUnit];
    197                     elseif isfield(AxeData,'TimeUnit')
    198                         text_displ_3=[text_displ_3 '  ' mouse.CoordUnit '/' AxeData.TimeUnit];
    199                     end
    200                 end
    201                 text_displ_4=[text_displ_4 c_text f_text ff_text];
    202             end
    203            
    204             if ~isempty(A_mouse)
    205                 text_displ_2=['A=' num2str(double(A_mouse)) ',i='  num2str(indx0) ',j=' num2str(indy0)];
    206             end
    207         elseif isequal(htype,'uicontrol') && isequal(get(hchild(ichild),'Visible'),'on')&& ~isequal(get(hchild(ichild),'Style'),'frame')
    208             text_displ_1=get(hchild(ichild),'Tag');
     176                    end
     177                end
     178                %coordinate transform if proj_coord differs from menu_coord A REVOIR
     179                if isfield(AxeData,'CoordType')
     180                    mouse.CoordType=AxeData.CoordType;
     181                end
     182                if isfield(AxeData,'CoordUnit')
     183                    mouse.CoordUnit=AxeData.CoordUnit;
     184                end
     185                if isfield(mouse,'CoordType')
     186                    if isequal(mouse.CoordType,'px')
     187                        mouse.CoordUnit='px';
     188                    end
     189                else
     190                    mouse.CoordUnit='';%default
     191                end
     192            end
    209193        end
    210194    end
     
    214198set(handles.text_display_3,'String',text_displ_3);
    215199set(handles.text_display_4,'String',text_displ_4);
    216 % if ~test_draw
    217 %     return
    218 % end
    219 % At this stage  if no drawing  operation is done
    220 
    221200
    222201%%%%%%%%%%%%%
  • trunk/src/plot_field.m

    r102 r105  
    202202    if testzoomaxes
    203203        [AxeData,zoomaxes,PlotParamOut]=plot_plane(Data,CellVarIndex(ind_select),VarType(ind_select),zoomaxes,PlotParam,1,PosColorbar);
    204         AxeData.ZoomAxes=zoomaxes;
     204        %AxeData.ZoomAxes=zoomaxes;
     205        Data.ZoomAxes=zoomaxes;
    205206    end
    206207elseif isequal(Data.NbDim,3)
     
    227228
    228229% set graph aspect ratio
    229 
     230if isfield(AxeData,'Mesh')
     231    Data.Mesh=AxeData.Mesh;
     232end
    230233
    231234%set(haxes,'UserData',AxeData)
  • trunk/src/read_get_field.m

    r89 r105  
    248248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    249249% vectors
    250 % test_vec_x_dimvar=0;%default
    251 % test_vec_y_dimvar=0;%default
     250test_vec_x_dimvar=0;%default
     251test_vec_y_dimvar=0;%default
    252252% test_vec_z_dimvar=0;%defaul
    253253dimname_vec_x=[];
     
    321321                end
    322322            end
    323 %             test_vec_x_dimvar=1;
     323             test_vec_x_dimvar=1;
    324324            SubVarAttribute{nbvar}.Role='dimvar';% dimension variable
    325325        else
     
    354354                end
    355355            end
    356 %             test_vec_y_dimvar=1;
     356             test_vec_y_dimvar=1;
    357357            SubVarAttribute{nbvar}.Role='dimvar';% dimension variable
    358358        else
     
    458458    VarNameA=Field.ListVarName{VarIndexA};
    459459    DimCellA=Field.VarDimName{VarIndexA};   
    460     eval(['npxy=size(SubField.' VarNameA ')'])
     460    eval(['npxy=size(SubField.' VarNameA ');'])
    461461    SingleCellA={};
    462462    if numel(npxy) < numel(DimCellA)
     
    489489        for icoord=1:numel(SingleCellA)% look for coincidence of dimension with one of the dimensions of the scalar
    490490            if strcmp(dimname_y,SingleCellA{icoord})% a singleton dimension
    491                 errormsg=['the singleton dimension ' dimname_y ' has been selected for ordiante'];
     491                errormsg=['the singleton dimension ' dimname_y ' has been selected for ordinate'];
    492492                return
    493493            end
     
    517517    dimextra(dimA)=[]; %list of unselected dimension indices
    518518    DimCellA=DimCellA([dimA dimextra]);
    519    % eval(['SubField.' VarNameA '=permute(squeeze(SubField.' VarNameA '),[dimA dimextra]);'])TO CHECK
     519    eval(['SubField.' VarNameA '=permute(squeeze(SubField.' VarNameA '),[dimA dimextra]);'])
    520520    SubField.VarDimName{VarSubIndexA}=DimCellA; 
    521521    %add default coord_x and/or coord_y if empty
     
    523523        VarName=Field.ListVarName{field_var_index};
    524524        DimCell=Field.VarDimName{field_var_index};   
    525         eval(['npxy=size(SubField.' VarName ')'])
     525        eval(['npxy=size(SubField.' VarName ');'])
    526526        if numel(npxy) < numel(DimCell)
    527527            DimCell=DimCell(end-numel(npxy)+1:end); %suppress the first singletons) dimensions
     
    579579    VarNameU=Field.ListVarName{VarIndexU}; % name of u component variable
    580580    DimCellU=Field.VarDimName{VarIndexU}; % list of dimensions for u component 
    581     eval(['npxy=size(SubField.' VarNameU ')']) % npxy= dimension values for the u component
     581    eval(['npxy=size(SubField.' VarNameU ');']) % npxy= dimension values for the u component
    582582    SingleCellU={};
    583583    if numel(npxy) < numel(DimCellU)
     
    609609        end
    610610    end
    611     if test_ydimvar%dim_x && dim_y && ~isempty(VarSubIndexA)
     611    if test_vec_y_dimvar%dim_x && dim_y && ~isempty(VarSubIndexA)
    612612        for icoord=1:numel(SingleCellU)% look for coincidence of dimension with one of the dimensions of the scalar
    613613            if strcmp(dimname_vec_y,SingleCellU{icoord})% a singleton dimension
     
    650650        VarName=Field.ListVarName{field_var_index};
    651651        DimCell=Field.VarDimName{field_var_index};   
    652         eval(['npxy=size(SubField.' VarName ')'])
     652        eval(['npxy=size(SubField.' VarName ');'])
    653653        if numel(npxy) < numel(DimCell)
    654654            DimCell=DimCell(end-numel(npxy)+1:end); %suppress the first singletons) dimensions
     
    722722        VarName=Field.ListVarName{VarIndex_y(1)};
    723723        DimCell=Field.VarDimName{VarIndex_y(1)};   
    724         eval(['npxy=size(SubField.' VarName ')'])
     724        eval(['npxy=size(SubField.' VarName ');'])
    725725        if numel(npxy) < numel(DimCell)
    726726%             DimCell=DimCell(end-numel(npxy)+1:end); %suppress the first singletons) dimensions
    727727        end
    728 %         ind_select=find(npxy~=1) ;%look for non singleton dimensions
    729 %         DimCell=DimCell(ind_select);
    730 %         npxy=npxy(ind_select);
    731728        if isfield(Field,'VarAttribute') && numel(Field.VarAttribute)>=VarIndex_y(1) ...
    732729                             && isfield(Field.VarAttribute{VarIndex_y(1)},'Coord_1')
  • trunk/src/uvmat.m

    r102 r105  
    356356       fid=fopen('revision.log');
    357357       if fid~=-1
    358         a=textscan(fid,'%s%s%s',1,'HeaderLines',1,'Delimiter','|');
    359         set(handles.UVMAT_title,'String',[{'Copyright Joel Sommeria, 2008, Coriolis/ LEGI / CNRS-UJF-INPG';'GNU General Public License'; path_to_uvmat; ['at revision ' a{1}{1}]};a{3}{1};date_str;errormsg]);
    360         fclose(fid);
     358         a=textscan(fid,'%s%s%s',1,'HeaderLines',1,'Delimiter','|');
     359         set(handles.UVMAT_title,'String',[{'Copyright Joel Sommeria, 2008, Coriolis/ LEGI / CNRS-UJF-INPG'};{'GNU General Public License'}; {path_to_uvmat}; ...
     360           {['at revision ' a{1}{1}]};a{3}(1);{date_str};errormsg]);
     361         fclose(fid);
    361362       else
    362            set(handles.UVMAT_title,'String',[{'Copyright Joel Sommeria, 2008, Coriolis/ LEGI / CNRS-UJF-INPG';'GNU General Public License'; path_to_uvmat;date_str};errormsg]);
     363          set(handles.UVMAT_title,'String',[{'Copyright Joel Sommeria, 2008, Coriolis/ LEGI / CNRS-UJF-INPG'};{'GNU General Public License'};{path_to_uvmat};...
     364               {date_str};errormsg]);
    363365       end
    364366   end
Note: See TracChangeset for help on using the changeset viewer.