function pp_editablecube::init,orcube=orcube,file=file,special=special,preservespecial=preservespecial
compile_opt idl2,hidden
ret=0
if (n_elements(file) eq 1) then ret=self->pp_readcube::init(file,special=special) else begin
orcube->getproperty,all=all
self.file=all.file
self.special=all.special
self.labels=ptr_new(all.labels)
self.tlabels=ptr_new(strtrim(all.labels,2))
self.history=ptr_new(all.history)
self.thistory=ptr_new(strtrim(all.history,2))
self.core=ptr_new(all.core)
if (all.nback gt 0) then self.backplanes=ptr_new(all.backplanes)
if (all.nside gt 0) then self.sideplanes=ptr_new(all.sideplanes)
if (all.nbottom gt 0) then self.bottomplanes=ptr_new(all.bottomplanes)
self.info=all.info
self.raw=ptr_new(all.raw)
self.wavs=ptr_new(all.wavelengths)
self.bnames=ptr_new(all.backnames)
self.snames=ptr_new(all.sidenames)
self.bonames=ptr_new(all.bottomnames)
self.units=all.units
self.bunits=ptr_new(all.backunits)
self.bunits=ptr_new(all.sideunits)
self.bunits=ptr_new(all.bottomunits)
ret=1
endelse
if (ret eq 0) then return,ret
self.oldlabels=ptr_new(*self.labels)
self.oldhistory=ptr_new(*self.history)
self.llength=strlen(strjoin(*self.labels))+2L*n_elements(*self.labels)
self.oldllength=self.llength
self.hlength=strlen(strjoin(*self.history))+2L*n_elements(*self.history)
self.oldhlength=self.hlength
self.binlength=n_elements(*self.raw)*self.info.bytes
if (n_elements(preservespecial) eq 1) then self.preservespecial=preservespecial
return,ret
end
pro pp_editablecube::setproperty,core=core,$
backplanes=backplanes,sideplanes=sideplanes,bottomplanes=bottomplanes,$
backnames=bnames,sidenames=snames,bottomnames=bonames,wavelengths=wavs,$
backunits=bunits,sideunits=sunits,bottomunits=bounits,wavelengthunits=wunits
compile_opt idl2
typechanged=0
dimschanged=[0,0,0]
corechange=(size(core,/n_dimensions) eq 3)
backchange=(size(backplanes,/n_dimensions) eq 3)
sidechange=(size(sideplanes,/n_dimensions) eq 3)
bottomchange=(size(sideplanes,/n_dimensions) eq 3)
if corechange then self->updatecore,core,dimschanged,typechanged
anydimschanged=(total(dimschanged) ne 0)
oldsuffdims=self.info.suffdims
if backchange||dimschanged[0]||dimschanged[1]||typechanged then self->updatesuffix,suffix=backplanes,'BAND',2,dimschanged,typechanged
if sidechange||dimschanged[1]||dimschanged[2]||typechanged then self->updatesuffix,suffix=sideplanes,'SAMPLE',0,dimschanged,typechanged
if bottomchange||dimschanged[0]||dimschanged[2]||typechanged then self->updatesuffix,suffix=bottomplanes,'LINE',1,dimschanged,typechanged
if (~array_equal(self.info.suffdims,oldsuffdims)) then begin
self.info.dims=self.info.coredims+self.info.suffdims
pp_setcubeheadervalue,*self.labels,'SUFFIX_ITEMS',self.info.suffdims
endif
if (corechange||backchange||sidechange||bottomchange) then begin
ptr_free,self.raw
raw=make_array(self.info.dims,type=self.info.datatype,/nozero)
special=self->getspecialvalues(default=~self.preservespecial)
raw[*]=special.null
cd=self.info.coredims
sd=self.info.suffdims
raw[0:cd[0]-1,0:cd[1]-1,0:cd[2]-1]=*self.core
if (sd[2] gt 0) then raw[0:cd[0]-1,0:cd[1]-1,cd[2]:cd[2]+sd[2]-1]=*self.backplanes
if (sd[0] gt 0) then raw[cd[0]:cd[0]+sd[0]-1,0:cd[1]-1,0:cd[2]-1]=*self.sideplanes
if (sd[1] gt 0) then raw[0:cd[0]-1,cd[1]:cd[1]+sd[1]-1,0:cd[2]-1]=*self.bottomplanes
byteorder,raw,swap_if_big_endian=self.info.littleendian,$
swap_if_little_endian=~self.info.littleendian
self.raw=ptr_new(raw,/no_copy)
endif
if (n_elements(wunits) eq 1) then begin
self.wunits=wunits
pp_setcubeheadervalue,*self.labels,'CORE_UNIT',self.wunits
endif
if (self.info.suffdims[2] gt 0) then begin
*self.bunits=(n_elements(bunits) eq self.info.suffdims[2]) ? bunits : replicate('UNKNOWN',self.info.suffdims[2])
pp_setcubeheadervalue,*self.labels,'BAND_SUFFIX_UNIT',*self.bunits
endif
if (self.info.suffdims[0] gt 0) then begin
*self.sunits=(n_elements(sunits) eq self.info.suffdims[0]) ? sunits : replicate('UNKNOWN',self.info.suffdims[0])
pp_setcubeheadervalue,*self.labels,'SAMPLE_SUFFIX_UNIT',*self.sunits
endif
if (self.info.suffdims[1] gt 0) then begin
*self.bounits=(n_elements(bounits) eq self.info.suffdims[1]) ? bounits : replicate('UNKNOWN',self.info.suffdims[1])
pp_setcubeheadervalue,*self.labels,'LINE_SUFFIX_UNIT',*self.info.bounits
endif
if dimschanged[2]||(n_elements(wavs) gt 0) then self->updatedatainfo,names=wavs,/core
if (oldsuffdims[2] ne self.info.suffdims[2])||(n_elements(bnames) gt 0) then $
self->updatedatainfo,names=bnames,type='BAND'
if (oldsuffdims[0] ne self.info.suffdims[0])||(n_elements(snames) gt 0) then $
self->updatedatainfo,names=snames,type='SAMPLE'
if (oldsuffdims[1] ne self.info.suffdims[1])||(n_elements(bonames) gt 0) then $
self->updatedatainfo,names=bonames,type='LINE'
self->updatelocations
*self.tlabels=strtrim(*self.labels,2)
end
pro pp_editablecube::updatedatainfo,names=names,type=type,core=core
compile_opt idl2,hidden
core=n_elements(core) eq 1 ? core : 0
if (core) then begin
*self.wavs=(n_elements(wavs) eq self.info.coredims[2]) ? wavs : replicate ('UNKNOWN',self.info.coredims[2])
pp_setcubeheadervalue,*self.labels,'BAND_BIN_CENTER',*self.wavs
endif else begin
case type of
'BAND' : begin & nsuf=self.info.suffdims[2] & ptr=self.bnames & end
'SAMPLE' : begin & nsuf=self.info.suffdims[0] & ptr=self.snames & end
'LINE' : begin & nsuf=self.info.suffdims[1] & ptr=self.bonames & end
endcase
if ptr_valid(ptr) then begin
*ptr=(n_elements(names) eq nsuf) ? names : 'UNKNOWN_'+strtrim(sindgen(nsuf),2)
pp_setcubeheadervalue,*self.labels,type+'_SUFFIX_NAME',*ptr
endif
endelse
end
pro pp_editablecube::updatesuffix,suffix=suffix,name,ind,dimschanged,typechanged
compile_opt idl2,hidden
suffixlabels=['_SUFFIX_NAME','_SUFFIX_UNIT','_SUFFIX_ITEM_TYPE',$
'_SUFFIX_ITEM_BYTES','_SUFFIX_BASE','_SUFFIX_MULTIPLIER',$
'_SUFFIX_VALID_MINIMUM','_SUFFIX_NULL','_SUFFIX_LOW_REPR_SAT',$
'_SUFFIX_LOW_INSTR_SAT','_SUFFIX_HIGH_INSTR_SAT','_SUFFIX_HIGH_REPR_SAT']
case name of
'BAND' : begin & ptrs=[self.bnames,self.backplanes,self.bunits] & dim=2 & end
'SAMPLE': begin & ptrs=[self.snames,self.sideplanes,self.sunits] & dim=0 & end
'LINE' : begin & ptrs=[self.bonames,self.bottomplanes,self.bounits] & dim=1 & end
endcase
szs=size(suffix,/l64)
if (szs[0] eq 3) then begin
tmp=make_array(szs[1:3],type=self.info.datatype)
tmp[*]=suffix
if ptr_valid(ptrs[1]) then *(ptrs[1])=temporary(tmp) else begin
ptrs[1]=ptr_new(tmp,/no_copy)
tmp=replicate('UNKNOWN',szs[ind+1])
ptrs[0]=ptr_new(tmp)
ptrs[2]=ptr_new(tmp,/no_copy)
case name of
'BAND' : begin & self.bnames=ptrs[0] & self.backplanes=ptrs[1] & self.bunits=ptrs[2] & end
'SAMPLE': begin & self.snames=ptrs[0] & self.sideplanes=ptrs[1] & self.sunits=ptrs[2] & end
'LINE' : begin & self.bonames=ptrs[0] & self.bottomplanes=ptrs[1] & self.bounits=ptrs[2] & end
endcase
endelse
if (typechanged || (szs[ind+1] ne self.info.suffdims[ind])) then begin
pp_setcubeheadervalue,*self.labels,name+'_SUFFIX_ITEM_BYTES',replicate(self.info.bytes,szs[ind+1])
pp_setcubeheadervalue,*self.labels,name+'_SUFFIX_ITEM_TYPE',replicate(self.info.type,szs[ind+1])
pp_setcubeheadervalue,*self.labels,name+'_SUFFIX_BASE',replicate(0.0,szs[ind+1])
pp_setcubeheadervalue,*self.labels,name+'_SUFFIX_MULTIPLIER',replicate(1.0,szs[ind+1])
special=self->getspecialvalues(default=typechanged)
pp_setcubeheadervalue,*self.labels,name+'_SUFFIX_VALID_MINIMUM',$
replicate((self.info.bytes lt 4 ? special.valid_min : string(special.valid_min,format='("16#",Z08,"#")')),szs[ind+1])
pp_setcubeheadervalue,*self.labels,name+'_SUFFIX_NULL',$
replicate((self.info.bytes lt 4 ? special.null : string(special.null,format='("16#",Z08,"#")')),szs[ind+1])
pp_setcubeheadervalue,*self.labels,name+'_SUFFIX_LOW_REPR_SAT',$
replicate((self.info.bytes lt 4 ? special.low_repr_sat : string(special.low_repr_sat,format='("16#",Z08,"#")')),szs[ind+1])
pp_setcubeheadervalue,*self.labels,name+'_SUFFIX_LOW_INSTR_SAT',$
replicate((self.info.bytes lt 4 ? special.low_instr_sat : string(special.low_instr_sat,format='("16#",Z08,"#")')),szs[ind+1])
pp_setcubeheadervalue,*self.labels,name+'_SUFFIX_HIGH_INSTR_SAT',$
replicate((self.info.bytes lt 4 ? special.high_instr_sat : string(special.high_instr_sat,format='("16#",Z08,"#")')),szs[ind+1])
pp_setcubeheadervalue,*self.labels,name+'_SUFFIX_HIGH_REPR_SAT',$
replicate((self.info.bytes lt 4 ? special.high_repr_sat : string(special.high_repr_sat,format='("16#",Z08,"#")')),szs[ind+1])
endif
self.info.suffdims[ind]=szs[ind+1]
endif else begin
for i=0,n_elements(suffixlabels)-1 do pp_setcubeheadervalue,*self.labels,$
name+suffixlabels[i]
ptr_free,ptrs[0:1]
self.info.suffdims[ind]=0L
endelse
end
pro pp_editablecube::updatecore,core,dimschanged,typechanged
compile_opt idl2,hidden
*self.core=core
szc=size(core,/l64)
newdims=szc[1:3]
if ~array_equal(newdims,self.info.coredims) then begin
dimschanged=newdims ne self.info.coredims
self.info.coredims=newdims
self.info.dims=self.info.coredims+self.info.suffdims
pp_setcubeheadervalue,*self.labels,'CORE_ITEMS','('+string(newdims,format='(3(I0,:,","))')+')'
endif
typechanged=szc[4] ne self.info.datatype
if typechanged then begin
self.info.type=self.info.littleendian ? 'PC_' : 'SUN_'
oldbytes=self.info.bytes
case szc[4] of
1 : begin & self.info.type+='INTEGER' & self.info.bytes=1 & end
2 : begin & self.info.type+='INTEGER' & self.info.bytes=2 & end
3 : begin & self.info.type+='INTEGER' & self.info.bytes=3 & end
4 : begin & self.into.type+='REAL' & self.info.bytes=4 & end
5 : begin & self.info.type+='REAL' & self.info.bytes=8 & end
else : begin & self.into.type+='INTEGER' & self.info.bytes=8 & end
endcase
self.info.datatype=szc[4]
pp_setcubeheadervalue,*self.labels,'CORE_ITEM_TYPE',self.info.type
pp_setcubeheadervalue,*self.labels,'CORE_ITEM_BYTES',self.info.bytes
pp_setcubeheadervalue,*self.labels,'SUFFIX_BYTES',self.info.bytes
special=self->getspecialvalues(/default)
special=self->getspecialvalues(default=typechanged)
pp_setcubeheadervalue,*self.labels,'CORE_VALID_MINIMUM',$
replicate(self.info.bytes lt 4 ? special.valid_min : string(special.valid_min,format='("16#",Z08,"#")'),szc[3])
pp_setcubeheadervalue,*self.labels,'CORE_NULL',$
replicate(self.info.bytes lt 4 ? special.null : string(special.null,format='("16#",Z08,"#")'),szc[3])
pp_setcubeheadervalue,*self.labels,'CORE_LOW_REPR_SAT',$
replicate(self.info.bytes lt 4 ? special.low_repr_sat : string(special.low_repr_sat,format='("16#",Z08,"#")'),szc[3])
pp_setcubeheadervalue,*self.labels,'CORE_LOW_INSTR_SAT',$
replicate(self.info.bytes lt 4 ? special.low_instr_sat : string(special.low_instr_sat,format='("16#",Z08,"#")'),szc[3])
pp_setcubeheadervalue,*self.labels,'CORE_HIGH_INSTR_SAT',$
replicate(self.info.bytes lt 4 ? special.high_instr_sat : string(special.high_instr_sat,format='("16#",Z08,"#")'),szc[3])
pp_setcubeheadervalue,*self.labels,'CORE_HIGH_REPR_SAT',$
replicate(self.info.bytes lt 4 ? special.high_repr_sat : string(special.high_repr_sat,format='("16#",Z08,"#")'),szc[3])
endif
end
pro pp_editablecube::updatelocations
compile_opt idl2,hidden
self.llength=strlen(strjoin(*self.labels))+2L*n_elements(*self.labels)
changelab=self.llength ne self.oldllength
self.hlength=strlen(strjoin(*self.history))+2L*n_elements(*self.history)
changehist=self.hlength ne self.oldhlength
self.binlength=n_elements(*self.raw)*self.info.bytes
changebin=self.oldbinlength ne self.binlength
self.info.labelrecords>=(1+ceil(double(self.llength)/self.info.recordbytes,/l64))
self.info.historyrecords>=ceil(double(self.hlength)/self.info.recordbytes,/l64)
self.info.binaryrecords=ceil(double(self.binlength)/self.info.recordbytes,/l64)
self.info.historystart=self.info.labelrecords
self.info.binarystart=self.info.historystart+self.info.labelrecords
self.info.filerecords=self.info.labelrecords+self.info.historyrecords+self.info.binaryrecords
pp_setcubeheadervalue,*self.labels,'FILE_RECORDS',self.info.filerecords
pp_setcubeheadervalue,*self.labels,'LABEL_RECORDS',self.info.labelrecords
pp_setcubeheadervalue,*self.labels,'\^HISTORY',self.info.historystart+1
pp_setcubeheadervalue,*self.labels,'\^QUBE',self.info.binarystart+1
self.llength=strlen(strjoin(*self.labels))+2L*n_elements(*self.labels)
self.oldllength=self.llength
self.oldhlength=self.hlength
self.oldbinlength=self.binlength
end
pro pp_editablecube::headeredit,key=key,value=value,append=append,history=hist
compile_opt idl2
hist=n_elements(hist) eq 1 ? hist : 0
tmp=hist ? *self.history : *self.labels
if (n_elements(append) gt 0) then pp_setcubeheadervalue,tmp,append=append else begin
if (n_elements(value) gt 0) then pp_setcubeheadervalue,tmp,key,value else pp_setcubeheadervalue,tmp,key
endelse
if (hist) then *self.history=tmp else *self.labels=tmp
end
pro pp_editablecube::write,filename
compile_opt idl2
filename=n_elements(filename) eq 1 ? filename : self.newfile
self.newfile=filename
if (self.newfile eq '') then message,'Filename required to write the cube'
print,'Writing cube to file ',filename
openw,unit,self.newfile,/get_lun
writeu,unit,strjoin((*self.labels)+string(13B)+string(10B))
point_lun,unit,self.info.recordbytes*self.info.historystart
writeu,unit,strjoin((*self.history)+string(13B)+string(10B))
point_lun,unit,self.info.recordbytes*self.info.binarystart
writeu,unit,*self.raw
point_lun,unit,self.info.recordbytes*self.info.filerecords
free_lun,unit
end
pro pp_editablecube::export,file,format=format
compile_opt idl2,logical_predicate
format=n_elements(format) ? format : 'fits'
c=self
templ={}
if c.bands then begin
bandnames=strtrim(sindgen(c.bands),2)
ml=max(strlen(bandnames))
bandnames='BAND_'+string(sindgen(c.bands),format='(I0'+strtrim(ml,2)+')')
foreach bn,bandnames do templ=create_struct(templ,bn,0d0)
endif else templ={}
foreach bn,c.backnames do templ=create_struct(templ,idl_validname(bn,/convert_all),0d0)
cubestruct=replicate(templ,c.lines*c.samples)
if c.bands then begin
core=reform(c.core,c.samples*c.lines,c.bands)
for i=0,c.bands-1 do cubestruct.(i)=core[*,i]
endif
if c.nback then begin
backplanes=reform(c.backplanes,c.lines*c.samples,c.nback)
for i=0,c.nback-1 do cubestruct.(i+c.bands)=backplanes[*,i]
endif
if strlowcase(format) eq 'fits' then mwrfits,cubestruct,file,/create
if strlowcase(format) eq 'csv' then write_csv_pp,file,cubestruct,/titles
end
pro pp_editablecube::cleanup
compile_opt idl2,hidden
ptr_free,self.oldlabels,self.oldhistory
self->pp_readcube::cleanup
end
pro pp_editablecube__define
void={pp_editablecube,inherits pp_readcube,newfile:'',$
oldlabels:ptr_new(),oldhistory:ptr_new(),$
llength:0L,oldllength:0L,hlength:0L,oldhlength:0L,$
binlength:0LL,oldbinlength:0LL,preservespecial:0}
end