def test_min_less_than_max_passes(self):
        mock_ui_holder = MockUIHolder()
        light_cone_form = make_form(self.default_form_values,LightConeForm,{},prefix='light_cone')
        mock_ui_holder.update(light_cone = light_cone_form)
        record_filter_form = make_form(self.default_form_values,RecordFilterForm,{'filter':'D-'+str(self.filter.id),'max': '30', 'min': '3'}, prefix='record_filter',ui_holder=mock_ui_holder)

        self.assertTrue(record_filter_form.is_valid())
 def test_min_wrong_type_fails(self):
     mock_ui_holder = MockUIHolder()
     light_cone_form = make_form(self.default_form_values,LightConeForm,{},prefix='light_cone')
     mock_ui_holder.update(light_cone = light_cone_form)
     for filter_obj, val in [(self.filter, '3.0'), (self.filter_float, 'a'), (self.filter_long, '3.0')]:
         record_filter_form = make_form(self.default_form_values,RecordFilterForm,{'filter':'D-'+str(filter_obj.id),'min': val}, prefix='record_filter',ui_holder=mock_ui_holder)
         self.assertFalse(record_filter_form.is_valid())
    def test_min_or_max_required_for_other_filter(self):
        mock_ui_holder = MockUIHolder()
        light_cone_form = make_form(self.default_form_values,LightConeForm,{},prefix='light_cone')
        mock_ui_holder.update(light_cone = light_cone_form)
        record_filter_form = make_form(self.default_form_values,RecordFilterForm,{'filter':'D-'+str(self.filter_long.id)}, prefix='record_filter',ui_holder=mock_ui_holder)

        self.assertFalse(record_filter_form.is_valid())
    def test_redshift_max_redshift_min_length(self):
        redshift_max_overflow_form = make_form(self.default_form_values,LightConeForm,{'redshift_max': '123456789012345678901', 'redshift_min': '7'},prefix='light_cone')
        self.assertFalse(redshift_max_overflow_form.is_valid())
        self.assertEqual(['Ensure that there are no more than 20 digits in total.'], redshift_max_overflow_form.errors['redshift_max'])

        redshift_min_overflow_form = make_form(self.default_form_values,LightConeForm,{'redshift_max': '2', 'redshift_min': '1.0000000000000000000001'},prefix='light_cone')
        self.assertFalse(redshift_min_overflow_form.is_valid())
        self.assertEqual(['Ensure that there are no more than 20 digits in total.'], redshift_min_overflow_form.errors['redshift_min'])
    def test_min_and_max_not_used_for_no_filter(self):
        from tao.forms import NO_FILTER
        mock_ui_holder = MockUIHolder()
        light_cone_form = make_form(self.default_form_values, LightConeForm, {}, prefix='light_cone')
        mock_ui_holder.update(light_cone = light_cone_form)
        record_filter_form = make_form(self.default_form_values, RecordFilterForm, {'filter': 'X-'+NO_FILTER}, prefix='record_filter', ui_holder=mock_ui_holder)

        self.assertTrue(record_filter_form.is_valid())
    def test_min_greater_than_max_fails(self):
        mock_ui_holder = MockUIHolder()
        light_cone_form = make_form(self.default_form_values,LightConeForm,{},prefix='light_cone')
        mock_ui_holder.update(light_cone = light_cone_form)

        record_filter_form = make_form(self.default_form_values,RecordFilterForm,{'max': '3', 'min': '9'}, prefix='record_filter',ui_holder=mock_ui_holder)

        self.assertFalse(record_filter_form.is_valid())
        self.assertEqual(['The "min" field must be less than the "max" field.'], record_filter_form.errors['min'])
    def test_min_or_max_required_when_no_default(self):
        data_set_no_default = DataSetFactory.create(simulation=self.simulation, galaxy_model=GalaxyModelFactory.create())
        new_filter = DataSetPropertyFactory.create(dataset=data_set_no_default)
        mock_ui_holder = MockUIHolder()
        light_cone_form = make_form(self.default_form_values,LightConeForm,{'galaxy_model': data_set_no_default.id, 'output_properties': [str(new_filter.id)],},prefix='light_cone')
        mock_ui_holder.update(light_cone = light_cone_form)
        record_filter_form = make_form(self.default_form_values,RecordFilterForm,{'filter':'D-'+str(new_filter.id)}, prefix='record_filter',ui_holder=mock_ui_holder)

        self.assertFalse(record_filter_form.is_valid())
 def test_min_or_max_provided_is_valid(self):
     mock_ui_holder = MockUIHolder()
     light_cone_form = make_form(self.default_form_values,LightConeForm,{},prefix='light_cone')
     mock_ui_holder.update(light_cone = light_cone_form)
     # test on default
     record_filter_form = make_form(self.default_form_values,RecordFilterForm,{'filter':'D-'+str(self.filter.id),'min':'10'}, prefix='record_filter',ui_holder=mock_ui_holder)
     self.assertTrue(record_filter_form.is_valid())
     # test on other
     record_filter_form = make_form(self.default_form_values,RecordFilterForm,{'filter':'D-'+str(self.filter_long.id),'min':'10'}, prefix='record_filter',ui_holder=mock_ui_holder)
     self.assertTrue(record_filter_form.is_valid())
    def test_max_or_min_empty_passes(self):
        mock_ui_holder = MockUIHolder()
        lc_form = make_form(self.default_form_values,LightConeForm,{},prefix='light_cone')
        mock_ui_holder.update(light_cone = lc_form)

        rf_form_no_min = make_form(self.default_form_values,RecordFilterForm,{'max': '3', 'min': ''}, prefix='record_filter',ui_holder=mock_ui_holder)
        rf_form_no_max = make_form(self.default_form_values,RecordFilterForm,{'max': '', 'min': '9'}, prefix='record_filter',ui_holder=mock_ui_holder)

        self.assertTrue(rf_form_no_min.is_valid())
        self.assertTrue(rf_form_no_max.is_valid())
    def test_max_min_length(self):
        mock_ui_holder = MockUIHolder()
        lc_form = make_form(self.default_form_values,LightConeForm,{},prefix='light_cone')
        mock_ui_holder.update(light_cone = lc_form)
        max_overflow_form = make_form(self.default_form_values,RecordFilterForm,{'filter':'D-'+str(self.filter.id), 'max': '100000000000000000000', 'min': '7'}, prefix='record_filter',ui_holder=mock_ui_holder)
        self.assertFalse(max_overflow_form.is_valid())
        self.assertEqual(['Ensure that there are no more than 20 digits in total.'], max_overflow_form.errors['max'])

        min_overflow_form = make_form(self.default_form_values,RecordFilterForm,{'filter':'D-'+str(self.filter.id), 'max': '2', 'min': '1.000000000000000000001'}, prefix='record_filter',ui_holder=mock_ui_holder)
        self.assertFalse(min_overflow_form.is_valid())
        self.assertEqual(['Ensure that there are no more than 20 digits in total.'], min_overflow_form.errors['min'])
 def test_output_properties_is_required(self):
     light_cone_form = make_form(self.default_form_values,LightConeForm,{
         'output_properties': [],
         },prefix='light_cone')
     self.assertEqual({
         'output_properties': [u'This field is required.'],
         }, light_cone_form.errors)
    def test_box_size_is_not_required_for_box(self):
        light_cone_form = make_form(self.default_form_values,LightConeForm,{
            'catalogue_geometry': LightConeForm.BOX,
            'snapshot': Snapshot.objects.all()[0].id,
            },prefix='light_cone')

        self.assertEqual({}, light_cone_form.errors)
        self.assertTrue(light_cone_form.is_valid())
 def test_dust_model_required_for_dust(self):
     sed_form_with_dust = make_form(self.default_form_values, SEDForm,
                                    {'apply_sed': True,
                                     'apply_dust': True,
                                     'single_stellar_population_model': self.stellar_model.id,
                                     'band_pass_filters': self.bandpass.id,},
                                    prefix='sed')
     self.assertFalse(sed_form_with_dust.is_valid())
     self.assertEqual(['This field is required.'], sed_form_with_dust.errors['select_dust_model'])
    def test_box_size_input_error(self):
        light_cone_form = make_form(self.default_form_values,LightConeForm,{
            'catalogue_geometry': LightConeForm.BOX,
            'box_size': 'badnumber',
            'snapshot': Snapshot.objects.all()[0].id,
        }, prefix='light_cone')

        self.assertEqual({'box_size': ['Enter a number.']}, light_cone_form.errors)
        self.assertFalse(light_cone_form.is_valid())

        light_cone_form = make_form(self.default_form_values,LightConeForm,{
            'catalogue_geometry': LightConeForm.BOX,
            'box_size': '',
            'snapshot': Snapshot.objects.all()[0].id,
        }, prefix='light_cone')

        self.assertEqual({}, light_cone_form.errors)
        self.assertTrue(light_cone_form.is_valid())
    def test_box_size_small_or_equal_to_simulation(self):
        light_cone_form = make_form(self.default_form_values,LightConeForm,{
            'catalogue_geometry': LightConeForm.BOX,
            'box_size': self.simulation.box_size + 1,
            'snapshot': Snapshot.objects.all()[0].id,
            },prefix='light_cone')

        self.assertFalse(light_cone_form.is_valid())
        self.assertTrue('box_size' in light_cone_form.errors)
    def test_box_size_greater_than_zero(self):
        light_cone_form = make_form(self.default_form_values,LightConeForm,{
            'catalogue_geometry': LightConeForm.BOX,
            'box_size': -10,
            'snapshot': Snapshot.objects.all()[0].id,
            },prefix='light_cone')

        self.assertFalse(light_cone_form.is_valid())
        self.assertTrue('box_size' in light_cone_form.errors)
    def test_ra_dec_min_max(self):
        light_cone_form = make_form(self.default_form_values,LightConeForm,{
            'catalogue_geometry': LightConeForm.CONE,
            'ra_opening_angle': '-1',
            'dec_opening_angle': '-1',
        }, prefix='light_cone')
        self.assertEqual({
            'ra_opening_angle': ['Ensure this value is greater than or equal to 0.'],
            'dec_opening_angle': ['Ensure this value is greater than or equal to 0.'],
        }, light_cone_form.errors)

        light_cone_form = make_form(self.default_form_values,LightConeForm,{
            'catalogue_geometry': LightConeForm.CONE,
            'ra_opening_angle': '362',
            'dec_opening_angle': '362',
        }, prefix='light_cone')
        self.assertEqual({
            'ra_opening_angle': ['Ensure this value is less than or equal to 360.'],
            'dec_opening_angle': ['Ensure this value is less than or equal to 360.'],
        }, light_cone_form.errors)
    def test_ra_dec_required_for_light_cone(self):
        light_cone_form = make_form(self.default_form_values,LightConeForm,{
            'catalogue_geometry': LightConeForm.CONE,
            'ra_opening_angle': '',
            'dec_opening_angle': ''
        },prefix='light_cone')
        light_cone_form.is_valid()

        self.assertEqual({
            'ra_opening_angle': ['This field is required.'],
            'dec_opening_angle': ['This field is required.'],
        }, light_cone_form.errors)
    def test_ra_dec_not_required_for_light_box(self):
        light_cone_form = make_form(self.default_form_values,LightConeForm,{
            'catalogue_geometry': LightConeForm.BOX,
            'box_size': self.simulation.box_size,
            'snapshot': Snapshot.objects.all()[0].id,
            'ra_min': '',
            'dec_min': '',
            'ra_opening_angle': '',
            'dec_opening_angle': '',
        },prefix='light_cone')
        light_cone_form.is_valid()

        self.assertEqual({}, light_cone_form.errors)
Пример #20
0
    def test_unique_cone(self):
        form_parameters = {
            'catalogue_geometry': 'light-cone',
            'dark_matter_simulation': self.simulation.id,
            'galaxy_model': self.galaxy_model.id,
            'redshift_min': 0.0,
            'redshift_max': 0.2,
            'ra_opening_angle': 12.001,
            'dec_opening_angle': 10.003,
            'output_properties' : [self.filter.id, self.output_prop.id, self.computed_filter.id],
            'light_cone_type': 'unique',
            'number_of_light_cones': 8,
            }
        xml_parameters = form_parameters.copy()
        xml_parameters.update({
            'username' : self.user.username,
            'dark_matter_simulation': self.simulation.name,
            'galaxy_model': self.galaxy_model.name,
            'output_properties_1_name' : self.filter.name,
            'output_properties_1_label' : self.filter.label,
            'output_properties_1_units' : self.filter.units,
            'output_properties_1_description' : self.filter.description,
            'output_properties_2_name' : self.output_prop.name,
            'output_properties_2_label' : self.output_prop.label,
            'output_properties_2_description' : self.output_prop.description,
            'output_properties_3_name' : self.computed_filter.name,
            'output_properties_3_label' : self.computed_filter.label,
            'output_properties_3_description' : self.computed_filter.description,
            })
        xml_parameters.update({
            'filter': self.filter.name,
            'filter_min' : '1000000',
            'filter_max' : 'None',
        })
        xml_parameters.update({
            'apply_sed': False,
        })
        xml_parameters.update({
            'ssp_encoding': self.stellar_model.encoding,
            'band_pass_filter_label': self.band_pass_filter.label,
            'band_pass_filter_id': self.band_pass_filter.filter_id,
            'band_pass_filter_name': self.band_pass_filter.filter_id,
            'dust_model_name': self.dust_model.name,
        })
        xml_parameters.update({
            'light_cone_id': FormsGraph.LIGHT_CONE_ID,
            'csv_dump_id': FormsGraph.OUTPUT_ID,
            'bandpass_filter_id': FormsGraph.BANDPASS_FILTER_ID,
            'sed_id': FormsGraph.SED_ID,
            'dust_id': FormsGraph.DUST_ID,
        })
        # TODO: there are commented out elements which are not implemented yet
        # comments are ignored by assertXmlEqual

        expected_parameter_xml = light_cone_xml(xml_parameters)

        mock_ui_holder = MockUIHolder()
        light_cone_form = make_form({}, LightConeForm, form_parameters, ui_holder=mock_ui_holder, prefix='light_cone')
        sed_form = make_form({}, SEDForm, self.sed_parameters, ui_holder=mock_ui_holder, prefix='sed')
        output_form = make_form({}, OutputFormatForm, {'supported_formats': 'csv'}, ui_holder=mock_ui_holder,
                                    prefix='output_format')
        mock_ui_holder.update(light_cone = light_cone_form, sed = sed_form, output_format = output_form)
        record_filter_form = make_form({}, RecordFilterForm, {'filter':'D-'+str(self.filter.id),'min':str(1000000)},
                                           ui_holder=mock_ui_holder, prefix='record_filter')
        self.assertEqual({}, light_cone_form.errors)
        self.assertEqual({}, sed_form.errors)
        self.assertEqual({}, record_filter_form.errors)
        self.assertEqual({}, output_form.errors)

        mock_ui_holder.update(record_filter = record_filter_form)
        mock_ui_holder.dataset = self.dataset
        job = workflow.save(self.user, mock_ui_holder)
        actual_parameter_xml = job.parameters

        self.assertEqual(self.dataset.database, job.database)
        self.assertXmlEqual(expected_parameter_xml, actual_parameter_xml)
    def test_sed_fields_required_for_sed(self):
        sed_form = make_form(self.default_form_values, SEDForm, {'apply_sed': True}, prefix='sed')

        self.assertFalse(sed_form.is_valid())
        self.assertEqual(['This field is required.'], sed_form.errors['band_pass_filters'])
    def test_sed_fields_not_required_for_no_sed(self):
        sed_form_no_sed = make_form(self.default_form_values, SEDForm, {})

        self.assertEqual({}, sed_form_no_sed.errors)
        self.assertTrue(sed_form_no_sed.is_valid())
    def test_redshift_min_less_than_redshift_max_passes(self):
        light_cone_form = make_form(self.default_form_values,LightConeForm,{'redshift_max': '2', 'redshift_min': '1.5'},prefix='light_cone')
        light_cone_form.is_valid()

        self.assertEqual({}, light_cone_form.errors)
        self.assertTrue(light_cone_form.is_valid())
 def test_redshift_max_less_than_zero_but_larger_than_redshift_min_fails(self):
     light_cone_form = make_form(self.default_form_values,LightConeForm,{'redshift_min': '-2', 'redshift_max': '-1'},prefix='light_cone')
     
     self.assertFalse(light_cone_form.is_valid())
     self.assertEqual(['The minimum redshift must be greater or equal to zero.'], light_cone_form.errors['redshift_min'])
     self.assertEqual(['The maximum redshift must be greater or equal to zero.'], light_cone_form.errors['redshift_max'])
 def test_redshift_min_greater_than_redshift_max_fails(self):
     light_cone_form = make_form(self.default_form_values,LightConeForm,{'redshift_max': '3', 'redshift_min': '9'},prefix='light_cone')
     light_cone_form.is_valid()
     
     self.assertFalse(light_cone_form.is_valid())
     self.assertEqual(['The minimum redshift must be less than or equal to the maximum redshift.'], light_cone_form.errors['redshift_min'])
Пример #26
0
            'ssp_encoding': self.stellar_model.encoding,
            'band_pass_filter_label': 'BPFN', # self.band_pass_filter.label,
            'band_pass_filter_id': 1L, # self.band_pass_filter.filter_id,
            'band_pass_filter_name': 'BPFN',
            'dust_model_name': 'DM', # self.dust_model.name,
        })
        xml_parameters.update({
            'light_cone_id': FormsGraph.LIGHT_CONE_ID,
            'csv_dump_id': FormsGraph.OUTPUT_ID,
            'bandpass_filter_id': FormsGraph.BANDPASS_FILTER_ID,
            'sed_id': FormsGraph.SED_ID,
            'dust_id': FormsGraph.DUST_ID,
        })
        mock_ui_holder = MockUIHolder()
        xml_str = light_cone_xml(xml_parameters)
        light_cone_form = make_form({}, LightConeForm, {'dark_matter_simulation':self.simulation.id, 'galaxy_model':self.dataset.id, 'catalogue_geometry': 'light-cone'}, prefix='light_cone')
        mock_ui_holder.update(light_cone = light_cone_form)
        mock_ui_holder.dataset = self.dataset
        rf_form = make_form_xml(RecordFilterForm, xml_str, prefix='record_filter', ui_holder=mock_ui_holder)

        self.assertEquals('D-' + str(self.filter.id), rf_form.data['record_filter-filter'])
        self.assertEquals('1000000', rf_form.data['record_filter-min'])
        self.assertEquals(None, rf_form.data['record_filter-max'])

    def test_sed_form(self):
        xml_parameters = {
            'catalogue_geometry': 'light-cone',
            'dark_matter_simulation': self.simulation.id, # self.simulation.id,
            'galaxy_model': self.galaxy_model.id, #self.galaxy_model.id,
            'redshift_min': 0.2,
            'redshift_max': 0.3,
Пример #27
0
    def test_no_dust(self):
        form_parameters = {
            'catalogue_geometry': 'box',
            'dark_matter_simulation': self.simulation.id,
            'galaxy_model': self.dataset.id,
            'output_properties' : [self.filter.id],
            'snapshot': self.snapshot.id,
            'box_size': 20,
            'rng_seed': 12345678901234567890
            }
        xml_parameters = form_parameters.copy()
        xml_parameters.update({
            'username' : self.user.username,
            'dark_matter_simulation': self.simulation.name,
            'galaxy_model': self.galaxy_model.name,
            'output_properties_1_name' : self.filter.name,
            'output_properties_1_label' : self.filter.label,
            'output_properties_1_units' : self.filter.units,
            'output_properties_1_description' : self.filter.description,
            'redshift' : float(self.snapshot.redshift),
            })
        xml_parameters.update({
            'filter': self.filter.name,
            'filter_min' : 'None',
            'filter_max' : '1000000',
            })
        # TODO: there are commented out elements which are not implemented yet
        xml_parameters.update({
            'ssp_encoding': self.stellar_model.encoding,
            'band_pass_filter_label': self.band_pass_filter.label,
            'band_pass_filter_id': self.band_pass_filter.filter_id,
            'band_pass_filter_name': self.band_pass_filter.filter_id,
            'band_pass_filter_description': self.band_pass_filter.description,
            'band_pass_extension': 'absolute',
            })
        xml_parameters.update({
            'light_cone_id': FormsGraph.LIGHT_CONE_ID,
            'csv_dump_id': FormsGraph.OUTPUT_ID,
            'bandpass_filter_id': FormsGraph.BANDPASS_FILTER_ID,
            'sed_id': FormsGraph.SED_ID,
            'dust_id': FormsGraph.DUST_ID,
            })
        # comments are ignored by assertXmlEqual
        expected_parameter_xml = stripped_joined_lines("""<?xml version="1.0"?>
            <!-- Using the XML namespace provides a version for future modifiability.  The timestamp allows
                 a researcher to know when this parameter file was generated.  -->
            <tao xmlns="http://tao.asvo.org.au/schema/module-parameters-v1" timestamp="2012-12-20T13:55:36+10:00">

                <!-- Username submitting the job -->
                <username>%(username)s</username>

                <!-- Workflow name identifies which workflow is to be executed.
                     This is currently a placeholder, the name is ignored. -->
                <workflow name="alpha-light-cone-image">

                    <!-- Global Configuration Parameters -->
                    <schema-version>2.0</schema-version>

                    <!-- Light-cone module parameters -->
                    <light-cone id="%(light_cone_id)s">
                        <!-- Module Version Number -->
                        <module-version>1</module-version>

                        <!-- Is the query a light-cone or box? -->
                        <geometry>box</geometry>

                        <!-- Selected Simuation -->
                        <simulation>%(dark_matter_simulation)s</simulation>

                        <!-- Selected Galaxy Model -->
                        <galaxy-model>%(galaxy_model)s</galaxy-model>

                        <!-- The number of light-cones to generate
                        <box-repetition>unique | random</box-repetition>
                        <num-cones>1</num-cones> -->

                        <!-- The min and max redshifts to filter by -->
                        <redshift>%(redshift).10f</redshift>

                        <!-- Size of box to return -->
                        <query-box-size units="Mpc">%(box_size)d</query-box-size>

                        <!-- RNG Seed -->
                        <!-- This will be added by the workflow after the job has been completed
                             to enable the job to be repeated.
                             The information stored may change, the intent is to store whatever is
                             required to re-run the job and obtain the same results.-->
                        <rng-seed>12345678901234567890</rng-seed> 

                        <!-- List of fields to be included in the output file -->
                        <output-fields>
                            <item description="%(output_properties_1_description)s" label="%(output_properties_1_label)s" units="%(output_properties_1_units)s">%(output_properties_1_name)s</item>
                        </output-fields>

                    </light-cone>

                    <!-- File output module -->
                    <csv id="%(csv_dump_id)s">
                        <fields>
                            <item label="%(output_properties_1_label)s" units="%(output_properties_1_units)s">%(output_properties_1_name)s</item>
                            <item label="bandpass (Absolute)">%(band_pass_filter_name)s_absolute</item>
                            <!-- <item label="bandpass (Apparent)">%(band_pass_filter_name)s_apparent</item> -->
                        </fields>

                        <!-- Module Version Number -->
                        <module-version>1</module-version>

                        <!-- Output file format -->
                        <filename>tao.output.csv</filename>

                        <parents>
                            <item>%(bandpass_filter_id)s</item>
                        </parents>

                    </csv>

                    <!-- Optional: Spectral Energy Distribution parameters -->
                    <sed id="%(sed_id)s">
                        <!-- Module Version Number -->
                        <module-version>1</module-version>

                        <parents>
                            <item>%(light_cone_id)s</item>
                        </parents>

                        %(ssp_encoding)s
                    </sed>

                    <filter id="%(bandpass_filter_id)s">
                        <module-version>1</module-version>
                        <parents>
                            <item>%(sed_id)s</item>
                        </parents>

                        <!-- Bandpass Filters) -->
                        <bandpass-filters>
                            <item description="%(band_pass_filter_description)s" label="%(band_pass_filter_label)s" selected="%(band_pass_extension)s">%(band_pass_filter_id)s</item>
                        </bandpass-filters>
                    </filter>

                    <!-- Record Filter -->
                    <record-filter>
                        <!-- Module Version Number -->
                        <module-version>1</module-version>

                        <!-- Note that the units are for readability,
                             no unit conversion is supported.  The consumer of the
                             parameter file should check that the expected units are provided. -->
                        <filter>
                            <filter-attribute>%(filter)s</filter-attribute>
                            <filter-min units="Msun/h">%(filter_min)s</filter-min>
                            <filter-max units="Msun/h">%(filter_max)s</filter-max>
                        </filter>
                    </record-filter>

                    <!-- Image generation module parameters
                    <image-generator>
                        <!- Module Version Number ->
                        <module-version>1</module-version>

                        <!- Image size parameters ->
                        <image-width units="px">1024</image-width>
                        <image-height units="px">1024</image-height>

                        <!- Focal scale parameters ->
                        <focalx units="??">1024</focalx>
                        <focaly units="??">1024</focaly>

                        <!- Image offset parameters ->
                        <image-offsetx units="??">512</image-offsetx>
                        <image-offsety units="??">0</image-offsety>
                    </image-generator> -->

                </workflow>

                <!-- The signature is automatically generated and is intended to be used when running
                     old versions of the science modules (to remove the need for the UI to parse and check
                     every version. -->
                <signature>base64encodedsignature</signature>

            </tao>
        """) % xml_parameters
        
        mock_ui_holder = MockUIHolder()
        light_cone_form = make_form({}, LightConeForm, form_parameters, ui_holder=mock_ui_holder, prefix='light_cone')
        sed_form = make_form({}, SEDForm, self.sed_parameters_no_dust, ui_holder=mock_ui_holder, prefix='sed')
        output_form = make_form({}, OutputFormatForm, {'supported_formats': 'csv'}, ui_holder=mock_ui_holder, prefix='output_format')
        mock_ui_holder.update(light_cone = light_cone_form, sed = sed_form, output_format = output_form)
        mock_ui_holder.dataset = self.dataset
        record_filter_form = make_form({}, RecordFilterForm, {'filter':'D-'+str(self.filter.id),'max':str(1000000)},
                                           ui_holder=mock_ui_holder, prefix='record_filter')
        self.assertEqual({}, light_cone_form.errors)
        self.assertEqual({}, sed_form.errors)
        self.assertEqual({}, record_filter_form.errors)
        self.assertEqual({}, output_form.errors)

        mock_ui_holder.update(record_filter = record_filter_form)
        job = workflow.save(self.user, mock_ui_holder)
        actual_parameter_xml = job.parameters

        self.assertXmlEqual(expected_parameter_xml, actual_parameter_xml)
        self.assertEqual(self.dataset.database, job.database)