예제 #1
0
def add_epoch(table, epoch):
    """
    Add an epoch column to the table.

    :param table:
    :param epoch:
    :return:
    """
    col = table.Column(data=np.ones(len(table), dtype=np.int32) * epoch,
                       name='epoch')
    table.add_column(col)
    return table
예제 #2
0
def process_table(table, epochs, band, blind=True,quiet=True, report=False):
    print 'Removing large boxes'
    too_large_rows=np.where(table['stamp_size']>100)[0]
    table.remove_rows(too_large_rows)
    
    print "Lower casing"
    lowercase(table)
    lowercase(epochs)

    print "Sorting and grouping"
    epochs.sort(["id", "expnum"])
    table.sort("identifier")

    print 'Adding chi2_pixel'
    chi2 = -2 * table['likelihood']
    effective_npix = table['stamp_size']**2 * table['n_exposure'] * (1-table['mean_mask_fraction'])
    chi2_pixel = chi2 / effective_npix
    col = astropy.table.Column(name='chi2_pixel', data=chi2_pixel)
    table.add_column(col)

    print 'Renaming identifier->coadd_objects_ids'
    table.rename_column("identifier", "coadd_objects_id")
    epochs.rename_column('id', 'coadd_objects_id')

    #print 'NOT NOT NOT NOT NOT NOT NOT Adding extra columns flags'
    print "adding new columns"
    extra_columns.add_standard_cols(table)

    print 'Flagging'
    #error cuts
    cuts = cut_data.error_cuts + getattr(cut_data, "error_cuts_%s"%band)
    flags, fractions = cut_data.compute_flags(table, cuts, verb=not quiet)
    col = astropy.table.Column(name='error_flag', data=flags)
    table.add_column(col)
    if report:
        print "INFO CUTS"
        cut_data.report(cuts)


    #info cuts
    cuts = cut_data.info_cuts1 + getattr(cut_data, "info_cuts_%s"%band) + cut_data.info_cuts2
    flags, fractions = cut_data.compute_flags(table, cuts, verb=not quiet)
    col = astropy.table.Column(name='info_flag', data=flags)
    table.add_column(col)

    if report:
        print "ERROR CUTS"
        cut_data.report(cuts)
        return table, epochs

    #blinding
    if blind:
        print 'Blinding'
        e1,e2 = blind_catalog.blind_arrays(table['e1'],table['e2'])
        table['e1'][:] = e1
        table['e2'][:] = e2

    print "Reticulating splines"
    return table, epochs
def build_table_from_output_dict(output_dict):
    """ Traverses the output dict to build a plottable table. """

    table = astropy.table.Table()

    column_names = ("trial_number", "noise_added", "n_clouds", "total_mass",
                    'inner_larson_A', 'inner_larson_beta', 'outer_larson_A',
                    'outer_larson_beta', 'inner_M0', 'inner_N0', 'inner_gamma',
                    'outer_M0', 'outer_N0', 'outer_gamma')

    for name in column_names:

        col = astropy.table.Column(data=[], name=name)

        table.add_column(col)

    for key, value in output_dict.items():

        # we are gonna try and add things row by row

        preamble = value[0:4]
        larson, mspec = value[-2:]

        larson_names = [
            'inner_larson_A', 'inner_larson_beta', 'outer_larson_A',
            'outer_larson_beta'
        ]
        larson_tuple = tuple(larson[name] for name in larson_names)

        mspec_names = [
            'inner_M0', 'inner_N0', 'inner_gamma', 'outer_M0', 'outer_N0',
            'outer_gamma'
        ]
        mspec_tuple = tuple(mspec[name] for name in mspec_names)

        table.add_row((preamble + larson_tuple + mspec_tuple))

    return table
def add_tex_tau_to_table(table):
    import pyradex
    R = pyradex.Radex(species='o-h2co_troscompt', h2column=1e21, abundance=10**-8.5)

    newcols = {'tau1':[],
               'tau2':[],
               'tex1':[],
               'tex2':[]}
    for t in table:
        R.temperature = t['TEMPERATURE']
        R.column = 10**t['COLUMN']
        orthofrac = 10**t['ORTHOPARA']/(1+10**t['ORTHOPARA'])
        R.density = {'oH2': 10**t['DENSITY']*orthofrac,
                     'pH2': 10**t['DENSITY']*(1-orthofrac)}
        R.run_radex()
        newcols['tex1'].append(R.tex[0].value)
        newcols['tex2'].append(R.tex[2].value)
        newcols['tau1'].append(R.tau[0])
        newcols['tau2'].append(R.tau[2])

    for k in newcols:
        table.add_column(astropy.table.Column(name=k, data=newcols[k]))

    return table
예제 #5
0
def table_latex_strings_test(write=False, begin=0, end=30):
    """ 
    This is a 'test' for generating pretty LaTeX-style tables.

    In particular, I want to see if I can make a) sexagesimal coordinate output
    and b) value \pm errorbar columns.

    See 
    https://github.com/YSOVAR/YSOVAR/blob/master/docs/workflow.rst 
    and
    http://docs.astropy.org/en/v0.2.1/_generated/astropy.io.ascii.latex.Latex.html
    for reference.
    
    """

    table = astropy.table.Table()
    table.table_name = "Table 1"

    # Be careful about this. Make sure you don't get the order of the args confused.
    addc = lambda name, data: table.add_column( 
        astropy.table.Column(name=name, data=data) )

    sexagesimal_RA, sexagesimal_Dec = (
        convert_decimal_degree_columns_to_sexagesimal(
            np.degrees(ukvar_spread.RA), np.degrees(ukvar_spread.DEC)) )

    j_value_pm_error = join_columns_with_plusminus(ukvar_spread.j_median,
                                                   ukvar_spread.j_err_median,
                                                   precision=2)
    
    addc('ONCvar ID', ukvar_spread.UKvar_ID)
    addc('R.A.', sexagesimal_RA)
    addc('Decl.', sexagesimal_Dec)
    addc('Median J mag', j_value_pm_error)

    if write:
        filename = output_directory+"Table_test.tex" 
        write_and_correct_latex_table(table, filename, 
                                      "Basic Properties of Stars")
    return table
예제 #6
0
파일: fiberloss.py 프로젝트: sdss/specsim
def calculate_fiber_acceptance_fraction(focal_x,
                                        focal_y,
                                        wavelength,
                                        source,
                                        atmosphere,
                                        instrument,
                                        source_types=None,
                                        source_fraction=None,
                                        source_half_light_radius=None,
                                        source_minor_major_axis_ratio=None,
                                        source_position_angle=None,
                                        oversampling=32,
                                        saved_images_file=None,
                                        saved_table_file=None):
    """Calculate the acceptance fraction for a single fiber.

    The behavior of this function is customized by the instrument.fiberloss
    configuration parameters. When instrument.fiberloss.method == 'table',
    pre-tabulated values are returned using source.type as the key and
    all other parameters to this function are ignored.

    When instrument.fiberloss.method == 'galsim', fiberloss is calculated
    on the fly using the GalSim package via :class:`GalsimFiberlossCalculator`
    to model the PSF components and source profile and perform the convolutions.

    To efficiently calculate fiberloss fractions for multiple sources with
    GalSim, use :class:`GalsimFiberlossCalculator` directly instead of
    repeatedly calling this method.  See :mod:`specsim.quickfiberloss` for an
    example of this approach.

    Parameters
    ----------
    focal_x : :class:`astropy.units.Quantity`
        X coordinate of the fiber center in the focal plane with length units.
    focal_y : :class:`astropy.units.Quantity`
        Y coordinate of the fiber center in the focal plane with length units.
    wavelength : :class:`astropy.units.Quantity`
        Array of simulation wavelengths (with length units) where the fiber
        acceptance fraction should be tabulated.
    source : :class:`specsim.source.Source`
        Source model to use for the calculation.
    atmosphere : :class:`specsim.atmosphere.Atmosphere`
        Atmosphere model to use for the calculation.
    instrument : :class:`specsim.instrument.Instrument`
        Instrument model to use for the calculation.
    source_types : array or None
        Array of source type names that identify which tabulated fiberloss
        fraction should be used for each fiber with the ``table`` method.
        Each name should already be defined as a key in the
        ``instruments.fiberloss.table.paths`` configuration.
        Ignored for the ``galsim`` method.
    source_fraction : array or None
        Array of shape (num_fibers, 2).  See
        :meth:`GalsimFiberlossCalculator.create_source` for details.
        Ignored for the ``table`` method.
    source_half_light_radius : array or None
        Array of shape (num_fibers, 2).  See
        :meth:`GalsimFiberlossCalculator.create_source` for details.
        Ignored for the ``table`` method.
    source_minor_major_axis_ratio : array or None
        Array of shape (num_fibers, 2).  See
        :meth:`GalsimFiberlossCalculator.create_source` for details.
        Ignored for the ``table`` method.
    source_position_angle : array or None
        Array of shape (num_fibers, 2).  See
        :meth:`GalsimFiberlossCalculator.create_source` for details.
        Ignored for the ``table`` method.
    oversampling : int
        Oversampling factor to use for anti-aliasing the fiber aperture.
        Ignored for the ``table`` method.
    saved_images_file : str or None
        See :meth:`GalsimFiberlossCalculator.calculate`.
        Ignored for the ``table`` method.
    saved_table_file : str or None
        Write a table of calculated values to a file with this name.  The
        extension determines the file format, and .ecsv is recommended.
        The saved file can then be used as a pre-tabulated input with
        instrument.fiberloss.method = 'table'.

    Returns
    -------
    numpy array
        Array of fiber acceptance fractions (dimensionless) at each of the
        input wavelengths.
    """
    num_fibers = len(focal_x)
    if len(focal_y) != num_fibers:
        raise ValueError('Arrays focal_x and focal_y must have same length.')

    # Use pre-tabulated fiberloss fractions when requested.
    if instrument.fiberloss_method == 'table':
        if source_types is None:
            # Use same source type for all fibers.
            return instrument.fiber_acceptance_dict[source.type_name][
                np.newaxis, :]
        elif len(source_types) != num_fibers:
            raise ValueError('Unexpected shape for source_types.')
        floss = np.empty((num_fibers, len(wavelength)))
        for i, type_name in enumerate(source_types):
            floss[i] = instrument.fiber_acceptance_dict[type_name]
        return floss

    # Otherwise, use GalSim or the fastfiberacceptance calibrated on galsim
    # to calculate fiberloss fractions on the fly...

    # Initialize the grid of wavelengths where the fiberloss will be
    # calculated.
    num_wlen = instrument.fiberloss_num_wlen
    wlen_unit = wavelength.unit
    wlen_grid = np.linspace(wavelength.value[0], wavelength.value[-1],
                            num_wlen) * wlen_unit

    # Calculate the focal-plane optics at the fiber locations.
    scale, blur, offset = instrument.get_focal_plane_optics(
        focal_x, focal_y, wlen_grid)

    # Calculate the atmospheric seeing at each wavelength.
    seeing_fwhm = atmosphere.get_seeing_fwhm(wlen_grid).to(u.arcsec).value

    # Replicate source parameters from the source config if they are not
    # provided via args. If they are provided, check for the expected shape.
    if source_fraction is None:
        source_fraction = np.tile(
            [source.disk_fraction, source.bulge_fraction], [num_fibers, 1])
    elif source_fraction.shape != (num_fibers, 2):
        raise ValueError('Unexpected shape for source_fraction.')
    if source_half_light_radius is None:
        source_half_light_radius = np.tile([
            source.disk_shape.half_light_radius.to(u.arcsec).value,
            source.bulge_shape.half_light_radius.to(u.arcsec).value
        ], [num_fibers, 1])
    elif source_half_light_radius.shape != (num_fibers, 2):
        raise ValueError('Unexpected shape for source_half_light_radius.')
    if source_minor_major_axis_ratio is None:
        source_minor_major_axis_ratio = np.tile([
            source.disk_shape.minor_major_axis_ratio,
            source.bulge_shape.minor_major_axis_ratio
        ], [num_fibers, 1])
    elif source_minor_major_axis_ratio.shape != (num_fibers, 2):
        raise ValueError('Unexpected shape for source_minor_major_axis_ratio.')
    if source_position_angle is None:
        source_position_angle = np.tile([
            source.disk_shape.position_angle.to(u.deg).value,
            source.bulge_shape.position_angle.to(u.deg).value
        ], [num_fibers, 1])
    elif source_position_angle.shape != (num_fibers, 2):
        raise ValueError('Unexpected shape for source_position_angle.')

    fiberloss_grid = None

    # choose here how to compute things
    if instrument.fiberloss_method == 'fastsim':
        scale_um_per_arcsec = scale.to(u.um / u.arcsec).value
        blur_um = blur.to(u.um).value

        sigma = np.zeros((offset.shape[0], offset.shape[1]))
        disk_half_light_radius = np.zeros(sigma.shape)
        bulge_half_light_radius = np.zeros(sigma.shape)
        disk_frac = np.zeros(sigma.shape)
        bulge_frac = np.zeros(sigma.shape)

        for i in range(offset.shape[0]):
            sigma[i] = np.sqrt((seeing_fwhm / 2.35482)**2 *
                               scale_um_per_arcsec[i, 0] *
                               scale_um_per_arcsec[i, 1] + blur_um[i]**2)
            disk_half_light_radius[i] = source_half_light_radius[
                i, 0] * np.ones(offset.shape[1])
            bulge_half_light_radius[i] = source_half_light_radius[
                i, 1] * np.ones(offset.shape[1])
            disk_frac[i] = source_fraction[i, 0] * np.ones(offset.shape[1])
            bulge_frac[i] = source_fraction[i, 1] * np.ones(offset.shape[1])

        point_frac = 1 - disk_frac - bulge_frac

        offset_um = offset.to(u.um).value
        delta = np.sqrt(offset_um[:, :, 0]**2 + offset_um[:, :, 1]**2)

        fiberloss_grid = np.zeros(sigma.shape)
        if np.sum(point_frac) > 0:
            fiberloss_grid += point_frac * instrument.fast_fiber_acceptance.value(
                "POINT", sigma, delta)
        if np.sum(disk_frac) > 0:
            fiberloss_grid += disk_frac * instrument.fast_fiber_acceptance.value(
                "DISK", sigma, delta, disk_half_light_radius)
        if np.sum(bulge_frac) > 0:
            fiberloss_grid += bulge_frac * instrument.fast_fiber_acceptance.value(
                "BULGE", sigma, delta, bulge_half_light_radius)

    else:

        # Initialize a new calculator.
        calc = GalsimFiberlossCalculator(
            instrument.fiber_diameter.to(u.um).value,
            wlen_grid.to(u.Angstrom).value, instrument.fiberloss_num_pixels,
            oversampling, atmosphere.seeing_moffat_beta)

        # Calculate fiberloss fractions.  Note that the calculator expects arrays
        # with implicit units.
        fiberloss_grid = calc.calculate(seeing_fwhm,
                                        scale.to(u.um / u.arcsec).value,
                                        offset.to(u.um).value,
                                        blur.to(u.um).value, source_fraction,
                                        source_half_light_radius,
                                        source_minor_major_axis_ratio,
                                        source_position_angle,
                                        saved_images_file)

    # TODO: add support for saving table when num_fibers > 1.
    if saved_table_file and num_fibers == 1:
        meta = dict(
            description='Fiberloss fraction for source "{0}"'.format(
                source.name) +
            ' at focal (x,y) = ({0:.3f},{1:.3f})'.format(focal_x, focal_y))
        table = astropy.table.Table(meta=meta)
        table.add_column(
            astropy.table.Column(name='Wavelength',
                                 data=wlen_grid.value,
                                 unit=wlen_grid.unit,
                                 description='Observed wavelength'))
        table.add_column(
            astropy.table.Column(name='FiberAcceptance',
                                 data=fiberloss_grid[0],
                                 description='Fiber acceptance fraction'))
        args = {}
        if saved_table_file.endswith('.ecsv'):
            args['format'] = 'ascii.ecsv'
        table.write(saved_table_file, **args)

    # Interpolate (linearly) to the simulation wavelength grid.
    # Use scipy.interpolate instead of np.interp here to avoid looping
    # over fibers.
    interpolator = scipy.interpolate.interp1d(wlen_grid.value,
                                              fiberloss_grid,
                                              kind='linear',
                                              axis=1,
                                              copy=False,
                                              assume_sorted=True)
    # Both wavelength grids have the same units, by construction, so no
    # conversion factor is required here.
    return interpolator(wavelength.value)
예제 #7
0
파일: simulator.py 프로젝트: sdss/specsim
    def __init__(self,
                 config,
                 num_fibers=2,
                 camera_output=True,
                 verbose=False,
                 params=None):

        if specsim.config.is_string(config):
            config = specsim.config.load_config(config)
        config.verbose = verbose
        self.verbose = verbose

        # Initalize our component models.
        self.atmosphere = specsim.atmosphere.initialize(config)
        self.instrument = specsim.instrument.initialize(config, camera_output)
        self.source = specsim.source.initialize(config)
        self.observation = specsim.observation.initialize(config)
        self.telescope = specsim.telescope.initialize(config, params=params)

        self._num_fibers = int(num_fibers)
        if self._num_fibers < 1:
            raise ValueError('Must have num_fibers >= 1.')

        # Initialize our table of simulation results.
        self.camera_names = []
        self.camera_slices = {}
        num_rows = len(config.wavelength)
        shape = (self.num_fibers, )
        column_args = dict(dtype=float, length=num_rows, shape=shape)
        flux_unit = u.erg / (u.cm**2 * u.s * u.Angstrom)
        self._simulated = astropy.table.Table(meta=dict(
            description='Specsim simulation results'))
        self._simulated.add_column(
            astropy.table.Column(name='wavelength', data=config.wavelength))
        self._simulated.add_column(
            astropy.table.Column(name='source_flux',
                                 unit=flux_unit,
                                 **column_args))
        self._simulated.add_column(
            astropy.table.Column(name='fiberloss', **column_args))
        self._simulated.add_column(
            astropy.table.Column(name='source_fiber_flux',
                                 unit=flux_unit,
                                 **column_args))
        self._simulated.add_column(
            astropy.table.Column(name='sky_fiber_flux',
                                 unit=flux_unit,
                                 **column_args))
        self._simulated.add_column(
            astropy.table.Column(name='num_source_photons', **column_args))
        self._simulated.add_column(
            astropy.table.Column(name='num_sky_photons', **column_args))
        for camera in self.instrument.cameras:
            name = camera.name
            self.camera_names.append(name)
            self.camera_slices[name] = camera.ccd_slice
            self._simulated.add_column(
                astropy.table.Column(
                    name='num_source_electrons_{0}'.format(name),
                    **column_args))
            self._simulated.add_column(
                astropy.table.Column(name='num_sky_electrons_{0}'.format(name),
                                     **column_args))
            self._simulated.add_column(
                astropy.table.Column(
                    name='num_dark_electrons_{0}'.format(name), **column_args))
            self._simulated.add_column(
                astropy.table.Column(
                    name='read_noise_electrons_{0}'.format(name),
                    **column_args))

        # Count the number of bytes used in the simulated table.
        self.table_bytes = 0
        for name in self._simulated.colnames:
            d = self._simulated[name].data
            self.table_bytes += np.prod(d.shape) * d.dtype.itemsize

        # Initialize each camera's table of results downsampled to
        # output pixels, if requested.
        self._camera_output = []
        if camera_output:
            for camera in self.instrument.cameras:
                meta = dict(name=camera.name,
                            num_fibers=self.num_fibers,
                            pixel_size=camera.output_pixel_size)
                table = astropy.table.Table(meta=meta)
                column_args['length'] = len(camera.output_wavelength)
                table.add_column(
                    astropy.table.Column(name='wavelength',
                                         data=camera.output_wavelength))
                table.add_column(
                    astropy.table.Column(name='num_source_electrons',
                                         **column_args))
                table.add_column(
                    astropy.table.Column(name='num_sky_electrons',
                                         **column_args))
                table.add_column(
                    astropy.table.Column(name='num_dark_electrons',
                                         **column_args))
                table.add_column(
                    astropy.table.Column(name='read_noise_electrons',
                                         **column_args))
                table.add_column(
                    astropy.table.Column(name='random_noise_electrons',
                                         **column_args))
                table.add_column(
                    astropy.table.Column(name='variance_electrons',
                                         **column_args))
                table.add_column(
                    astropy.table.Column(name='flux_calibration',
                                         **column_args))
                table.add_column(
                    astropy.table.Column(name='observed_flux',
                                         unit=flux_unit,
                                         **column_args))
                table.add_column(
                    astropy.table.Column(name='flux_inverse_variance',
                                         unit=flux_unit**-2,
                                         **column_args))
                # Add bytes used in this table to our running total.
                for name in table.colnames:
                    d = table[name].data
                    self.table_bytes += np.prod(d.shape) * d.dtype.itemsize

                self._camera_output.append(table)

        if self.verbose:
            print('Allocated {0:.1f}Mb of table data.'.format(
                self.table_bytes / (2.**20)))
예제 #8
0
    def __init__(self, config):

        if isinstance(config, basestring):
            config = specsim.config.load_config(config)

        # Initalize our component models.
        self.atmosphere = specsim.atmosphere.initialize(config)
        self.instrument = specsim.instrument.initialize(config)
        self.source = specsim.source.initialize(config)
        self.observation = specsim.observation.initialize(config)

        # Initialize our table of simulation results.
        self.camera_names = []
        self.camera_slices = {}
        num_rows = len(config.wavelength)
        flux_unit = u.erg / (u.cm**2 * u.s * u.Angstrom)
        self._simulated = astropy.table.Table(
            meta=dict(description='Specsim simulation results'))
        self._simulated.add_column(astropy.table.Column(
            name='wavelength', data=config.wavelength))
        self._simulated.add_column(astropy.table.Column(
            name='source_flux', dtype=float, length=num_rows, unit=flux_unit))
        self._simulated.add_column(astropy.table.Column(
            name='source_fiber_flux', dtype=float, length=num_rows,
            unit=flux_unit))
        self._simulated.add_column(astropy.table.Column(
            name='sky_fiber_flux', dtype=float, length=num_rows,
            unit=flux_unit))
        self._simulated.add_column(astropy.table.Column(
            name='num_source_photons', dtype=float, length=num_rows))
        self._simulated.add_column(astropy.table.Column(
            name='num_sky_photons', dtype=float, length=num_rows))
        for camera in self.instrument.cameras:
            name = camera.name
            self.camera_names.append(name)
            self.camera_slices[name] = camera.ccd_slice
            self._simulated.add_column(astropy.table.Column(
                name='num_source_electrons_{0}'.format(name),
                dtype=float, length=num_rows))
            self._simulated.add_column(astropy.table.Column(
                name='num_sky_electrons_{0}'.format(name),
                dtype=float, length=num_rows))
            self._simulated.add_column(astropy.table.Column(
                name='num_dark_electrons_{0}'.format(name),
                dtype=float, length=num_rows))
            self._simulated.add_column(astropy.table.Column(
                name='read_noise_electrons_{0}'.format(name),
                dtype=float, length=num_rows))

        # Initialize each camera's table of results downsampled to
        # output pixels.
        self._camera_output = []
        for camera in self.instrument.cameras:
            meta = dict(
                name=camera.name,
                pixel_size=camera.output_pixel_size)
            table = astropy.table.Table(meta=meta)
            num_rows = len(camera.output_wavelength)
            table.add_column(astropy.table.Column(
                name='wavelength', data=camera.output_wavelength))
            table.add_column(astropy.table.Column(
                name='num_source_electrons', dtype=float, length=num_rows))
            table.add_column(astropy.table.Column(
                name='num_sky_electrons', dtype=float, length=num_rows))
            table.add_column(astropy.table.Column(
                name='num_dark_electrons', dtype=float, length=num_rows))
            table.add_column(astropy.table.Column(
                name='read_noise_electrons', dtype=float, length=num_rows))
            table.add_column(astropy.table.Column(
                name='random_noise_electrons', dtype=float, length=num_rows))
            table.add_column(astropy.table.Column(
                name='variance_electrons', dtype=float, length=num_rows))
            table.add_column(astropy.table.Column(
                name='flux_calibration', dtype=float, length=num_rows,
                unit=flux_unit))
            table.add_column(astropy.table.Column(
                name='observed_flux', dtype=float, length=num_rows,
                unit=flux_unit))
            table.add_column(astropy.table.Column(
                name='flux_inverse_variance', dtype=float, length=num_rows,
                unit=flux_unit ** -2))
            self._camera_output.append(table)
예제 #9
0
def extract(inputs, pixel_scale, filename, noisefile, outputfile, finalfits,
            num_sections, height, width, x, y):
    logger.info(f"Will source extract galaxies from noise file {noisefile}")

    # run sextractor on noise image.
    cmd = '/nfs/slac/g/ki/ki19/deuce/AEGIS/ismael/WLD/params/sextractor-2.25.0/src/sex {} -c {} -CATALOG_NAME {} ' \
          '-PARAMETERS_NAME {} -FILTER_NAME {} -STARNNW_NAME {}'.format(
            noisefile, inputs['config_file'], outputfile, inputs['param_file'], inputs['filter_file'],
            inputs['starnnw_file'])

    logger.info(f"With cmd: {cmd}")

    subprocess.run(cmd, shell=True)

    logger.success(f"Successfully source extracted {noisefile}!")

    # read noise image to figure out image bounds.
    fits_section = fitsio.FITS(noisefile)
    stamp = fits_section[0].read()
    img_width = stamp.shape[0]  # pixels
    img_height = stamp.shape[1]

    assert img_width == width / num_sections and img_height == height / num_sections, \
        "Something is wrong with the heights specified."

    logger.info(
        f"The image width and height from the stamp are {img_width} and {img_height} respectively."
    )

    # read results obtained (table obtained either from combining or from single.)
    cat = descwl.output.Reader(filename).results
    table = cat.table
    detected, matched, indices, distance = cat.match_sextractor(outputfile)
    logger.success(
        f"Successfully matched catalogue with source extractor from sextract output: {outputfile}"
    )

    # convert to arcsecs and relative to this image's center (not to absolute, before w/ respect to corner.)
    detected['X_IMAGE'] = (detected['X_IMAGE'] - 0.5 * img_width -
                           0.5) * pixel_scale
    detected['Y_IMAGE'] = (detected['Y_IMAGE'] - 0.5 * img_height -
                           0.5) * pixel_scale

    # adjust to absolute image center if necessary, both for measured centers and catalogue centers.
    detected['X_IMAGE'] += x * (width * pixel_scale)  # need to use arcsecs
    detected['Y_IMAGE'] += y * (height * pixel_scale)

    table['dx'] += x * (width * pixel_scale)
    table['dy'] += y * (height * pixel_scale)

    # also adjust the xmin,xmax, ymin, ymax bounding box edges, because why not?
    # remember these are in pixels; xmin, xmax relative to left edge; ymin,ymax relative to right edge.
    table['xmin'] += int(x * width + width / 2 - img_width / 2)
    table['xmax'] += int(x * width + width / 2 - img_width / 2)
    table['ymin'] += int(x * height + height / 2 - img_height / 2)
    table['ymax'] += int(x * height + height / 2 - img_height / 2)

    # convert second moments to arcsecs.
    # Not adjust relative to center, because only used for sigma calculation.
    detected['X2_IMAGE'] *= pixel_scale**2
    detected['Y2_IMAGE'] *= pixel_scale**2
    detected['XY_IMAGE'] *= pixel_scale**2

    # calculate size from moments X2_IMAGE,Y2_IMAGE,XY_IMAGE -> remember in pixel**2 so have to convert to arcsecs.
    sigmas = []
    for x2, y2, xy in zip(detected['X2_IMAGE'], detected['Y2_IMAGE'],
                          detected['XY_IMAGE']):
        second_moments = np.array([[x2, xy], [xy, y2]])
        sigma = np.linalg.det(second_moments)**(+1. / 4)  # should be a PLUS.
        sigmas.append(sigma)

    SIGMA = astropy.table.Column(name='SIGMA', data=sigmas)
    detected.add_column(SIGMA)

    # find the indices of the ambiguous blends.
    logger.info("Finding indices/ids that are ambiguously blended")
    ambg_blends = detected_ambiguous_blends(table, indices, detected)

    logger.success("All indices have been found")

    logger.info(
        f"Adding column to original table and writing it to {finalfits}")

    ambiguous_blend_column = []
    for i, gal_row in enumerate(table):
        if i in ambg_blends:
            ambiguous_blend_column.append(True)
        else:
            ambiguous_blend_column.append(False)
    column = astropy.table.Column(name='ambig_blend',
                                  data=ambiguous_blend_column)
    table.add_column(column)

    logger.debug(
        f"Number of galaxies in table from file {finalfits} is: {len(table)}")

    table.write(finalfits)