Example #1
0
# -----------------------------------------------------------------

earth_projection_path = fs.join(modeling_path, "components", "projections",
                                "earth.proj")
earth_projection = GalaxyProjection.from_file(earth_projection_path)
#full_instrument = FullInstrument.from_projection(earth_projection)
simple_instrument = SimpleInstrument.from_projection(earth_projection)

faceon_projection_path = fs.join(modeling_path, "components", "projections",
                                 "faceon.proj")
faceon_projection = GalaxyProjection.from_file(faceon_projection_path)

faceon_instrument = FrameInstrument.from_projection(faceon_projection)

ski.remove_all_instruments()
ski.add_instrument("earth", simple_instrument)
ski.add_instrument("faceon", faceon_instrument)

# -----------------------------------------------------------------

# Save the ski template in the test directory
ski_path = fs.join(test_path, "mappings.ski")
ski.saveto(ski_path)

# Output path
out_path = fs.create_directory_in(test_path, "out")

# Input path
in_path = fs.create_directory_in(test_path, "in")

# Copy file i
Example #2
0
File: test.py Project: rag9704/PTS
class NGC4013Test(TestImplementation):
    """
    This class ...
    """
    def __init__(self, *args, **kwargs):
        """
        The constructor ...
        :param kwargs:
        """

        # Call the constructor of the base class
        super(NGC4013Test, self).__init__(*args, **kwargs)

        # The path with the test data
        self.data_path = None

        # The path for the fitskirt run
        self.reference_path = None
        self.reference_output_path = None
        self.reference_ski_path = None
        self.reference_fski_path = None

        # The ski file
        self.ski = None

        # The fski file
        self.fski = None

        # The images
        self.images = dict()

        # The original image paths
        self.image_paths = dict()

        # The instrument
        self.instrument = None

        # The reference wcs
        self.wcs = None

        # The wavelengths
        self.wavelengths = None

        # The dust grid
        self.dust_grid = None

        # The FitSKIRT launcher
        self.launcher = None

        # The best parameter values
        self.best_parameter_values = None

        # The best luminosities
        self.best_luminosities = None

        # The modeler
        self.modeler = None

    # -----------------------------------------------------------------

    def run(self, **kwargs):
        """
        This function ...
        :param kwargs:
        :return:
        """

        # 1. Call the setup function
        self.setup(**kwargs)

        # 2. Load the ski file
        self.load_ski()

        # 3. Load the fski file
        self.load_fski()

        # 4. Load the images
        self.load_images()

        # 5. Create instrument
        self.create_instrument()

        # 6. Create the wavelength grid
        self.create_wavelength_grid()

        # 7. Create the dust grid
        self.create_dust_grid()

        # 8. Create the ski file
        self.adjust_ski()

        # 9. Create the fski file
        self.adjust_fski()

        # 10. Write
        self.write()

        # 11. Launch with FitSKIRT
        self.launch_fitskirt()

        # Get the best values from FitSKIRT
        self.get_best_parameter_values()

        # Get best luminosities
        self.get_best_luminositites()

        # Show
        self.show()

        # 12. Setup the modeling
        self.setup_modelling()

        # 13. Model
        self.model()

    # -----------------------------------------------------------------

    def setup(self, **kwargs):
        """
        This function ...
        :param kwargs:
        :return:
        """

        # CAll the setup function of the base class
        super(NGC4013Test, self).setup(**kwargs)

        # Check the data
        if fs.is_directory(norm_path): self.data_path = norm_path
        else:

            # Create the data directory and get the data
            self.data_path = fs.create_directory_in(self.path, "data")
            self.get_data()

        # Create the reference directory and subdirectories
        self.reference_path = fs.create_directory_in(self.path, "ref")
        self.reference_output_path = fs.create_directory_in(
            self.reference_path, "out")
        self.reference_ski_path = fs.join(self.reference_path, "NGC4013.ski")
        self.reference_fski_path = fs.join(self.reference_path, "NGC4013.fski")

    # -----------------------------------------------------------------

    def get_data(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Downloading the input ...")

        # Download the input
        network.download_and_decompress_directory(all_url,
                                                  self.data_path,
                                                  progress_bar=True,
                                                  into_root=True)

    # -----------------------------------------------------------------

    def load_ski(self):
        """
        THis function ...
        :return:
        """

        # Inform the user
        log.info("Loading the ski file ...")

        # Load ski
        self.ski = LabeledSkiFile(ski_path)

    # -----------------------------------------------------------------

    def load_fski(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Loading the fski file ...")

        # Load the fski file
        self.fski = FskiFile(fski_path)

    # -----------------------------------------------------------------

    def load_images(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Loading the images ...")

        # The common wcs of the images
        wcs = None

        # Loop over the images in the data directory
        for path, filename in fs.files_in_path(self.data_path,
                                               extension="fits",
                                               returns=["path", "name"]):

            # Load the frame
            frame = Frame.from_file(path)

            # Set filter
            previous_filter = frame.filter
            frame.filter = parse_filter(filename.split("_norm")[0])
            if previous_filter != frame.filter: frame.save()

            # Check filter
            if str(frame.filter) not in [
                    str(fltr) for fltr in self.config.fitting_filters
            ]:
                continue

            # Determine name
            name = str(frame.filter)

            # Check wcs
            if wcs is None: wcs = frame.wcs
            elif wcs == frame.wcs: pass
            else:
                raise IOError("The coordinate system of image '" + filename +
                              "' does not match that of other images")

            # Debugging
            log.debug("Adding frame '" + filename + "' ...")

            # Add to dictionary
            self.images[name] = frame

            # Set original path
            self.image_paths[name] = path

        # Set the wcs
        self.wcs = wcs

    # -----------------------------------------------------------------

    def create_instrument(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Creating the instrument ...")

        # Set general properties
        distance = parse_quantity("18.6 Mpc")
        inclination = initial_guesses["inclination"]
        azimuth = parse_angle("0 deg")
        position_angle = parse_angle("0 deg")

        # Create multiframe instrument
        self.instrument = MultiFrameInstrument(distance=distance,
                                               inclination=inclination,
                                               azimuth=azimuth,
                                               position_angle=position_angle,
                                               write_stellar_components=True)

        # Loop over the filters, create frames
        for fltr in self.config.fitting_filters:

            # Determine xsize and ysize
            xsize = self.wcs.xsize
            ysize = self.wcs.ysize

            # Determine pixelscale
            pixelscale_physical_x = (self.wcs.pixelscale.x * distance).to(
                "pc", equivalencies=dimensionless_angles())
            pixelscale_physical_y = (self.wcs.pixelscale.y * distance).to(
                "pc", equivalencies=dimensionless_angles())

            # Determine field of view
            field_x = pixelscale_physical_x * xsize
            field_y = pixelscale_physical_y * ysize

            # Create frame
            frame = InstrumentFrame(pixels_x=xsize,
                                    pixels_y=ysize,
                                    field_x=field_x,
                                    field_y=field_y)

            # Add the frame
            self.instrument.add_frame(frame)

    # -----------------------------------------------------------------

    def create_wavelength_grid(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Creating the wavelength grid ...")

        # Set the wavelengths
        self.wavelengths = [fltr.pivot for fltr in self.config.fitting_filters]

    # -----------------------------------------------------------------

    def create_dust_grid(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Creating the dust grid ...")

        # Set boundaries
        max_r = parse_quantity("25000 pc")
        min_z = parse_quantity("-4000 pc")
        max_z = parse_quantity("4000 pc")

        # Create the grid
        self.dust_grid = CylindricalGrid(max_r=max_r,
                                         min_z=min_z,
                                         max_z=max_z,
                                         type_r="logarithmic",
                                         type_z="symmetric_power",
                                         nbins_r=250,
                                         nbins_z=250,
                                         central_bin_fraction_r=0.0004,
                                         ratio_z=50,
                                         write=False)

    # -----------------------------------------------------------------

    def adjust_ski(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Adjusting the ski file ...")

        # Set the number of photon packages
        self.ski.setpackages(self.config.npackages)

        # Set wavelength grid
        self.ski.set_wavelengths(*self.wavelengths)

        # Set dust grid
        self.ski.set_dust_grid(self.dust_grid)

        # Set instrument
        self.ski.remove_all_instruments()
        self.ski.add_instrument(instrument_name, self.instrument)

        # Add label
        element = self.ski.get_instrument(instrument_name)
        path = "inclination"
        if "inclination" in self.config.free_parameters:
            self.ski.add_label_to_path(path, "inclination", element=element)

    # -----------------------------------------------------------------

    def adjust_fski(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Creating the fski file ...")

        # Set ski name
        self.fski.set_ski_name(fs.name(self.reference_ski_path))

        # Set the parameter ranges
        self.set_parameter_ranges()

        # Set the reference images
        self.set_reference_images()

        # Set the genetic options
        self.set_genetic_options()

    # -----------------------------------------------------------------

    def set_parameter_ranges(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Setting the parameter ranges ...")

        # Loop over the free parameters
        for label in self.config.free_parameters:

            # Get the parameter range
            parameter_range = parameter_ranges[label]

            # Set the range
            self.fski.set_parameter_range(label, parameter_range)

    # -----------------------------------------------------------------

    def set_reference_images(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Setting the reference images ...")

        # Remove reference images
        self.fski.remove_all_reference_images()

        # Set reference images
        for name in self.image_paths:

            # Get filename
            path = self.image_paths[name]
            filename = fs.name(path)

            # Set FWHM
            if "u" in filename: kernel_fwhm = 1.7
            elif "g" in filename: kernel_fwhm = 1.6
            else: raise NotImplementedError("Not implemented")

            # Ranges (for both stellar components)
            luminosity_range = RealRange(min_luminosity, max_luminosity)
            luminosity_ranges = [luminosity_range, luminosity_range]

            # Add reference image
            self.fski.add_reference_image(filename, luminosity_ranges,
                                          kernel_fwhm, self.config.kernel_type,
                                          self.config.kernel_dimension)

    # -----------------------------------------------------------------

    def set_genetic_options(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Setting the genetic algorithm options ...")

        # Set genetic algorithm properties
        self.fski.set_population_size(self.config.nmodels)
        self.fski.set_ngenerations(self.config.ngenerations)
        self.fski.set_mutation_rate(self.config.mutation_rate)
        self.fski.set_crossover_rate(self.config.crossover_rate)

    # -----------------------------------------------------------------

    def write(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing ...")

        # Write ski
        self.write_ski()

        # Write fski
        self.write_fski()

    # -----------------------------------------------------------------

    def write_ski(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the ski file ...")

        # Write
        self.ski.saveto(self.reference_ski_path)

    # -----------------------------------------------------------------

    def write_fski(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the fski file ...")

        # Write the fski file
        self.fski.saveto(self.reference_fski_path)

    # -----------------------------------------------------------------

    def launch_fitskirt(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Launching FitSKIRT ...")

        # Create configuration
        config = dict()

        # The path to the ski file and fski file
        config["ski"] = self.reference_ski_path
        config["fski"] = self.reference_fski_path

        config["input"] = self.data_path
        config["output"] = self.reference_output_path

        # Input
        input_dict = dict()

        # Construct the command
        command = Command("fitskirt",
                          "run the reference fitting with FitSKIRT",
                          config,
                          input_dict,
                          cwd=".")

        # Run the command
        self.launcher = self.run_command(command)

    # -----------------------------------------------------------------

    def get_best_parameter_values(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Getting the best parameter values according to FitSKIRT ...")

        # Get best parameter values
        self.best_parameter_values = self.launcher.fit_run.best_parameter_values

    # -----------------------------------------------------------------

    def get_best_luminositites(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Getting the best luminosities according to FitSKIRT ...")

        # Get luminosities
        self.best_luminosities = self.launcher.fit_run.best_luminosities

    # -----------------------------------------------------------------

    def show(self):
        """
        This function ...
        :return:
        """

        print("")
        print("Best parameter values:")
        print("")
        for label in self.best_parameter_values:
            print(" - " + label + ": " +
                  stringify.stringify(self.best_parameter_values[label])[1])
        print("")

        print("Best luminosities:")
        print("")
        for filter_name in self.best_luminosities:
            print("  " + filter_name + ":")
            print("")
            for index in range(len(self.best_luminosities)):
                print("   - component #" + str(index) + ": " +
                      stringify.stringify(self.best_luminosities[filter_name]
                                          [index])[1])
            print("")

    # -----------------------------------------------------------------

    def setup_modelling(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Setting up the modeling ...")

        # Settings
        settings_setup = dict()
        settings_setup["type"] = "images"
        settings_setup["name"] = "NGC4013"
        settings_setup["fitting_host_ids"] = None

        # Create object config
        object_config = dict()
        ski_path = fs.join(this_dir_path, "NGC4013.ski")
        object_config["ski"] = ski_path

        object_config["images"] = self.image_paths.values()

        # Create input dict for setup
        input_setup = dict()
        input_setup["object_config"] = object_config

        # Construct the command
        setup_command = Command("setup", "setup the modelling", settings_setup,
                                input_setup, ".")

        # Run the command
        tool = self.run_command(setup_command)

    # -----------------------------------------------------------------

    def model(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Performing the modelling ...")

        # Settings
        settings_model = dict()
        settings_model["ngenerations"] = self.config.ngenerations

        # -----------------------------------------------------------------

        # Create input dict for model
        input_model = dict()
        #input_model["parameters_config"] = Configuration(free_parameters=free_parameter_names)
        #input_model["descriptions_config"] = Configuration(descriptions=descriptions)
        #input_model["types_config"] = Configuration(types=types)
        #input_model["units_config"] = Configuration(units=units)
        #input_model["ranges_config"] = Configuration(luminosity_range=luminosity_range, dustmass_range=dustmass_range, grainsize_range=grainsize_range, fsil_range=fsil_range)
        #input_model["filters_config"] = Configuration(filters=filter_names)

        # Fitting initializer config
        #input_model["initialize_config"] = Configuration(npackages=1e4)

        # Construct the command
        model_command = Command("model",
                                "perform the modelling",
                                settings_model,
                                input_model,
                                cwd="./NGC4013")

        # Run the command
        self.modeler = self.run_command(model_command)
Example #3
0
class GalaxyTest(TestImplementation):
    """
    This class ...
    """
    def __init__(self, *args, **kwargs):
        """
        This function ...
        :param kwargs:
        """

        # Call the constructor of the base class
        super(GalaxyTest, self).__init__(*args, **kwargs)

        # Free parameters for fitting
        self.free_parameters = Map()

        # Path to the ski file for the reference simulation
        self.reference_ski_path = None
        self.simulation_output_path = None

        # The reference ski file
        self.ski = None

        # Galaxy properties
        self.properties = None

        # Galaxy properties
        self.wcs = None

        # Configurables
        self.launcher = None
        self.flux_calculator = None
        self.image_maker = None

    # -----------------------------------------------------------------

    def run(self, **kwargs):
        """
        This function ...
        :param kwargs:
        :return:
        """

        # 1. Call the setup function
        self.setup(**kwargs)

        # Set parameters
        self.set_parameters()

        # Set galaxy info
        self.set_galaxy_properties()

        # Create WCS
        self.create_wcs()

        # Create galaxy components
        self.create_components()

        # Create instrument

        # Create wavelength grid
        self.create_wavelength_grid()

        # Create dust grid
        self.create_dust_grid()

        # Create ski file
        self.create_ski()

        # Launch reference simulation
        self.launch_reference()

        # Make observed SED
        self.make_sed()

        # Make observed images
        self.make_images()

        # Setup modelling
        self.setup_modelling()

        # Model
        self.model()

    # -----------------------------------------------------------------

    def setup(self, **kwargs):
        """
        This function ...
        :param kwargs:
        :return:
        """

        # Call the
        super(GalaxyTest, self).setup(**kwargs)

        # Reference ski path
        self.reference_ski_path = fs.join(self.path, "galaxy_clumpy.ski")

        # Determine the simulation output path
        self.simulation_output_path = fs.join(self.path, "ref")

    # -----------------------------------------------------------------

    def set_parameters(self):
        """
        This function ...
        :return:
        """

        # Define the true values for the free parameters
        self.free_parameters.dust_mass = None
        self.free_parameters.fuv_ionizing = None
        self.free_parameters.fuv_young = None

    # -----------------------------------------------------------------

    def set_galaxy_properties(self):
        """
        This function ..
        :return:
        """

        # Inform the user
        log.info("Setting galaxy properties ...")

        # Galaxy poperties
        galaxy_distance = parse_quantity("3.63 Mpc")
        galaxy_inclination = Angle(59, "deg")
        galaxy_pa = Angle(67, "deg")

        # Generate a random coordinate for the center of the galaxy
        ra_random = np.random.rand() * 360.0 * u("deg")
        dec_random = (np.random.rand() * 180.0 - 90.0) * u("deg")
        galaxy_center = SkyCoordinate(ra=ra_random, dec=dec_random)

        # Determine the galaxy size, convert to
        galaxy_size = parse_quantity("100000 lyr")
        galaxy_radius = 0.5 * galaxy_size.to("pc")
        galaxy_radius_arcsec = (galaxy_radius / galaxy_distance).to(
            "arcsec", equivalencies=dimensionless_angles())

        # Determine ellipticity
        ellipticity = 0.5

        # Set the properties
        self.properties = GalaxyProperties(name=fake_name,
                                           ngc_name=fake_name,
                                           hyperleda_name=fake_name,
                                           galaxy_type=None,
                                           center=galaxy_center,
                                           major=galaxy_radius,
                                           major_arcsec=galaxy_radius_arcsec,
                                           ellipticity=ellipticity,
                                           position_angle=galaxy_pa,
                                           distance=galaxy_distance,
                                           distance_error=None,
                                           inclination=galaxy_inclination,
                                           redshift=None,
                                           common_name=fake_name)

    # -----------------------------------------------------------------

    def create_wcs(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Creating WCS ...")

        # Create WCS
        size = PixelStretch(1000, 1000)
        center_pixel = PixelCoordinate(500, 500)
        center_sky = self.properties.center
        pixelscale = Pixelscale(parse_quantity("2 arcsec"))
        self.wcs = CoordinateSystem.from_properties(size, center_pixel,
                                                    center_sky, pixelscale)

    # -----------------------------------------------------------------

    def create_components(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Creating the galaxy components ...")

        # Create a Sersic model for the bulge
        #self.bulge = SersicModel3D.from_2d(self.components["bulge"], self.properties.inclination, self.disk_pa, azimuth_or_tilt=self.config.bulge_deprojection_method)

        # Create an exponential disk model for the disk
        #self.disk = ExponentialDiskModel3D.from_2d(self.components["disk"], self.properties.inclination, self.disk_pa)

    # -----------------------------------------------------------------

    def create_dust_grid(self):
        """
        This function ...
        :return:
        """

        generator = DustGridGenerator()

        # <CartesianDustGrid writeGrid="true" minX="-2e4 pc" maxX="2e4 pc" minY="-2e4 pc" maxY="2e4 pc" minZ="-500 pc" maxZ="500 pc">
        # <meshX type="MoveableMesh">
        # <SymPowMesh numBins="50" ratio="25"/>
        #</meshX>
        #                <meshY type="MoveableMesh">
        #                    <SymPowMesh numBins="50" ratio="25"/>
        #                </meshY>
        #                <meshZ type="MoveableMesh">
        #                    <SymPowMesh numBins="20" ratio="45"/>
        #                </meshZ>
        #            </CartesianDustGrid>

    # -----------------------------------------------------------------

    def create_wavelength_grid(self):
        """
        This function ...
        :return:
        """

        generator = WavelengthGridGenerator()

        # <LogWavelengthGrid writeWavelengths="true" minWavelength="0.1 micron" maxWavelength="1000 micron" points="50"/>

    # -----------------------------------------------------------------

    def create_ski(self):
        """
        This function ...
        """

        # Inform the user
        log.info("Creating ski file ...")

        fraction = 0.5
        count = 1000
        radius = parse_quantity("10 pc")
        cutoff = False
        kernel_type = "uniform"

        # Determine the ski path
        ski_path = fs.join(this_dir_path, "galaxy.ski")

        # Create clumpy ski file
        self.ski = LabeledSkiFile(ski_path)

        # Set instrument
        self.set_instrument()

        # Set stellar components
        self.set_stellar_components()

        # Set dust components
        self.set_dust_components()

        # Save as new ski file
        self.ski.saveto(self.reference_ski_path)

    # -----------------------------------------------------------------

    def set_instrument(self):
        """
        This function ...
        :return:
        """

        # Add full instrument that writes out photon counts
        self.ski.remove_all_instruments()

        # Create a full instrument
        distance = self.properties.distance
        inclination = self.properties.inclination
        azimuth = parse_angle("0 deg")
        position_angle = self.properties.position_angle
        field_x = parse_quantity("55000 pc")
        field_y = parse_quantity("5500 pc")
        pixels_x = self.config.nxpixels
        pixels_y = self.config.nypixels
        center_x = parse_quantity("130 pc")
        center_y = parse_quantity("-181 pc")
        scattering_levels = 0
        counts = True  # write photon counts
        instrument = FullInstrument(distance=distance,
                                    inclination=inclination,
                                    azimuth=azimuth,
                                    position_angle=position_angle,
                                    field_x=field_x,
                                    field_y=field_y,
                                    pixels_x=pixels_x,
                                    pixels_y=pixels_y,
                                    center_x=center_x,
                                    center_y=center_y,
                                    scattering_levels=scattering_levels,
                                    counts=counts)

        # Add the instrument
        self.ski.add_instrument("earth", instrument)

    # -----------------------------------------------------------------

    def set_stellar_components(self):
        """
        This function ...
        :return:
        """

        # Remove all stellar components
        self.ski.remove_all_stellar_components()

        # self, component_id, radius, perturbation_weight, arms=1, pitch=0.1745329252, , phase=0, index=1
        self.ski.add_stellar_component_clumpiness(component_id, radius,
                                                  perturbation_weight, arms,
                                                  pitch, phase, index)

        # Add clumpiness to all stellar components
        for component_id in self.ski.get_stellar_component_ids():
            self.ski.add_stellar_component_clumpiness(component_id, fraction,
                                                      count, radius, cutoff,
                                                      kernel_type)

    # -----------------------------------------------------------------

    def set_dust_components(self):
        """
        This function ...
        :return:
        """

        # Remove all dust components
        self.ski.remove_all_dust_components()

        # Add clumpiness to all dust components
        for component_id in self.ski.get_dust_component_ids():
            self.ski.add_dust_component_clumpiness(component_id, fraction,
                                                   count, radius, cutoff,
                                                   kernel_type)

    # -----------------------------------------------------------------

    def launch_reference(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Launching the reference simulation ...")

        # Settings
        settings_launch = dict()
        settings_launch["ski"] = self.reference_ski_path
        settings_launch["output"] = self.simulation_output_path
        settings_launch["create_output"] = True

        # Input
        input_launch = dict()

        # Launch command
        launch = Command("launch_simulation",
                         "launch the reference simulation",
                         settings_launch,
                         input_launch,
                         cwd=".")
        self.launcher = self.run_command(launch)

    # -----------------------------------------------------------------

    def make_sed(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Creating the observed mock SED ...")

        # Settings
        settings_sed = dict()
        settings_sed["spectral_convolution"] = False

        # Input
        input_sed = dict()
        input_sed["simulation_output_path"] = self.simulation_output_path
        input_sed["output_path"] = "."

        # Construct the command
        #create_sed = Command("observed_fluxes", "create the mock SED", settings_sed, input_sed, cwd=".")

        # Add the command
        #commands.append(create_sed)

        # Launch command
        calculate = Command("observed_fluxes",
                            "create the mock SED",
                            settings_sed,
                            input_sed,
                            cwd=".")
        self.flux_calculator = self.run_command(calculate)

        # Determine the path to the mock SED
        mock_sed_path = "spiral_earth_fluxes.dat"

    # -----------------------------------------------------------------

    def make_images(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Creating the observed mock images ...")

        # Create Aniano kernels object
        aniano = AnianoKernels()

        # Set the paths to the kernel for each image
        kernel_paths = dict()
        for filter_name in fitting_filter_names:
            kernel_paths[filter_name] = aniano.get_psf_path(
                parse_filter(filter_name))

        # Settings
        settings_images = dict()
        settings_images["spectral_convolution"] = False
        # No output path is specified, so images won't be written out

        # Input
        input_images = dict()
        input_images["simulation_output_path"] = self.simulation_output_path
        input_images["output_path"] = "."
        input_images["filter_names"] = fitting_filter_names
        input_images["instrument_names"] = ["earth"]
        # input_images["wcs_path"] =
        input_images["wcs"] = self.wcs
        input_images["kernel_paths"] = kernel_paths
        input_images["unit"] = "Jy/pix"
        # input_images["host_id"] = "nancy"

        # Construct the command
        #create_images = Command("observed_images", "create the mock images", settings_images, input_images, cwd=".",
        #                        finish=make_data)

        # Add the command
        #commands.append(create_images)

        make = Command("observed_images",
                       "create the mock images",
                       settings_images,
                       input_images,
                       cwd=".")
        self.image_maker = self.run_command(make)

        # MAKE DATA:

        # Create directory for the images
        ref_path = fs.create_directory_in(self.path, "ref")
        images_path = fs.create_directory_in(ref_path, "images")

        # Determine the name of the datacube
        datacube_names = self.image_maker.images.keys()
        if len(datacube_names) > 1:
            raise RuntimeError("Unexpected number of datacubes")
        datacube_name = datacube_names[0]

        # Loop over the images
        for filter_name in self.image_maker.images[datacube_name]:

            # Get the image
            image = self.image_maker.images[datacube_name][filter_name]

            # Save the image
            image_path = fs.join(images_path, filter_name + ".fits")
            image.saveto(image_path)

    # -----------------------------------------------------------------

    def setup_modelling(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Setting up the modelling ...")

        # Settings
        settings_setup = dict()
        settings_setup["type"] = "galaxy"
        settings_setup["name"] = "Galaxy"
        settings_setup["fitting_host_ids"] = None

        # Create input dict for setup
        input_setup = dict()
        input_setup["ngc_name"] = fake_name
        input_setup["hyperleda_name"] = fake_name

        # Construct the command
        #stp = Command("setup", "setup the modeling", settings_setup, input_setup, cwd=".")

        # Add the command
        #commands.append(stp)

    # -----------------------------------------------------------------

    def model(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Performing the modelling ...")

        # Settings
        settings_model = dict()
        settings_model["ngenerations"] = 4
        settings_model["nsimulations"] = 20
        settings_model["fitting_settings"] = {"spectral_convolution": False}

        # Input
        input_model = dict()

        # Set galaxy properties
        input_model["properties"] = self.properties

        # Set SEDs
        input_model["seds"] = dict()

        # Set images dictionary
        images = dict()
        for filter_name in fitting_filter_names:
            images[filter_name] = fs.join("../ref/images",
                                          filter_name + ".fits")
        input_model["images"] = images