Changeset 609 for trunk/src/series
 Timestamp:
 Apr 9, 2013, 8:20:00 PM (11 years ago)
 Location:
 trunk/src/series
 Files:

 4 edited
Legend:
 Unmodified
 Added
 Removed

trunk/src/series/aver_stat.m
r605 r609 73 73 OutputDir=[Param.OutputSubDir Param.OutputDirExt]; 74 74 75 %% root input file(s) and type75 %% root input file(s) name, type and index series 76 76 RootPath=Param.InputTable(:,1); 77 77 RootFile=Param.InputTable(:,3); … … 88 88 % i1_series(iview,fileindex) expresses the same indices as a 1D array in file indices 89 89 %%%%%%%%%%%% 90 % NbSlice=1;%default91 % if isfield(Param.IndexRange,'NbSlice')&&~isempty(Param.IndexRange.NbSlice)92 % NbSlice=Param.IndexRange.NbSlice;93 % end94 90 nbview=numel(i1_series);%number of input file series (lines in InputTable) 95 91 nbfield_j=size(i1_series{1},1); %nb of fields for the j index (bursts or volume slices) 96 92 nbfield_i=size(i1_series{1},2); %nb of fields for the i index 97 93 nbfield=nbfield_j*nbfield_i; %total number of fields 98 %nbfield_i=floor(nbfield/NbSlice);%total number of indexes in a slice (adjusted to an integer number of slices) 99 %nbfield=nbfield_i*NbSlice; %total number of fields after adjustement 100 101 % determine the file type on each line from the first input file94 [first_i,tild,last_i,first_j,tild,last_j,errormsg]=get_index_range(Param.IndexRange); 95 if ~isempty(errormsg),display(errormsg),return,end 96 97 %% determine the file type on each line from the first input file 102 98 ImageTypeOptions={'image','multimage','mmreader','video'}; 103 99 NcTypeOptions={'netcdf','civx','civdata'}; … … 150 146 return 151 147 end 152 NomTypeOut='_12_1';% output file index will indicate the first and last ref index in the series153 148 %NomTypeOut='_12_1';% output file index will indicate the first and last ref index in the series 149 NomTypeOut=nomtype2pair(NomType{1});% determine the index nomenclature type for the output file 154 150 155 151 %% Set field names and velocity types … … 272 268 %%%%%%%%%%%% END MAIN RUNNING OPERATIONS %%%%%%%%%%%% 273 269 else 274 disp lay(errormsg)270 disp(errormsg) 275 271 end 276 272 end … … 303 299 end 304 300 305 % writting the result file306 OutputFile=fullfile_uvmat(RootPath{1},OutputDir,RootFile{1},FileExtOut,NomTypeOut, i1_series{1}(1),i1_series{1}(end),j1_series{1}(1),j1_series{1}(end));301 %% writing the result file 302 OutputFile=fullfile_uvmat(RootPath{1},OutputDir,RootFile{1},FileExtOut,NomTypeOut,first_i,last_i,first_j,last_j); 307 303 if CheckImage{1} %case of images 308 304 if isequal(FileInfo{1}.BitDepth,16)(numel(FileInfo)==2 &&isequal(FileInfo{2}.BitDepth,16)) … … 313 309 imwrite(DataOut.A,OutputFile,'BitDepth',8); % case of 16 bit images 314 310 end 315 disp lay([OutputFile ' written']);311 disp([OutputFile ' written']); 316 312 else %case of netcdf input file , determine global attributes 317 313 errormsg=struct2nc(OutputFile,DataOut); %save result file 318 314 if isempty(errormsg) 319 display([OutputFile ' written']); 320 else 321 msgbox_uvmat('ERROR',['error in writting result file: ' errormsg]) 322 display(errormsg) 315 disp([OutputFile ' written']); 316 else 317 disp(['error in writting result file: ' errormsg]) 323 318 end 324 319 end % end averaging loop 
trunk/src/series/civ_input.m
r604 r609 89 89 FileType=SeriesData.FileType{1}; 90 90 FileInfo=SeriesData.FileInfo{1}; 91 Ref_i=SeriesData.Ref_i{1}; 92 Ref_j=SeriesData.Ref_j{1}; 93 FileInput=fullfile_uvmat(RootPath,SubDir,RootFile,FileExt,NomTypeInput,Ref_i(1),Ref_i(2),Ref_j(1),Ref_j(2)); 91 FileInput=SeriesData.RefFile{1}; 94 92 95 93 %% case of netcdf file as input, get the processing stage and look for corresponding images … … 226 224 time=SeriesData.Time{1}; 227 225 %transform .Time to a column vector if it is a line vector thenomenclature uses a single index: correct possible bug in xml 228 if isequal(MaxIndex_i,1) && ~isequal(MaxIndex_j,1)% .Time is a line vector 229 if numel(nom_type_read)>=2 && isempty(regexp(nom_type_read(2:end),'\D','once')) 230 time=time'; 231 MaxIndex_i=MaxIndex_j; 232 MaxIndex_j=1; 233 end 234 end 235 end 236 if isfield(SeriesData,'TimeUnit') 237 TimeUnit=SeriesData.TimeUnit; 238 end 226 % if isequal(MaxIndex_i,1) && ~isequal(MaxIndex_j,1)% .Time is a line vector 227 % if numel(nom_type_read)>=2 && isempty(regexp(nom_type_read(2:end),'\D','once')) 228 % time=time'; 229 % MaxIndex_i=MaxIndex_j; 230 % MaxIndex_j=1; 231 % end 232 % end 233 end 234 if isfield(Param.IndexRange,'TimeUnit')&&~isempty(Param.IndexRange.TimeUnit) 235 TimeUnit=Param.IndexRange.TimeUnit; 236 end 237 if isfield(SeriesData,'TimeSource') 238 set(handles.ImaDoc,'String',SeriesData.TimeSource) 239 end 239 240 if isfield(SeriesData,'GeometryCalib') 240 241 tsai=SeriesData.GeometryCalib; … … 247 248 end 248 249 % timing set by video input 249 if isempty(time) && (strcmp(FileType,'video')  strcmp(FileType,'mmreader'))250 set(handles.ListPairMode,'Value',1);251 dt=1/get(MovieObject,'FrameRate');%time interval between successive frames252 if strcmp(NomTypeIma,'*')253 set(handles.ListPairMode,'String',{'series(Di)'})254 time=(dt*(0:MaxIndex_i1))';%list of image times255 else256 set(handles.ListPairMode,'String',[{'series(Dj)'};{'series(Di)'}])257 time=ones(MaxIndex_i,1)*(dt*(0:MaxIndex_j1));%list of image times258 enable_j(handles,'on')259 end260 TimeUnit='s';261 set(handles.ImaDoc,'BackgroundColor',[1 1 1])% set display box back to whiter262 end250 % if isempty(time) && (strcmp(FileType,'video')  strcmp(FileType,'mmreader')) 251 % set(handles.ListPairMode,'Value',1); 252 % dt=1/get(MovieObject,'FrameRate');%time interval between successive frames 253 % if strcmp(NomTypeIma,'*') 254 % set(handles.ListPairMode,'String',{'series(Di)'}) 255 % time=(dt*(0:MaxIndex_i1))';%list of image times 256 % else 257 % set(handles.ListPairMode,'String',[{'series(Dj)'};{'series(Di)'}]) 258 % time=ones(MaxIndex_i,1)*(dt*(0:MaxIndex_j1));%list of image times 259 % enable_j(handles,'on') 260 % end 261 % TimeUnit='s'; 262 % set(handles.ImaDoc,'BackgroundColor',[1 1 1])% set display box back to whiter 263 % end 263 264 264 265 %% timing display … … 274 275 else 275 276 set(handles.ImaDoc,'String',''); %xml file not used for timing 276 % time=(i1_series(:,1)+0:size(i1_series,3)1);% time=index i277 % time=time'*ones(1,size(i1_series,2),1); %makes a time matrix with the same time for all j indices278 277 TimeUnit='frame'; 279 278 time=ones(MaxIndex_jMinIndex_j+1,1)*(MinIndex_i:MaxIndex_i); 280 279 time=time+0.001*(MinIndex_j:MaxIndex_j)'*ones(1,MaxIndex_iMinIndex_i+1); 281 280 end 282 time=[zeros(size(time,1),1) time]; %insert a vertical line of zeros (to deal with zero file indices)283 time=[zeros(1,size(time,2)); time]; %insert a horizontal line of zeros281 % time=[zeros(size(time,1),1) time]; %insert a vertical line of zeros (to deal with zero file indices) 282 % time=[zeros(1,size(time,2)); time]; %insert a horizontal line of zeros 284 283 CivInputData.Time=time; 285 284 CivInputData.NomTypeIma=NomTypeIma; 286 285 set(handles.civ_input,'UserData',CivInputData) 287 %set(handles.ImaDoc,'UserData',time); %store the matrix of times288 286 set(handles.dt_unit,'String',['dt in m' TimeUnit]);%display dt in unit 103 of the time (e.g ms) 289 287 set(handles.TimeUnit,'String',TimeUnit); … … 292 290 set(handles.CoordUnit,'String',CoordUnit) 293 291 set(handles.SearchRange,'UserData', pxcm_search); 294 295 % set(handles.ImaExt,'String',ImaExt)296 % set(handles.NomType,'String',NomTypeIma)297 292 298 293 %% set the reference indices from the input file indices … … 865 860 mode=mode_list{mode_value}; 866 861 end 867 displ_num=[];%default862 % displ_num=[];%default 868 863 ref_i=str2double(get(handles.ref_i,'String')); 869 864 % last_i=str2num(get(handles.last_i,'String')); … … 873 868 time=CivInputData.Time; 874 869 siztime=size(CivInputData.Time); 875 nbfield=siztime( 2)1;876 nbfield2=siztime( 1)1;870 nbfield=siztime(1)1; 871 nbfield2=siztime(2)1; 877 872 indchosen=1; %%first pair selected by default 878 873 %displ_num used to define the indices of the civ_input pairs … … 916 911 enable_j(handles, 'on') 917 912 elseif isequal(mode,'series(Di)') % isequal(mode,'st_series(Di)') 918 index=1:200;919 displ_num(1:2,index)=zeros(2,200);920 displ_num(3,index)=floor(index/2);921 displ_num(4,index)=ceil(index/2);913 % index=1:200; 914 % displ_num(1:2,index)=zeros(2,200); 915 % displ_num(3,index)=floor(index/2); 916 % displ_num(4,index)=ceil(index/2); 922 917 enable_i(handles, 'on') 923 918 if nbfield2 > 1 … … 942 937 end 943 938 end 944 set(handles.ListPairCiv1,'UserData',displ_num);939 %set(handles.ListPairCiv1,'UserData',displ_num); 945 940 errormsg=find_netcpair_civ( handles,1); 946 941 if ~isempty(errormsg) … … 978 973 set(handles.ListPairCiv2,'Value',index_pair); 979 974 end 975 976 %update first_i and last_i according to the chosen image pairs 977 % mode_list=get(handles.ListPairMode,'String'); 978 % mode_value=get(handles.ListPairMode,'Value'); 979 % mode=mode_list{mode_value}; 980 % if isequal(mode,'series(Di)') 981 % first_i=str2double(get(handles.first_i,'String')); 982 % last_i=str2double(get(handles.last_i,'String')); 983 % incr_i=str2double(get(handles.incr_i,'String')); 984 % num_i=first_i:incr_i:last_i; 985 % lastfield=str2double(get(handles.nb_field,'String')); 986 % if ~isnan(lastfield) 987 % test_find=(num_ifloor(index_pair/2)*ones(size(num_i))>0)& ... 988 % (num_i+ceil(index_pair/2)*ones(size(num_i))<=lastfield); 989 % num_i=num_i(test_find); 990 % end 991 % set(handles.first_i,'String',num2str(num_i(1))); 992 % set(handles.last_i,'String',num2str(num_i(end))); 993 % elseif isequal(mode,'series(Dj)') 994 % first_j=str2double(get(handles.first_j,'String')); 995 % last_j=str2double(get(handles.last_j,'String')); 996 % incr_j=str2double(get(handles.incr_j,'String')); 997 % num_j=first_j:incr_j:last_j; 998 % lastfield2=str2double(get(handles.nb_field2,'String')); 999 % if ~isnan(lastfield2) 1000 % test_find=(num_jfloor(index_pair/2)*ones(size(num_j))>0)& ... 1001 % (num_j+ceil(index_pair/2)*ones(size(num_j))<=lastfield2); 1002 % num_j=num_j(test_find); 1003 % end 1004 % set(handles.first_j,'String',num2str(num_j(1))); 1005 % set(handles.last_j,'String',num2str(num_j(end))); 1006 % end 1007 1008 % 1009 %  Executes on selection change in ListPairCiv2. 1010 function ListPairCiv2_Callback(hObject, eventdata, handles) 1011 % 1012 index_pair=get(handles.ListPairCiv2,'Value');%get the selected position index in the menu 980 1013 981 1014 %update first_i and last_i according to the chosen image pairs … … 1012 1045 1013 1046 % 1014 %  Executes on selection change in ListPairCiv2.1015 function ListPairCiv2_Callback(hObject, eventdata, handles)1016 %1017 index_pair=get(handles.ListPairCiv2,'Value');%get the selected position index in the menu1018 1019 %update first_i and last_i according to the chosen image pairs1020 mode_list=get(handles.ListPairMode,'String');1021 mode_value=get(handles.ListPairMode,'Value');1022 mode=mode_list{mode_value};1023 if isequal(mode,'series(Di)')1024 first_i=str2double(get(handles.first_i,'String'));1025 last_i=str2double(get(handles.last_i,'String'));1026 incr_i=str2double(get(handles.incr_i,'String'));1027 num_i=first_i:incr_i:last_i;1028 lastfield=str2double(get(handles.nb_field,'String'));1029 if ~isnan(lastfield)1030 test_find=(num_ifloor(index_pair/2)*ones(size(num_i))>0)& ...1031 (num_i+ceil(index_pair/2)*ones(size(num_i))<=lastfield);1032 num_i=num_i(test_find);1033 end1034 set(handles.first_i,'String',num2str(num_i(1)));1035 set(handles.last_i,'String',num2str(num_i(end)));1036 elseif isequal(mode,'series(Dj)')1037 first_j=str2double(get(handles.first_j,'String'));1038 last_j=str2double(get(handles.last_j,'String'));1039 incr_j=str2double(get(handles.incr_j,'String'));1040 num_j=first_j:incr_j:last_j;1041 lastfield2=str2double(get(handles.nb_field2,'String'));1042 if ~isnan(lastfield2)1043 test_find=(num_jfloor(index_pair/2)*ones(size(num_j))>0)& ...1044 (num_j+ceil(index_pair/2)*ones(size(num_j))<=lastfield2);1045 num_j=num_j(test_find);1046 end1047 set(handles.first_j,'String',num2str(num_j(1)));1048 set(handles.last_j,'String',num2str(num_j(end)));1049 end1050 1051 %1052 1047 function ref_i_Callback(hObject, eventdata, handles) 1053 1048 % … … 1114 1109 %% reads .nc subdirectoy and image numbers from the interface 1115 1110 SubDirImages=get(handles.Civ1_ImageA,'String'); 1111 %TODO: determine 1116 1112 subdir_civ1=[SubDirImages get(handles.Civ1_ImageB,'String')];%subdirectory subdir_civ1 for the netcdf data 1117 1113 subdir_civ2=[SubDirImages get(handles.Civ2_ImageA,'String')];%subdirectory subdir_civ2 for the netcdf data … … 1126 1122 ref_j=1; 1127 1123 end 1128 time=get(handles.ImaDoc,'UserData');%get the set of times 1124 CivInputData=get(handles.civ_input,'UserData'); 1129 1125 TimeUnit=get(handles.TimeUnit,'String'); 1126 time=CivInputData.Time; 1130 1127 checkframe=strcmp(TimeUnit,'frame'); 1131 displ_num=get(handles.ListPairCiv1,'UserData');1128 %displ_num=get(handles.ListPairCiv1,'UserData'); 1132 1129 1133 1130 %% eliminate the first pairs inconsistent with the position 1134 if isempty(displ_num)1135 nbpair=0;1136 else1137 nbpair=length(displ_num(1,:));%nbre of displayed pairs1138 if isequal(mode,'series(Di)') % isequal(mode,'st_series(Di)')1139 nbpair=min(2*ref_i1,nbpair);%limit the number of pairs with positive first index1140 elseif isequal(mode,'series(Dj)')%  isequal(mode,'st_series(Dj)')1141 nbpair=min(2*ref_j1,nbpair);%limit the number of pairs with positive first index1142 end1143 end1144 nbpair=min(200,nbpair);%limit the number of displayed pairs to 2001131 % if isempty(displ_num) 1132 % nbpair=0; 1133 % else 1134 % nbpair=length(displ_num(1,:));%nbre of displayed pairs 1135 % if isequal(mode,'series(Di)') % isequal(mode,'st_series(Di)') 1136 % nbpair=min(2*ref_i1,nbpair);%limit the number of pairs with positive first index 1137 % elseif isequal(mode,'series(Dj)')%  isequal(mode,'st_series(Dj)') 1138 % nbpair=min(2*ref_j1,nbpair);%limit the number of pairs with positive first index 1139 % end 1140 % end 1141 % nbpair=min(200,nbpair);%limit the number of displayed pairs to 200 1145 1142 1146 1143 %% case with no Civ1 operation, netcdf files need to exist for reading 1147 1144 displ_pair={''}; 1145 nbpair=200;%default 1148 1146 select=ones(size(1:nbpair));%flag for displayed pairs =1 for display 1149 1147 testpair=0; 1150 1148 RootPath=get(handles.RootPath,'String'); 1151 1149 RootFile=get(handles.Civ2_ImageB,'String'); 1150 nbpair=200; %default 1152 1151 if index==1 % case civ1 1153 1152 if ~get(handles.CheckCiv1,'Value') % … … 1227 1226 % in mode 'pair j1j2', j1 and j2 are the file indices, else the indices 1228 1227 % are relative to the reference indices ref_i and ref_j respectively. 1228 testpair=0; %TODO: check 1229 1229 if isequal(mode,'series(Di)') 1230 1230 if testpair 
trunk/src/series/civ_series.m
r606 r609 58 58 if ~exist(filecell{1,1},'file') 59 59 msgbox_uvmat('WARNING','the first input file does not exist') 60 else 61 FileType=get_file_type(filecell{1,1}); 62 if isempty(find(strcmp(FileType,{'civdata','image','multimage','mmreader','video'})));% =1 for images 63 msgbox_uvmat('ERROR',['bad input file type for ' mfilename ': an image or civdata file is needed']) 64 end 60 65 end 61 66 return … … 85 90 MinIndex=cell2mat(Param.IndexRange.MinIndex); 86 91 [filecell,i_series,tild,j_series]=get_file_series(Param); 92 [FileType_A,FileInfo,MovieObject_A]=get_file_type(filecell{1,1}); 93 if strcmp(FileType_A,'civdata')% a civdata file has been introduced as input. 94 [FileType_A,FileInfo,MovieObject_A]=get_file_type(filecell{2,1}); 95 end 87 96 [i1_series_Civ1,i2_series_Civ1,j1_series_Civ1,j2_series_Civ1,check_bounds,NomTypeNc]=... 88 97 find_pair_indices(PairCiv1,i_series{1},j_series{1},MinIndex,MaxIndex); … … 118 127 119 128 NbField=numel(i1_series_Civ1); 120 [FileType_A,FileInfo,MovieObject_A]=get_file_type(filecell{1,1}); 129 121 130 FileType_B=FileType_A; 122 131 MovieObject_B=MovieObject_A; … … 143 152 144 153 %% get timing from the ImaDoc file or input video 145 [XmlData,NbSlice_calib,time,errormsg]=read_multimadoc(RootPath,SubDir,RootFile,FileExt,i1_series,i2_series,j1_series,j2_series); 154 XmlFileName=find_imadoc(RootPath,SubDir,RootFile,FileExt); 155 time=[]; 156 if ~isempty(XmlFileName) 157 XmlData=imadoc2struct(XmlFileName); 158 if isfield(XmlData,'Time') 159 time=XmlData.Time; 160 TimeSource='xml'; 161 end 162 if isfield(XmlData,'Camera') 163 if isfield(XmlData.Camera,'NbSlice')&& ~isempty(XmlData.Camera.NbSlice) 164 NbSlice_calib{iview}=XmlData.Camera.NbSlice;% Nbre of slices for Zindex in phys transform 165 if ~isequal(NbSlice_calib{iview},NbSlice_calib{1}) 166 msgbox_uvmat('WARNING','inconsistent number of Z indices for the two field series'); 167 end 168 end 169 if isfield(XmlData.Camera,'TimeUnit')&& ~isempty(XmlData.Camera.TimeUnit) 170 TimeUnit=XmlData.Camera.TimeUnit; 171 end 172 end 173 end 174 if strcmp(InputTable{iview,4},'*') 175 if ~isempty(VideoObject) 176 imainfo=get(VideoObject); 177 time=zeros(imainfo.NumberOfFrames+1,2); 178 time(:,2)=(0:1/imainfo.FrameRate:(imainfo.NumberOfFrames)/imainfo.FrameRate)'; 179 TimeSource='video'; 180 % set(han:dles.Dt_txt,'String',['Dt=' num2str(1000/imainfo.FrameRate) 'ms']);%display the elementary time interval in millisec 181 ColorType='truecolor'; 182 elseif ~isempty(imformats(regexprep(InputTable{iview,5},'^.','')))  isequal(InputTable{iview,5},'.vol')%&& isequal(NomType,'*')% multiframe image 183 if ~isempty(InputTable{iview,2}) 184 imainfo=imfinfo(fullfile(InputTable{iview,1},InputTable{iview,2},[InputTable{iview,3} InputTable{iview,5}])); 185 else 186 imainfo=imfinfo([FileBase InputTable{iview,5}]); 187 end 188 ColorType=imainfo.ColorType;%='truecolor' for color images 189 if length(imainfo) >1 %case of image with multiple frames 190 nbfield=length(imainfo); 191 nbfield_j=1; 192 end 193 end 194 end 195 146 196 %TODO: get time_A and time_B 147 % case of movies TODO TODO TODO 197 148 198 if isempty(time) && (strcmp(FileType,'video')  strcmp(FileType,'mmreader')) 149 199 set(handles.ListPairMode,'Value',1); … … 161 211 end 162 212 TimeUnit='s'; 213 end 163 214 %%%%% MAIN LOOP %%%%%% 164 215 
trunk/src/series/time_series.m
r606 r609 75 75 OutputDir=[Param.OutputSubDir Param.OutputDirExt]; 76 76 77 %% root input file(s) and type77 %% root input file(s) name, type and index series 78 78 RootPath=Param.InputTable(:,1); 79 79 RootFile=Param.InputTable(:,3); … … 90 90 % i1_series(iview,fileindex) expresses the same indices as a 1D array in file indices 91 91 %%%%%%%%%%%% 92 % NbSlice=1;%default93 % if isfield(Param.IndexRange,'NbSlice')&&~isempty(Param.IndexRange.NbSlice)94 % NbSlice=Param.IndexRange.NbSlice;95 % end96 92 nbview=numel(i1_series);%number of input file series (lines in InputTable) 97 93 nbfield_j=size(j1_series{1},1); %nb of fields for the j index (bursts or volume slices) 98 94 nbfield_i=size(i1_series{1},2); %nb of fields for the i index 99 95 nbfield=nbfield_j*nbfield_i; %total number of fields 100 101 %determine the file type on each line from the first input file 96 [first_i,tild,last_i,first_j,tild,last_j,errormsg]=get_index_range(Param.IndexRange); 97 if ~isempty(errormsg),display(errormsg),return,end 98 99 %% determine the file type on each line from the first input file 102 100 ImageTypeOptions={'image','multimage','mmreader','video'}; 103 101 NcTypeOptions={'netcdf','civx','civdata'}; … … 151 149 return 152 150 end 153 NomTypeOut= '_12_1';% output file index will indicate the first and last ref index in the series151 NomTypeOut=nomtype2pair(NomType{1});% determine the index nomenclature type for the output file 154 152 155 153 %% Set field names and velocity types … … 414 412 end 415 413 416 % name of result file417 OutputFile=fullfile_uvmat(RootPath{1},OutputDir,RootFile{1},FileExtOut,NomTypeOut, i1_series{1}(1),i1_series{1}(end),j1_series{1}(1),j1_series{1}(end));414 %% name of result file 415 OutputFile=fullfile_uvmat(RootPath{1},OutputDir,RootFile{1},FileExtOut,NomTypeOut,first_i,last_i,first_j,last_j); 418 416 errormsg=struct2nc(OutputFile,DataOut); %save result file 419 417 if isempty(errormsg) … … 422 420 displ_uvmat('ERROR',['error in Series/struct2nc: ' errormsg],checkrun) 423 421 end 424 425 422 426 423 %% plot the time series (the last one in case of multislices)
Note: See TracChangeset
for help on using the changeset viewer.