radio-astro-tools / spectral-cube

Library for reading and analyzing astrophysical spectral data cubes
http://spectral-cube.rtfd.org
BSD 3-Clause "New" or "Revised" License
96 stars 63 forks source link

Problem to update SpectralCube values after baseline subtraction: 'SpectralCube' object does not support item assignment #904

Open astro-pablo opened 7 months ago

astro-pablo commented 7 months ago

I can not update the intensity values within a SpectralCube after baseline subtraction:

x               = sub_cube_v_range[:,j,i].spectral_axis / (u.km / u.s)
y               = sub_cube_v_range[:,j,i] 
baseline   = np.polynomial.Polynomial(params['coef'])(x) * spectrum_avg.unit 
base_sub_y = y.copy()-baseline          
print(type(y.copy()))     
print(type(base_sub_y))
sub_cube_v_range[:,j,i] = base_sub_y 

output:

<class 'spectral_cube.lower_dimensional_structures.OneDSpectrum'>
<class 'spectral_cube.lower_dimensional_structures.OneDSpectrum'>
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[232], line 102
     98 print(type(base_sub_y))
     99 # print(type(sub_cube_v_base[:,j,i]))
    100 # print(type(sub_cube_v_base))
--> 102 sub_cube_v_range[:,j,i] = base_sub_y # * spectrum_avg.unit 
    103 masked_y             = y.copy()
    104 masked_y[~non_peaks] = np.nan

TypeError: 'SpectralCube' object does not support item assignment

I tried by updating the values of a copy of the cube, but I get the following error when creating the copy:

import copy   # to create mutable copy of objects (deeper than = assigment)

sub_cube_v           = sub_cube.with_spectral_unit(u.km / u.s, velocity_convention='optical', rest_value=line_wave * u.AA) # transform to radial velocities
sub_cube_v_range     = sub_cube_v.spectral_slab(-100 *u.km / u.s, 100 *u.km / u.s) # select range in velocities
sub_cube_v_base      = sub_cube_v_range.copy() 

output:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[233], line 16
     14 sub_cube_v           = sub_cube.with_spectral_unit(u.km [/](http://localhost:8888/) u.s, velocity_convention='optical', rest_value=line_wave * u.AA) # transform to radial velocities
     15 sub_cube_v_range     = sub_cube_v.spectral_slab(-100 *u.km [/](http://localhost:8888/) u.s, 100 *u.km [/](http://localhost:8888/) u.s) # select range in velocities
---> 16 sub_cube_v_base      = sub_cube_v_range.copy() 
     18 #sub_cube_v_range     = sub_cube_v.spectral_slab(velo_i *u.km [/](http://localhost:8888/) u.s, velo_f *u.km [/](http://localhost:8888/) u.s) # select range in velocities
     19 
     20 # sub_cube_v_range[:, 20, 20].quicklook()
     21 spectrum_avg    = sub_cube_v_range.mean(axis=(1,2))

AttributeError: 'SpectralCube' object has no attribute 'copy'

which is very strange since the y.copy() in the previous code just works fine.

keflavich commented 7 months ago

SpectralCubes are intentionally not mutable - mutability requires loading the whole object into memory, in general.

y.copy() is copying a OneDSpectrum object, which is not a SpectralCube object. If you want a copy of a cube, you can get that easily enough with:

cubecopy = cube[:]

If you're trying to baseline-subtract a cube, you can do:

baseline   = np.polynomial.Polynomial(params['coef'])(x) * spectrum_avg.unit 
baseline_subtracted_cube = cube - baseline[:,None,None]

based on your code. It will not - and cannot, by construction - update the original cube in place.