specutils icon indicating copy to clipboard operation
specutils copied to clipboard

specutils.Spectrum1D refuses a Pandas Series as input

Open janerigby opened this issue 4 years ago • 5 comments

I tried adapting the specutils demo notebook for my own spectra. The input spectrum is in a pandas dataframe, which specutils.Spectrum1D() refuses as follows:

----> 1 s1723_spec = specutils.Spectrum1D(spectral_axis = df_s1723['wave'] * u.AA, flux=df_s1723['fnu'] * u.Unit('Jansky'))

~/anaconda3/envs/astroconda/lib/python3.6/site-packages/specutils/spectra/spectrum1d.py in init(self, flux, spectral_axis, wcs, velocity_convention, rest_value, redshift, radial_velocity, bin_specification, **kwargs) 97 if flux is not None: 98 if not isinstance(flux, u.Quantity): ---> 99 raise ValueError("Flux must be a Quantity object.") 100 elif flux.isscalar: 101 flux = u.Quantity([flux])

ValueError: Flux must be a Quantity object.

The kludgy workaround is to put .values after each Series: s1723_spec = specutils.Spectrum1D(spectral_axis = df_s1723['wave'].values * u.AA, flux=df_s1723['fnu'].values * u.Unit('Jansky'))

A better solution would be for astropy to gracefully accept a pandas Series. (And maybe even a pandas dataframe? Hey, I can dream.)

janerigby avatar Dec 07 '20 20:12 janerigby

Thanks @janerigby! I think we can certainly do something at the specutils level to help compatibility, but this might also be a higher-level astropy question of getting Quantity objects to accept pandas Series.

nmearl avatar Dec 07 '20 21:12 nmearl

Yes, I've worked with @eteq in the past to try to get Astropy to stop refusing pandas Series, in cases where a numpy array is accepted. This is a new case. I don't know where in Astropy to file the ticket. Help?

janerigby avatar Dec 18 '20 15:12 janerigby

It is a good idea! You can file the feature request here.

nmearl avatar Dec 19 '20 05:12 nmearl

Done, https://github.com/astropy/astropy/issues/11247

janerigby avatar Jan 13 '21 15:01 janerigby

As pointed out in https://github.com/astropy/astropy/issues/11247#issuecomment-759742700 the problem is due to pandas' incorrect handling of series.__mul__(u.Unit()) and can only be fixed there. Among the various slightly less kludgy workarounds it is noteworthy that u.Quantity(df['wave'] * u.AA) works as well, i.e. this could in principle be implemented to intercept this input in the Spectrum1D initialisation, i.e. in https://github.com/astropy/specutils/blob/57dd2b28e5122e00e28333043192d30ec9f78a9d/specutils/spectra/spectrum1d.py#L114-L115 add an additional

                try:
                    flux = u.Quantity(flux)

For plain ndarray or Series input this would create a dimensionless quantity and of course raising a UnitError further down, but the same applies to any input with incompatible units, so I don't think this would create a source of additional confusion. Anyway it would perhaps be preferable to check for valid units already right there.

The question is probably how far specutils wants to go to accommodate non-numpy compliant input.

dhomeier avatar Apr 25 '21 12:04 dhomeier