Repository: astropy/photutils

Issue:
Source catalogue to_table method giving RepresenterError
I'm trying to output the results from SourceCatalog into a Qtable with the to_table method using columns that are not the defaults.
(Photutils v 2.0.2)

The output fails giving me the error:
`RepresenterError: ('cannot represent an object', 'eccentricity')`

(removing eccentricity from the list of columns to include leads to other columns raising the same error, e.g. area, orientation and so on)

This is the code I use to get the source catalog and table:
```
scat = SourceCatalog(data_det, segmap_debl, convolved_data=None, error=err_det, mask=mask_det==0, wcs=wcs)
outcols = ['label', 'xcentroid_win', 'ycentroid_win', 'sky_centroid_win', 'area', 'semimajor_sigma', 'semiminor_sigma', 'eccentricity', 'orientation', 'segment_flux', 'segment_fluxerr']
dettab = scat.to_table(columns=outcols)
```
Using the default column names works fine (`scat.to_table()`) and outputs the offending columns just fine. But I need some of the non-default outputs as well. I can of course manually construct a table from the source catalog, but it would be simpler if `to_table` would work for this.

I suspect this has something to do with the units of the columns? But the error output is not very informative (YAML error maybe?) so I can't tell for sure.

Discussion:

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index d5ad6598..5c692d16 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -10,6 +10,13 @@ New Features
 Bug Fixes
 ^^^^^^^^^
 
+- ``photutils.segmentation``
+
+  - Fixed a bug where the table output from the ``SourceCatalog``
+    ``to_table`` method could have column names with a ``np.str_``
+    representation instead of ``str`` representation when using NumPy
+    2.0+. [#1956]
+
 API Changes
 ^^^^^^^^^^^
 
diff --git a/photutils/segmentation/catalog.py b/photutils/segmentation/catalog.py
index df2e7467..439522c7 100644
--- a/photutils/segmentation/catalog.py
+++ b/photutils/segmentation/catalog.py
@@ -967,8 +967,10 @@ class SourceCatalog:
         """
         if columns is None:
             table_columns = self.default_columns
+        elif isinstance(columns, str):
+            table_columns = [columns]
         else:
-            table_columns = np.atleast_1d(columns)
+            table_columns = columns
 
         tbl = QTable()
         tbl.meta.update(self.meta)  # keep tbl.meta type


Test patch:
diff --git a/photutils/segmentation/tests/test_catalog.py b/photutils/segmentation/tests/test_catalog.py
index 39b6a3cb..eb6113e2 100644
--- a/photutils/segmentation/tests/test_catalog.py
+++ b/photutils/segmentation/tests/test_catalog.py
@@ -275,6 +275,16 @@ class TestSourceCatalog:
         assert len(tbl) == 7
         assert tbl.colnames == columns
 
+        tbl = self.cat.to_table(self.cat.default_columns)
+        for col in tbl.columns:
+            assert isinstance(col, str)
+            assert not isinstance(col, np.str_)
+
+        tbl = self.cat.to_table('label')
+        for col in tbl.columns:
+            assert isinstance(col, str)
+            assert not isinstance(col, np.str_)
+
     def test_invalid_inputs(self):
         segm = SegmentationImage(np.zeros(self.data.shape, dtype=int))
         match = 'segment_img must have at least one non-zero label'