Beispiel #1
0
    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)
Beispiel #2
0
    def load_ski(self):
        """
        THis function ...
        :return:
        """

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

        # Load ski
        self.ski = LabeledSkiFile(ski_path)
Beispiel #3
0
    def load_reference(self):
        """
        This function ...
        :return: 
        """

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

        # Determine simulation directory
        if self.config.reference_path is not None:
            simulation_path = self.config.reference_path
        elif self.config.reference_test is not None:
            simulation_path = fs.join(introspection.pts_tests_dir,
                                      self.config.reference_test, "ref")
        else:
            raise ValueError(
                "Reference path and reference test settings are None")

        # Check whether present
        if not fs.is_directory(simulation_path):
            raise ValueError(
                "The reference simulation path could not be found")

        # Look for simulation
        prefix, ski_path, in_path, out_path = find_one_simulation_in_path(
            simulation_path)

        # Load the ski file
        self.ski = LabeledSkiFile(ski_path)

        # Other paths
        extr_path = fs.join(simulation_path, "extr")
        plot_path = fs.join(simulation_path, "plot")
        misc_path = fs.join(simulation_path, "misc")

        # Check existence
        if not fs.is_directory(extr_path):
            raise IOError("Extraction directory not found")
        if not fs.is_directory(plot_path):
            raise IOError("Plotting directory not found")
        if not fs.is_directory(misc_path):
            raise IOError("Misc directory not found")

        # Copy
        self.copy_reference(ski_path, in_path, out_path, extr_path, plot_path,
                            misc_path)
Beispiel #4
0
    def create_template(self):
        """
        This function ...
        :return:
        """

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

        # Load as labeled ski file
        self.ski_template = LabeledSkiFile(self.reference_ski_path)

        # Add parameter labels
        self.add_labels()

        # Set initial parameter values
        self.set_initial_values()
Beispiel #5
0
    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

        # Get free parameter names
        ski = LabeledSkiFile(ski_path)
        free_parameter_names = ski.labels

        # Get fitting filter names
        filter_names = sed.filter_names()

        # Set descriptions
        descriptions = Map()
        descriptions["luminosity"] = "total luminosity of the SN"
        descriptions["dustmass"] = "total dust mass"
        descriptions["grainsize"] = "dust grain size"
        descriptions["fsil"] = "dust silicate fraction"

        # Set types
        types = Map()
        types["luminosity"] = "luminosity"
        types["dustmas"] = "mass"
        types["grainsize"] = "grainsize"
        types["fsil"] = "dimless"

        # Set units
        units = Map()
        units["luminosity"] = u("Lsun")
        units["dustmass"] = u("Msun")
        units["grainsize"] = u("micron")
        units["fsil"] = None

        # Set ranges
        luminosity_range = QuantityRange(100, 1000, "Lsun")
        dustmass_range = QuantityRange(0.3, 5, "Msun")
        grainsize_range = QuantityRange(0.1, 5, "micron")
        fsil_range = RealRange(0.1, 100)

        # 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, "./SN1987A")

        # Add the command
        #commands.append(model_command)

        self.modeler = self.run_command(model_command)
Beispiel #6
0
class M81SEDTest(M81TestBase):
    """
    This class runs the test on M81, but by only adjusting the normalizations (not by creating a model),
    and fitting to a mock observed SED
    """
    def __init__(self, *args, **kwargs):
        """
        The constructor
        :param kwargs:
        """

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

        # The galaxy properties
        self.properties = None

        # Bulge and disk model
        self.bulge = None
        self.disk = None

        # The input maps
        self.maps = dict()

        # The instrument
        self.instrument = None

        # The ski template
        self.ski_template = None

        # The observed SED
        self.observed_sed = None

        # The initial parameter values for the fitting
        self.initial_parameter_values = dict()

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

    @property
    def from_existing_reference(self):
        """
        This function ...
        :return: 
        """

        return self.config.reference_path is not None or self.config.reference_test is not None

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

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

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

        # 2. Load the properties
        self.load_properties()

        # 3. Reference simulation
        self.set_reference()

        # 4. Get the real parameter values
        self.get_real_parameter_values()

        # 5. Generate the initial parameter values
        self.generate_initial_parameter_values()

        # 6. Create the ski file template
        self.create_template()

        # 7. Load the observed SED
        self.load_observed_sed()

        # 8. Setup the modeling
        self.setup_modelling()

        # 9. Model
        self.model()

        # 10. Get best parameter values
        self.get_best_parameter_values()

        # 11. Test
        self.test()

        # 12. Plot
        self.plot()

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

    @property
    def required_input_files(self):
        """
        This function ...
        :return:
        """

        return fs.files_in_path(self.simulation_input_path,
                                exact_not_name="wavelengths")

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

    @property
    def all_input_files(self):
        """
        This function ...
        :return:
        """

        return fs.files_in_path(self.simulation_input_path)

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

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

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

        # Create the SED instrument
        azimuth = parse_angle("0. deg")
        self.instrument = SEDInstrument(
            distance=self.galaxy_distance,
            inclination=self.galaxy_inclination,
            azimuth=azimuth,
            position_angle=self.galaxy_position_angle)

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

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

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

        # Load or create
        if self.from_existing_reference: self.load_reference()
        else: self.create_reference()

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

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

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

        # Determine simulation directory
        if self.config.reference_path is not None:
            simulation_path = self.config.reference_path
        elif self.config.reference_test is not None:
            simulation_path = fs.join(introspection.pts_tests_dir,
                                      self.config.reference_test, "ref")
        else:
            raise ValueError(
                "Reference path and reference test settings are None")

        # Check whether present
        if not fs.is_directory(simulation_path):
            raise ValueError(
                "The reference simulation path could not be found")

        # Look for simulation
        prefix, ski_path, in_path, out_path = find_one_simulation_in_path(
            simulation_path)

        # Load the ski file
        self.ski = LabeledSkiFile(ski_path)

        # Other paths
        extr_path = fs.join(simulation_path, "extr")
        plot_path = fs.join(simulation_path, "plot")
        misc_path = fs.join(simulation_path, "misc")

        # Check existence
        if not fs.is_directory(extr_path):
            raise IOError("Extraction directory not found")
        if not fs.is_directory(plot_path):
            raise IOError("Plotting directory not found")
        if not fs.is_directory(misc_path):
            raise IOError("Misc directory not found")

        # Copy
        self.copy_reference(ski_path, in_path, out_path, extr_path, plot_path,
                            misc_path)

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

    def copy_reference(self, ski_path, in_path, out_path, extr_path, plot_path,
                       misc_path):
        """
        This function ...
        :param ski_path:
        :param in_path:
        :param out_path:
        :param extr_path:
        :param plot_path:
        :param misc_path:
        :return: 
        """

        # Copy to new reference path
        fs.copy_file(ski_path, self.reference_ski_path)
        if in_path is not None:
            fs.copy_from_directory(in_path, self.simulation_input_path)
        fs.copy_from_directory(out_path, self.simulation_output_path)
        fs.copy_from_directory(extr_path, self.simulation_extract_path)
        fs.copy_from_directory(plot_path, self.simulation_plot_path)
        fs.copy_from_directory(misc_path, self.simulation_misc_path)

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

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

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

        # 1. Load the components
        self.load_components()

        # 2. Load the input maps
        self.load_maps()

        # 3. Create instrument
        self.create_instrument()

        # 4. Create deprojection
        self.create_deprojections()

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

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

        # 7. Create the ski file
        self.create_ski()

        # 8. Write
        self.write_reference()

        # 9. Plot
        self.plot_reference()

        # 10. Launch the reference simulation
        self.launch_reference()

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

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

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

        # Write the ski file
        self.write_ski()

        # Write the input
        self.write_input()

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

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

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

        # Plot the wavelengths
        self.plot_wavelengths()

        # Plot the filters
        self.plot_filters()

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

    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["input"] = self.simulation_input_path
        settings_launch["output"] = self.simulation_output_path
        settings_launch["create_output"] = True
        settings_launch["remote"] = self.moderator.host_id_for_single(
            "reference")
        settings_launch["attached"] = self.config.attached
        settings_launch["progress_bar"] = True

        # Create the analysis options
        analysis = AnalysisOptions()
        analysis.extraction.path = self.simulation_extract_path
        analysis.plotting.path = self.simulation_plot_path
        analysis.misc.path = self.simulation_misc_path
        analysis.extraction.progress = True
        analysis.extraction.timeline = True
        analysis.extraction.memory = True
        analysis.plotting.progress = True
        analysis.plotting.timeline = True
        analysis.plotting.memory = True
        analysis.plotting.seds = True
        analysis.plotting.grids = True
        analysis.plotting.reference_seds = fs.files_in_path(seds_path)
        analysis.misc.fluxes = True
        analysis.misc.images = False
        analysis.misc.observation_filters = fitting_filter_names
        analysis.misc.observation_instruments = [instrument_name]
        analysis.misc.spectral_convolution = self.config.spectral_convolution

        # Set flux error bars
        dustpedia_sed = ObservedSED.from_file(dustpedia_sed_path)
        filter_names = dustpedia_sed.filter_names()
        errors = dustpedia_sed.errors()
        flux_errors = sequences.zip_into_dict(filter_names,
                                              [str(error) for error in errors])
        analysis.misc.flux_errors = flux_errors

        # Input
        input_launch = dict()
        # input_launch["memory"] = MemoryRequirement(serial_memory, parallel_memory)
        input_launch["analysis_options"] = analysis

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

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

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

        # Inform the user
        log.info("Generating random initial parameter values ...")

        # Get the low and high value
        low_factor = self.config.relative_range_initial.min
        high_factor = self.config.relative_range_initial.max

        # Determine the exponents, to generate random points
        log_low = np.log10(low_factor)
        log_high = np.log10(high_factor)

        # Loop over the real parameter values
        for parameter_name in self.real_parameter_values:

            # Get the parameter value
            value = self.real_parameter_values[parameter_name]

            # Multiply the value with a random number between 1/3 and 3.
            random = np.random.uniform(log_low, log_high)
            random_factor = 10**random
            value = value * random_factor  # DON'T DO VALUE *= RANDOM_FACTOR HERE: CHANGES THE UNDERLYING QUANTITY OBJECT AS WELL IN SELF.REAL_PARAMETER_VALUES !!

            # Set the value as the initial parameter value
            self.initial_parameter_values[parameter_name] = value

        # Debugging
        log.debug("The initial parameter values are:")
        log.debug("")
        for parameter_name in self.real_parameter_values:
            log.debug(" - " + parameter_name + ": " +
                      tostr(self.initial_parameter_values[parameter_name],
                            scientific=True,
                            fancy=True,
                            ndigits=parameter_ndigits[parameter_name]))
        log.debug("")

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

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

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

        # Load as labeled ski file
        self.ski_template = LabeledSkiFile(self.reference_ski_path)

        # Add parameter labels
        self.add_labels()

        # Set initial parameter values
        self.set_initial_values()

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

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

        # Inform the user
        log.info("Adding the free parameter labels ...")

        # Add labels for absolute properties
        self.add_labels_absolute()

        # Add labels for stellar component properties
        self.add_labels_stellar_components()

        # Add labels for dust component properties
        self.add_labels_dust_components()

        # Add labels for instruments
        self.add_labels_instruments()

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

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

        # Inform the user
        log.info(
            "Adding parameter labels for absolute simulation properties ...")

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

            # Search in the absolute parameters
            if parameter_name not in free_parameters_absolute_paths: continue

            # Determine path
            path = free_parameters_absolute_paths[parameter_name]

            # label
            self.ski_template.add_label_to_path(path, parameter_name)

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

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

        # Inform the user
        log.info(
            "Adding parameter labels for stellar component properties ...")

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

            # Search in the stellar components
            if parameter_name not in free_parameters_relative_stellar_component_paths:
                continue

            # Determine the relative path to the property and the stellar component name
            path, component_name = free_parameters_relative_stellar_component_paths[
                parameter_name]

            # Specific component is specified
            if component_name is not None:

                # Get the stellar component
                stellar_component = self.ski_template.get_stellar_component(
                    component_name)

                # label
                self.ski_template.add_label_to_path(path, parameter_name,
                                                    stellar_component)

            # Non-specific
            else:

                # Loop over the stellar components
                for component_id in self.ski_template.get_stellar_component_ids(
                ):

                    # Get the stellar component
                    stellar_component = self.ski_template.get_stellar_component(
                        component_id)

                    # Label
                    self.ski_template.add_label_to_path(
                        path, parameter_name, stellar_component)

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

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

        # Inform the user
        log.info("Adding labels for dust components ...")

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

            # Dust components
            if parameter_name not in free_parameters_relative_dust_component_paths:
                continue

            # Determine the relative path to the property and the dust component name
            path, component_name = free_parameters_relative_dust_component_paths[
                parameter_name]

            # Specific component is specified
            if component_name is not None:

                # Get the dust component
                dust_component = self.ski_template.get_dust_component(
                    component_name)

                # label
                self.ski_template.add_label_to_path(path, parameter_name,
                                                    dust_component)

            # Non-specific
            else:

                # Loop over the dust components
                for component_id in self.ski_template.get_dust_component_ids():

                    # Get the dust component
                    dust_component = self.ski_template.get_dust_component(
                        component_id)

                    # Label
                    self.ski_template.add_label_to_path(
                        path, parameter_name, dust_component)

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

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

        # Inform the user
        log.info("Adding parameter labels for instrument properties ...")

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

            # Instruments
            if parameter_name not in free_parameters_relative_instruments_paths:
                continue

            # Determine the relative path to the property and the instrument name
            path, instrument_name = free_parameters_relative_instruments_paths[
                parameter_name]

            # Specific instrument is specified
            if instrument_name is not None:

                # Get the instrument
                instrument = self.ski.get_instrument(instrument_name)

                # Label
                self.ski_template.add_label_to_path(path, parameter_name,
                                                    instrument)

            # Non-specific
            else:

                # Loop over the instruments
                for instrument_name in self.ski.get_instrument_names():

                    # Get the instruemnt
                    instrument = self.ski.get_instrument(instrument_name)

                    # Label
                    self.ski_template.add_label_to_path(
                        path, parameter_name, instrument)

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

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

        # Inform the user
        log.info("Setting the initial parameter values for the fitting ...")

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

            # Get the value
            value = self.initial_parameter_values[parameter_name]

            # Set the value
            self.ski_template.set_labeled_value(parameter_name, value)

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

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

        # Inform the user
        log.info("Loading the mock observed sed ...")

        # Determine path
        paths = fs.files_in_path(self.simulation_misc_path,
                                 contains="_fluxes",
                                 extension="dat")

        # Check if there is only one SED
        if len(paths) > 1: raise RuntimeError("More than one SED is found")
        path = paths[0]

        # Load the observed SED
        self.observed_sed = ObservedSED.from_file(path)

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

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

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

        # Settings
        settings_setup = dict()
        settings_setup["type"] = "sed"
        settings_setup["name"] = self.modeling_name
        settings_setup[
            "fitting_host_ids"] = self.moderator.host_ids_for_ensemble(
                "fitting", none_if_none=True)

        # Create input dict for setup
        input_setup = dict()
        input_setup["sed"] = self.observed_sed
        input_setup["ski"] = self.ski_template
        #input_setup["ski_input"] = self.required_input_files
        input_setup[
            "ski_input"] = self.all_input_files  # Important so that the fittinginitializer can choose the number
        #  of wavelengths for the fitting based on what the user used as a wavelength grid file for the ski file

        # Create object config
        object_config = dict()
        # object_config["ski"] = ski_path
        input_setup["object_config"] = object_config

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

        # Call the command
        tool = self.run_command(stp)

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

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

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

        # Settings
        settings_model = dict()
        settings_model["ngenerations"] = self.config.ngenerations
        settings_model["nsimulations"] = self.config.nsimulations
        settings_model["fitting_settings"] = {"spectral_convolution": False}

        # For remote execution
        settings_model["attached"] = self.config.attached
        settings_model["fitting_attached"] = self.config.attached

        # Set the random seed
        #settings_model["seed"] = self.config.seed

        # RECURRENCE SETTINGS
        settings_model["check_recurrence"] = self.config.check_recurrence
        settings_model["recurrence_rtol"] = self.config.recurrence_rtol
        settings_model["recurrence_atol"] = self.config.recurrence_atol

        # Input
        input_model = dict()

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

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

        # Create free parameters config

        # Create descriptions config
        descriptions_config = Map(descriptions=free_parameter_descriptions)
        input_model["descriptions_config"] = descriptions_config

        # Create types config
        types_config = Map(types=free_parameter_types)
        input_model["types_config"] = types_config

        # Create units config
        units_config = Map(units=free_parameter_units)
        input_model["units_config"] = units_config

        # Create the ndigits config
        ndigits_config = Map(ndigits=parameter_ndigits)
        input_model["ndigits_config"] = ndigits_config

        # Create filters config
        filters_config = Map(filters=fitting_filter_names)
        input_model["filters_config"] = filters_config

        # Create genetic config
        input_model["genetic_config"] = Map(genetic=self.config.genetic)

        # Create grid config ??
        #input_model["grid_config"] = Map(grid=self.config.grid)

        # Create ranges config
        ranges_config = Map()
        for parameter_name in self.config.free_parameters:  # Define range
            ranges_config[
                parameter_name +
                "_range"] = self.config.relative_range_fitting * self.real_parameter_values[
                    parameter_name]
        input_model["ranges_config"] = ranges_config

        # If we're cheating
        if self.config.cheat:
            fixed_parameter_values = defaultdict(list)
            for label in self.config.free_parameters:
                fixed_parameter_values[label].append(
                    self.real_parameter_values[label])
            input_model["fixed_initial_parameters"] = fixed_parameter_values

        # Create initialize config
        initialize_config = Map()
        initialize_config.npackages = self.config.npackages_fitting
        initialize_config.selfabsorption = self.config.selfabsorption
        initialize_config.transient_heating = self.config.transient_heating
        input_model["initialize_config"] = initialize_config

        # Other input
        input_model["fitting_method"] = self.config.fitting_method
        input_model["parameter_grid_scales"] = self.parameter_grid_scales
        input_model["parameter_grid_weights"] = None

        # Construct the command
        command = Command("model",
                          "perform the modelling",
                          settings_model,
                          input_model,
                          cwd=self.modeling_path)

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

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

    @property
    def parameter_grid_scales(self):
        """
        This function ...
        :return: 
        """

        scales = dict()
        for label in self.config.free_parameters:
            scales[label] = self.config.scale
        return scales

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

    @property
    def modeling_environment(self):
        """
        This function ...
        :return: 
        """

        return SEDModelingEnvironment(self.modeling_path)

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

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

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

        # Check the best value
        #self.check_best() # CANNOT CHECK ANYMORE TEMPORARILY BECAUSE OF RECURRENCE

        # Check the database
        self.check_database()
Beispiel #7
0
    def model(self):
        """
        This function ...
        :return:
        """

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

        # Input

        # Get free parameter names
        ski = LabeledSkiFile(ski_path)
        free_parameter_names = ski.labels

        # Get fitting filter names
        #filter_names = sed.filter_names()

        # Set descriptions
        descriptions = Map()
        descriptions[
            "exp_dustmass"] = "dust mass of the exponential disk with spiral structure"

        # Set types
        types = Map()
        types["exp_dustmass"] = "dust mass"

        # Set units
        units = Map()
        units["exp_dustmass"] = u("Msun")

        # Set the range of the dust mass
        dustmass_range = QuantityRange(0.1 * dust_mass, 100 * dust_mass)

        # 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(
            exp_dustmass_range=dustmass_range)
        #input_model["filters_config"] = Configuration(filters=filter_names)

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

        # Add dict of input for 'model' command to the list
        #input_dicts.append(input_model)

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

        # Add the command
        #commands.append(command)

        modeler = self.run_command(command)
Beispiel #8
0
# -----------------------------------------------------------------

this_path = fs.absolute_path(inspect.stack()[0][1])
this_dir_path = fs.directory_of(this_path)

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

description = "determining parameters based on mock observations of a simple spiral galaxy model"

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

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

# Get the initial dust mass of the exponential disk with spiral structure
ski = LabeledSkiFile(ski_path)
dust_mass = ski.get_labeled_value("exp_dustmass")

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


class SpiralTest(TestImplementation):
    """
    This class ...
    """
    def __init__(self, *args, **kwargs):
        """
        The constructor ...
        :param kwargs:
        """
Beispiel #9
0
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)
Beispiel #10
0
metallicity = fixed["metallicity"]
compactness = fixed["sfr_compactness"]
pressure = fixed["sfr_pressure"]
covering_factor = fixed["sfr_covering"]

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

test_path = fs.create_directory_in(modeling_path, "test")

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

# Ski template path
ski_template_path = fs.join(modeling_path, "fit", "template.ski")

# Open the ski template
ski = LabeledSkiFile(ski_template_path)

# Get initial values
initial_values = ski.get_labeled_values()

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

# Initial guess for the star formation rate # see Perez-Gonzalez 2006 (mentions Devereux et al 1995)
sfr = 0.8  # in Msun yr-1

# Create the MAPPINGS template
mappings_initial = Mappings(metallicity, compactness, pressure,
                            covering_factor, sfr)

# Luminosity for FUV (wavelength)
lum = mappings_initial.luminosity_at(fuv_wavelength)
Beispiel #11
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