; docformat = 'rst'
;+
;
; :Uses: pp_editablecube__define, pp_getcubeheadervalue, pp_extractfields, pp_setcubeheadervalue, pp_readcube__define
;
; :Author: Paulo Penteado (pp.penteado@gmail.com), Nov/2009
;-
;+
; :Description:
; Initializes a pp_cubecollection object, either from a previously built file,
; or builds the file from cube files.
;
; :Params:
; savefile : in, required
; The name of the file that either will contain the object's data, or the data will be
; read from, depending on the build keyword.
;
; :Keywords:
; build : in, optional, default=0
; If set, the cubes named in cubefiles are read from disk and the container file is created.
; Otherwise, it is assumed the container file was previously created, and the object gets
; its data from that file.
; cubefiles : in, out, optional
; If build is set, a string array with the names of the cube files to read. If absent and build is
; set, all cubes found in the current directory (ending with '_eg.cub', '_ir_eg.cub', or '_vis_eg.cub',
; depending on the vis and ir keywords) are used, and their names are returned in this keyword.
; vis : in, optional, default=0
; If set, cubes matching '*_vis_eg.cub' are used when building the container file, instead of '*_eg.cub'.
; ir : in, optional, default=0
; If set, cubes matching '*_ir_eg.cub' are used when building the container file, instead of '*_eg.cub'.
;
; :Examples:
; See the example on pp_editablecube__define.
;
; :Author: Paulo Penteado (pp.penteado@gmail.com), Nov/2009
;-
function pp_cubecollection::init,savefile,build=build,cubefiles=cubefiles,vis=vis,ir=ir,compress=compress,$
class=class,_ref_extra=ex
compile_opt idl2
ret=0
;Defaults
class=n_elements(class) ? class : 'pp_editablecube'
compress=n_elements(compress) eq 1 ? compress : 1B
build=n_elements(build) eq 1 ? build : 0
if (n_elements(savefile) eq 0) then begin
print,'pp_cubecollection: collection file not provided'
return,0
endif else self.savefile=savefile
idstring='pp_cubecollection_container' ;id to test if savefile was created by this object
error_status=0;catch,error_status
if (error_status ne 0) then begin
catch,/cancel
print,'pp_cubecollection::init : Could not read file "',self.savefile,'"'
self->cleanup
endif else begin
;Build savefile
if build then begin
ncubes=n_elements(cubefiles)
suff=keyword_set(vis) ? '_vis_eg.cub' : (keyword_set(ir) ? '_ir_eg.cub' : '_eg.cub')
cubefiles=ncubes gt 0 ? cubefiles : file_search('*'+suff,count=ncubes)
print,ncubes,' cubes found'
if (ncubes eq 0) then message,'No cubes found to build collection from'
print,'Building collection file, this may take a long time and use a lot of memory if there are many cubes'
ocubes=objarr(ncubes)
for i=0,ncubes-1 do begin
print,'Reading ',cubefiles[i],' (',strcompress(string(i+1,'/',ncubes,')'),/rem)
ocubes[i]=obj_new(class,file=cubefiles[i],_strict_extra=ex)
endfor
;Build index of heap variables, needed to retrieve individual elements of ocube from savefile
heapinds=long(strsplit(strjoin(string(ocubes,/print)),'<ObjHeapVar',/regex,/extract))
;Make savefile
print,'Writing savefile'
save,file=savefile,idstring,ncubes,cubefiles,heapinds,ocubes,compress=compress
;Get rid of the large ocubes array
obj_destroy,ocubes
endif
;Initialize the object to read the savefile
self.osav=obj_new('idl_savefile',savefile,/relaxed_structure_assignment)
;Get metadata from savefile, if initializing from it
if (~build) then begin
oidstring=idstring
self.osav->restore,'idstring'
if (idstring[0] ne oidstring) then message,'Not a pp_cubecollection savefile'
self.osav->restore,['ncubes','cubefiles','heapinds']
;Make a dummy editablecube object just to make sure its methods get compiled
a=obj_new('pp_editablecube',file='')
obj_destroy,a
endif
;Save fields into self
self.ncubes=ncubes
self.cubefiles=ptr_new(cubefiles,/no_copy)
self.heapinds=ptr_new(heapinds,/no_copy)
obj_destroy,self.osav
ret=1
endelse
return,ret
end
pro pp_cubecollection::cleanup
compile_opt idl2,hidden
ptr_free,self.cubefiles,self.heapinds
obj_destroy,self.osav
end
;+
; :Description:
; Retrieves selected cubes from the container, by their indexes or filenames.
;
; :Returns:
; If index or name are scalars, the object with the selected cube. If they are arrays,
; an object array of the same dimensions, with each containing the corresponding object.
; If a requested object is not found, a null object is returned in its place.
; If both index and name are provided, the index values are used to select the cubes,
; with their names returned in names.
;
; The object references returned are to the same objects: no copy is made on successive calls
; to get the same cube. A copy can be made making a new pp_editablecube object from the returned
; object reference, as shown in the example.
;
; :Params:
; index : in, optional
; The index numbers of the cubes to retrieve.
;
; :Keywords:
; name : in, optional
; The names of the cubes to retrieve.
;
; :Examples:
; See the example on pp_editablecube__define.
;
; :Author: Paulo Penteado (pp.penteado@gmail.com), Nov/2009
;-
function pp_cubecollection::getcube,index,name=name
compile_opt idl2
ni=n_elements(index)
nn=n_elements(name)
if (ni eq 0) then begin
if (nn eq 0) then ret=obj_new() else begin
ret=objarr(nn)
index=lonarr(nn)
for i=0,nn-1 do index[i]=(where(*self.cubefiles eq name[i]))[0]
ni=nn
endelse
endif else begin
ret=objarr(ni)
name=strarr(ni)
endelse
sav=obj_valid(self.osav)
if (~sav) then self.osav=obj_new('idl_savefile',self.savefile,/relaxed_structure_assignment)
for i=0,ni-1 do begin
if (index[i] ge 0)&&(index[i] lt self.ncubes) then begin
self.osav->restore,(*self.heapinds)[index[i]],/object_heapvar,new_heapvar=tmp
ret[i]=tmp
name[i]=tmp->getproperty(/file)
endif
endfor
if (~sav) then obj_destroy,self.osav
return,ret
end
pro pp_cubecollection::opensav,close=close
compile_opt idl2
if keyword_set(close) then obj_destroy,self.osav else if (~obj_valid(self.osav)) $
then self.osav=obj_new('idl_savefile',self.savefile,/relaxed_structure_assignment)
end
;+
; :Description:
; Returns a string array with the filenames of all cubes in the collection.
;
; :Keywords:
; ncubes, out: optional
; The number of cubes contained in the collection.
;
; :Examples:
; See the example on pp_editablecube__define.
;
; :Author: Paulo Penteado (pp.penteado@gmail.com), Nov/2009
;-
function pp_cubecollection::filenames,ncubes=ncubes
compile_opt idl2
ncubes=self.ncubes
return,*self.cubefiles
end
;+
; :Description:
; Object that contains a collection of cubes, that can be retrieved as pp_editablecube objects
; by their names or indexes. The cubes are stored in a savefile instead of memory, so initializing
; from an existing file is a quick and light operation. The cube data is only read when that particular
; cube is to be retrieved, and only those selected to be retrieved are read from the file. Thus a savefile
; made by a pp_cubecollecion object is a portable, convenient and efficient way to store and carry several cubes.
;
; :Examples:
; Initially, a container file must be built from cube files. To take all files ending with
; '_ir_eg.cub' from the current directory (which can be a long operation and use a lot of
; memory if there are many cubes)::
;
; a=obj_new('pp_cubecollection','testcollection.sav',/build,/ir)
;
; If a collection savefile already exists, no matter how large it is, loading it is a quick
; and light operation, because only meta-data is read::
;
; a=obj_new('pp_cubecollection','testcollection.sav')
;
; To get the names of the cubes present in the collection::
;
; print,a->filenames(ncubes=ncubes)
; ;CM_1467426144_5_ir_eg.cub CM_1467426479_1_ir_eg.cub CM_1467426798_1_ir_eg.cub CM_1467427145_1_ir_eg.cub
; ;(...)
; print,ncubes
; 57
;
; To retrieve the first 3 cubes::
;
; b=a->getcube([0,1,2])
;
; To retrieve the cube of name CM_1467426479_1_ir_eg::
;
; c=a->getcube(name='CM_1467426479_1_ir_eg.cub')
;
; b[1] and c are the same object::
;
; ;print,b[1],c
;
; To make a copy of that object, to keep after the collection is destroyed::
;
; d=obj_new('pp_editablecube',c)
; print,obj_valid(b),obj_valid(c),obj_valid(d)
; ;1 1 1
; ;1
; ;1
; obj_destroy,b
; print,obj_valid(b),obj_valid(c),obj_valid(d)
; ;0 0 0
; ;0
; ;1
;
; Get rid of the collection once it is done with. This does not affect the savefile,
; which can be used to reobtain this collection in the future::
;
; obj_destroy,a
;
; See pp_editablecube__define for examples on how to use the cube objects.
;
; :Uses: pp_editablecube__define, pp_getcubeheadervalue, pp_extractfields, pp_setcubeheadervalue, pp_readcube__define
;
; :Author: Paulo Penteado (pp.penteado@gmail.com), Nov/2009
;-
pro pp_cubecollection__define
compile_opt idl2
void={pp_cubecollection,savefile:'',ncubes:0L,cubefiles:ptr_new(),heapinds:ptr_new(),osav:obj_new()}
end