Beispiel #1
0
    def test_exec_sed_task(self):
        task = sedml_data_model.Task(
            model=sedml_data_model.Model(
                source=self.EXAMPLE_MODEL_FILENAME,
                language=sedml_data_model.ModelLanguage.SBML.value,
                changes=[],
            ),
            simulation=sedml_data_model.UniformTimeCourseSimulation(
                algorithm=sedml_data_model.Algorithm(
                    kisao_id='KISAO_0000560',
                    changes=[
                        sedml_data_model.AlgorithmParameterChange(
                            kisao_id='KISAO_0000209',
                            new_value='2e-6',
                        ),
                    ],
                ),
                initial_time=0.,
                output_start_time=10.,
                output_end_time=20.,
                number_of_points=20,
            ),
        )

        variables = [
            sedml_data_model.Variable(id='time',
                                      symbol=sedml_data_model.Symbol.time,
                                      task=task),
            sedml_data_model.Variable(
                id='A',
                target=
                "/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='A']",
                task=task),
            sedml_data_model.Variable(
                id='C',
                target=
                '/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id="C"]',
                task=task),
            sedml_data_model.Variable(
                id='DA',
                target=
                "/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='DA']",
                task=task),
        ]

        variable_results = exec_sed_task(task, variables)

        self.assertTrue(sorted(variable_results.keys()),
                        sorted([var.id for var in variables]))
        self.assertEqual(variable_results[variables[0].id].shape,
                         (task.simulation.number_of_points + 1, ))
        numpy.testing.assert_almost_equal(
            variable_results['time'],
            numpy.linspace(task.simulation.output_start_time,
                           task.simulation.output_end_time,
                           task.simulation.number_of_points + 1),
        )

        for results in variable_results.values():
            self.assertFalse(numpy.any(numpy.isnan(results)))
    def test_exec_sed_task_negative_initial_time(self):
        task = sedml_data_model.Task(
            model=sedml_data_model.Model(
                source=os.path.join(os.path.dirname(__file__), 'fixtures', 'BIOMD0000000297.edited', 'ex1', 'BIOMD0000000297.xml'),
                language=sedml_data_model.ModelLanguage.SBML.value,
                changes=[],
            ),
            simulation=sedml_data_model.UniformTimeCourseSimulation(
                algorithm=sedml_data_model.Algorithm(
                    kisao_id='KISAO_0000088',
                ),
                initial_time=-10.,
                output_start_time=-10.,
                output_end_time=10.,
                number_of_points=20,
            ),
        )

        variables = [
            sedml_data_model.Variable(
                id='time',
                symbol=sedml_data_model.Symbol.time,
                task=task,
            ),
            sedml_data_model.Variable(
                id='BE',
                target="/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='BE']",
                target_namespaces=self.NAMESPACES,
                task=task,
            ),
        ]

        variable_results, _ = core.exec_sed_task(task, variables, log=TaskLog())

        self.assertTrue(sorted(variable_results.keys()), sorted([var.id for var in variables]))
        self.assertEqual(variable_results[variables[0].id].shape, (task.simulation.number_of_points + 1,))
        numpy.testing.assert_allclose(
            variable_results['time'],
            numpy.linspace(task.simulation.output_start_time, task.simulation.output_end_time, task.simulation.number_of_points + 1),
        )
        for variable in variables:
            self.assertFalse(numpy.any(numpy.isnan(variable_results[variable.id])))
    def _build_sed_doc(self, algorithm=None):
        if algorithm is None:
            algorithm = sedml_data_model.Algorithm(
                kisao_id='KISAO_0000019',
                changes=[
                    sedml_data_model.AlgorithmParameterChange(
                        kisao_id='KISAO_0000211',
                        new_value='2e-8',
                    ),
                ],
            )

        doc = sedml_data_model.SedDocument()
        doc.models.append(
            sedml_data_model.Model(
                id='model_1',
                source='model_1.bngl',
                language=sedml_data_model.ModelLanguage.BNGL.value,
                changes=[
                    sedml_data_model.ModelAttributeChange(
                        target='functions.gfunc.expression',
                        new_value='0.5*Atot^2/(10 + Atot^2)'),
                    sedml_data_model.ModelAttributeChange(
                        target='functions.gfunc().expression',
                        new_value='0.5*Atot^2/(10 + Atot^2)'),
                    sedml_data_model.ModelAttributeChange(
                        target='species.A().initialCount', new_value='4'),
                    sedml_data_model.ModelAttributeChange(
                        target='parameters.g1.value', new_value='18.0'),
                ],
            ))
        doc.simulations.append(
            sedml_data_model.UniformTimeCourseSimulation(
                id='sim_1_time_course',
                algorithm=algorithm,
                initial_time=0.,
                output_start_time=0.1,
                output_end_time=0.2,
                number_of_points=20,
            ))
        doc.tasks.append(
            sedml_data_model.Task(
                id='task_1',
                model=doc.models[0],
                simulation=doc.simulations[0],
            ))
        doc.data_generators.append(
            sedml_data_model.DataGenerator(
                id='data_gen_time',
                variables=[
                    sedml_data_model.Variable(
                        id='var_time',
                        symbol=sedml_data_model.Symbol.time,
                        task=doc.tasks[0],
                    ),
                ],
                math='var_time',
            ))
        doc.data_generators.append(
            sedml_data_model.DataGenerator(
                id='data_gen_A',
                variables=[
                    sedml_data_model.Variable(
                        id='var_A',
                        target="species.A",
                        task=doc.tasks[0],
                    ),
                ],
                math='var_A',
            ))
        doc.data_generators.append(
            sedml_data_model.DataGenerator(
                id='data_gen_B',
                variables=[
                    sedml_data_model.Variable(
                        id='var_B',
                        target='species.B.count',
                        task=doc.tasks[0],
                    ),
                ],
                math='var_B',
            ))
        doc.data_generators.append(
            sedml_data_model.DataGenerator(
                id='data_gen_GeneA_00',
                variables=[
                    sedml_data_model.Variable(
                        id='var_GeneA_00',
                        target="molecules.GeneA_00()",
                        task=doc.tasks[0],
                    ),
                ],
                math='var_GeneA_00',
            ))
        doc.data_generators.append(
            sedml_data_model.DataGenerator(
                id='data_gen_GeneA_01',
                variables=[
                    sedml_data_model.Variable(
                        id='var_GeneA_01',
                        target="molecules.GeneA_01()",
                        task=doc.tasks[0],
                    ),
                ],
                math='var_GeneA_01',
            ))
        doc.outputs.append(
            sedml_data_model.Report(
                id='report_1',
                data_sets=[
                    sedml_data_model.DataSet(
                        id='data_set_time',
                        label='Time',
                        data_generator=doc.data_generators[0]),
                    sedml_data_model.DataSet(
                        id='data_set_A',
                        label='A',
                        data_generator=doc.data_generators[1]),
                    sedml_data_model.DataSet(
                        id='data_set_B',
                        label='B',
                        data_generator=doc.data_generators[2]),
                    sedml_data_model.DataSet(
                        id='data_set_GeneA_00',
                        label='GeneA_00',
                        data_generator=doc.data_generators[3]),
                    sedml_data_model.DataSet(
                        id='data_set_GeneA_01',
                        label='GeneA_01',
                        data_generator=doc.data_generators[4]),
                ],
            ))

        append_all_nested_children_to_doc(doc)

        return doc
Beispiel #4
0
    def test(self):
        model = data_model.Model(
            id='model1',
            name='Model1',
            source='model.sbml',
            language='urn:sedml:language:sbml',
            changes=[
                data_model.ModelAttributeChange(target='/sbml:sbml/sbml:model[id=\'a\']/@id', new_value='234'),
                data_model.ModelAttributeChange(target='/sbml:sbml/sbml:model[id=\'b\']/@id', new_value='432'),
                data_model.AddElementModelChange(target='/sbml:sbml/sbml:model[id=\'b\']/@id', new_elements='432'),
                data_model.ReplaceElementModelChange(target='/sbml:sbml/sbml:model[id=\'b\']/@id', new_elements='432'),
                data_model.RemoveElementModelChange(target='/sbml:sbml/sbml:model[id=\'b\']/@id'),
                data_model.ComputeModelChange(
                    target='/sbml:sbml/sbml:model[id=\'b\']/@id',
                    parameters=[
                        data_model.Parameter(id='p_1', value=1.5),
                        data_model.Parameter(id='p_2', value=2.5),
                    ],
                    variables=[
                        data_model.Variable(
                            id='v_1',
                            model=None,
                            target="/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='param_1']",
                        ),
                        data_model.Variable(
                            id='v_1',
                            model=None,
                            target="/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='param_1']",
                        ),
                    ],
                    math='p_1 * v_1 + p_2 * v_2',
                ),
            ],
        )
        for var in model.changes[-1].variables:
            var.model = model

        ss_simulation = data_model.SteadyStateSimulation(
            id='simulation1',
            name='Simulation1',
            algorithm=data_model.Algorithm(
                kisao_id='KISAO_0000029',
                changes=[
                    data_model.AlgorithmParameterChange(kisao_id='KISAO_0000001', new_value='1.234'),
                ]),
        )

        one_step_simulation = data_model.OneStepSimulation(
            id='simulation1',
            name='Simulation1',
            algorithm=data_model.Algorithm(
                kisao_id='KISAO_0000029',
                changes=[
                    data_model.AlgorithmParameterChange(kisao_id='KISAO_0000001', new_value='1.234'),
                ]),
            step=10.)

        time_course_simulation = data_model.UniformTimeCourseSimulation(
            id='simulation1',
            name='Simulation1',
            algorithm=data_model.Algorithm(
                kisao_id='KISAO_0000029',
                changes=[
                    data_model.AlgorithmParameterChange(kisao_id='KISAO_0000001', new_value='1.234'),
                    data_model.AlgorithmParameterChange(kisao_id='KISAO_0000002', new_value='4.321'),
                ]),
            initial_time=10.,
            output_start_time=20.,
            output_end_time=30,
            number_of_steps=10)

        task = data_model.Task(id='task1', name='Task1', model=model, simulation=time_course_simulation)
        for var in model.changes[-1].variables:
            var.task = task

        report = data_model.Report(
            id='report1',
            name='Report1',
            data_sets=[
                data_model.DataSet(
                    id='dataset1',
                    name='Dataset1',
                    label='Dataset-1',
                    data_generator=data_model.DataGenerator(
                        id='dataGen1',
                        name='DataGen1',
                        variables=[
                            data_model.Variable(
                                id='DataGenVar1', name='DataGenVar1', target='/sbml:sbml/sbml:model/@id', task=task, model=model)
                        ],
                        parameters=[
                            data_model.Parameter(
                                id='DataGenParam1', name='DataGenParam1', value=2.)
                        ],
                        math='DataGenVar1 - DataGenParam1',
                    )
                ),
            ],
        )

        plot2d = data_model.Plot2D(
            name='Plot2D',
            curves=[
                data_model.Curve(
                    id='curve1', name='Curve1',
                    x_scale=data_model.AxisScale.linear,
                    y_scale=data_model.AxisScale.log,
                    x_data_generator=data_model.DataGenerator(
                        id='xDataGen1',
                        name='XDataGen1',
                        variables=[
                            data_model.Variable(
                                id='xDataGenVar1', name='XDataGenVar1', target='/sbml:sbml/sbml:model/@id', task=task, model=model)
                        ],
                        parameters=[
                            data_model.Parameter(
                                id='xDataGenParam1', name='XDataGenParam1', value=2.)
                        ],
                        math='xDataGenVar1 * xDataGenParam1',
                    ),
                    y_data_generator=None,
                ),
                data_model.Curve(
                    id='curve2', name='Curve2',
                    x_scale=data_model.AxisScale.linear,
                    y_scale=data_model.AxisScale.log,
                    x_data_generator=None,
                    y_data_generator=data_model.DataGenerator(
                        id='yDataGen1',
                        name='yDataGen1',
                        variables=[
                            data_model.Variable(
                                id='yDataGenVar1', name='YDataGenVar1', target='/sbml:sbml/sbml:model/@id', task=task, model=model)
                        ],
                        parameters=[
                            data_model.Parameter(
                                id='yDataGenParam1', name='YDataGenParam1', value=2.)
                        ],
                        math='yDataGenParam1 + YDataGenParam1',
                    ),
                ),
            ]
        )

        plot3d = data_model.Plot3D(
            name='Plot3D',
            surfaces=[
                data_model.Surface(
                    id='curve1', name='Curve1',
                    x_scale=data_model.AxisScale.linear,
                    y_scale=data_model.AxisScale.log,
                    z_scale=data_model.AxisScale.linear,
                    x_data_generator=data_model.DataGenerator(
                        id='xDataGen1',
                        name='XDataGen1',
                        variables=[
                            data_model.Variable(
                                id='xDataGenVar1', name='XDataGenVar1', target='/sbml:sbml/sbml:model/@id', task=task, model=model)
                        ],
                        parameters=[
                            data_model.Parameter(
                                id='xDataGenParam1', name='XDataGenParam1', value=2.)
                        ],
                        math='xDataGenVar1 * xDataGenParam1',
                    ),
                    y_data_generator=None,
                    z_data_generator=None,
                ),
                data_model.Surface(
                    id='curve2',
                    name='Curve2',
                    x_scale=data_model.AxisScale.linear,
                    y_scale=data_model.AxisScale.log,
                    z_scale=data_model.AxisScale.log,
                    x_data_generator=None,
                    y_data_generator=None,
                    z_data_generator=data_model.DataGenerator(
                        id='zDataGen1',
                        name='zDataGen1',
                        variables=[
                            data_model.Variable(
                                id='zDataGenVar1', name='ZDataGenVar1', target='/sbml:sbml/sbml:model/@id', task=task, model=model)
                        ],
                        parameters=[
                            data_model.Parameter(
                                id='zDataGenParam1', name='ZDataGenParam1', value=2.)
                        ],
                        math='zDataGenParam1 / ZDataGenParam1',
                    ),
                ),
            ]
        )

        document = data_model.SedDocument(
            level=1,
            version=3,
            models=[model],
            simulations=[ss_simulation, one_step_simulation, time_course_simulation],
            tasks=[task],
            data_generators=[plot2d.curves[0].x_data_generator],
            outputs=[report, plot2d, plot3d],
            metadata=Metadata(),
        )

        self.assertEqual(
            ss_simulation.to_tuple(),
            (
                ss_simulation.id,
                ss_simulation.name,
                (
                    ss_simulation.algorithm.kisao_id,
                    (
                        (
                            ss_simulation.algorithm.changes[0].kisao_id,
                            ss_simulation.algorithm.changes[0].new_value,
                        ),
                    ),
                ),
            )
        )

        self.assertEqual(
            one_step_simulation.to_tuple(),
            (
                one_step_simulation.id,
                one_step_simulation.name,
                (
                    one_step_simulation.algorithm.kisao_id,
                    (
                        (
                            one_step_simulation.algorithm.changes[0].kisao_id,
                            one_step_simulation.algorithm.changes[0].new_value,
                        ),
                    ),
                ),
                one_step_simulation.step
            )
        )

        self.assertEqual(report.to_tuple()[0], report.id)
        self.assertEqual(plot2d.to_tuple()[2][0][4], plot2d.curves[0].x_data_generator.id)

        self.assertEqual(document.to_tuple(), (
            document.level,
            document.version,
            (model.to_tuple(),),
            tuple(none_sorted((ss_simulation.to_tuple(), one_step_simulation.to_tuple(), time_course_simulation.to_tuple()))),
            (task.to_tuple(),),
            (plot2d.curves[0].x_data_generator.to_tuple(),),
            tuple(none_sorted((report.to_tuple(), plot2d.to_tuple(), plot3d.to_tuple()))),
            document.metadata.to_tuple(),
        ))

        change = model.changes[0]
        change2 = copy.deepcopy(change)
        self.assertTrue(change.is_equal(change2))
        change2.target = None
        self.assertFalse(change.is_equal(change2))

        change = model.changes[-1]
        change2 = copy.deepcopy(change)
        self.assertTrue(change.is_equal(change2))
        change2 = copy.deepcopy(change)
        change2.target = None
        self.assertFalse(change.is_equal(change2))
        change2 = copy.deepcopy(change)
        change2.parameters[0].value = -1
        self.assertFalse(change.is_equal(change2))
        change2 = copy.deepcopy(change)
        change2.variables[0].id = 'variable_1'
        self.assertFalse(change.is_equal(change2))
        change2 = copy.deepcopy(change)
        change2.variables[0].model.id = 'different_model'
        self.assertFalse(change.is_equal(change2))
        change2 = copy.deepcopy(change)
        change2.math = 'x * y'
        self.assertFalse(change.is_equal(change2))

        model2 = copy.deepcopy(model)
        self.assertTrue(model.is_equal(model2))
        model2.id = None
        self.assertFalse(model.is_equal(model2))

        alg_change = time_course_simulation.algorithm.changes[0]
        alg_change_2 = copy.deepcopy(alg_change)
        self.assertTrue(alg_change.is_equal(alg_change_2))
        alg_change_2.new_value = None
        self.assertFalse(alg_change.is_equal(alg_change_2))

        alg = time_course_simulation.algorithm
        alg2 = copy.deepcopy(alg)
        self.assertTrue(alg.is_equal(alg2))
        alg2.kisao_id = None
        self.assertFalse(alg.is_equal(alg2))

        one_step_simulation_2 = copy.deepcopy(one_step_simulation)
        self.assertTrue(one_step_simulation.is_equal(one_step_simulation_2))
        one_step_simulation_2.step = -1.
        self.assertFalse(one_step_simulation.is_equal(one_step_simulation_2))

        time_course_simulation_2 = copy.deepcopy(time_course_simulation)
        self.assertTrue(time_course_simulation.is_equal(time_course_simulation_2))
        time_course_simulation_2.initial_time = -1.
        self.assertFalse(time_course_simulation.is_equal(time_course_simulation_2))

        task2 = copy.deepcopy(task)
        self.assertTrue(task.is_equal(task2))
        task2.id = None
        self.assertFalse(task.is_equal(task2))

        var = copy.deepcopy(report.data_sets[0].data_generator.variables[0])
        var2 = copy.deepcopy(var)
        self.assertTrue(var.is_equal(var2))
        var2.target = None
        self.assertFalse(var.is_equal(var2))

        data_generator = copy.deepcopy(report.data_sets[0].data_generator)
        data_generator_2 = copy.deepcopy(data_generator)
        self.assertTrue(data_generator.is_equal(data_generator_2))
        data_generator_2.variables = []
        self.assertFalse(data_generator.is_equal(data_generator_2))

        data_set = copy.deepcopy(report.data_sets[0])
        data_set_2 = copy.deepcopy(data_set)
        self.assertTrue(data_set.is_equal(data_set_2))
        data_set_2.label = None
        self.assertFalse(data_set.is_equal(data_set_2))

        report2 = copy.deepcopy(report)
        self.assertTrue(report.is_equal(report2))
        report2.data_sets = []
        self.assertFalse(report.is_equal(report2))

        curve = copy.deepcopy(plot2d.curves[0])
        curve2 = copy.deepcopy(curve)
        self.assertTrue(curve.is_equal(curve2))
        curve2.x_scale = None
        self.assertFalse(curve.is_equal(curve2))

        surface = copy.deepcopy(plot3d.surfaces[1])
        surface2 = copy.deepcopy(surface)
        self.assertTrue(surface.is_equal(surface2))
        surface2.z_data_generator = None
        self.assertFalse(surface.is_equal(surface2))

        plot2d_2 = copy.deepcopy(plot2d)
        self.assertTrue(plot2d.is_equal(plot2d_2))
        plot2d_2.curves = []
        self.assertFalse(plot2d.is_equal(plot2d_2))

        plot3d_2 = copy.deepcopy(plot3d)
        self.assertTrue(plot3d.is_equal(plot3d_2))
        plot3d_2.name = None
        self.assertFalse(plot3d.is_equal(plot3d_2))

        document_2 = copy.deepcopy(document)
        self.assertTrue(document.is_equal(document_2))
        document_2.models = []
        self.assertFalse(document.is_equal(document_2))
    def _build_sed_doc(self, algorithm=None):
        if algorithm is None:
            algorithm = sedml_data_model.Algorithm(
                kisao_id='KISAO_0000088',
                changes=[
                    sedml_data_model.AlgorithmParameterChange(
                        kisao_id='KISAO_0000211',
                        new_value='1e-10',
                    ),
                ],
            )

        doc = sedml_data_model.SedDocument()
        doc.models.append(sedml_data_model.Model(
            id='model_1',
            source='model_1.xml',
            language=sedml_data_model.ModelLanguage.SBML.value,
            changes=[],
        ))
        doc.simulations.append(sedml_data_model.UniformTimeCourseSimulation(
            id='sim_1_time_course',
            algorithm=algorithm,
            initial_time=0.,
            output_start_time=0.1,
            output_end_time=0.2,
            number_of_points=20,
        ))
        doc.tasks.append(sedml_data_model.Task(
            id='task_1',
            model=doc.models[0],
            simulation=doc.simulations[0],
        ))
        doc.data_generators.append(sedml_data_model.DataGenerator(
            id='data_gen_time',
            variables=[
                sedml_data_model.Variable(
                    id='var_time',
                    symbol=sedml_data_model.Symbol.time,
                    task=doc.tasks[0],
                ),
            ],
            math='var_time',
        ))
        doc.data_generators.append(sedml_data_model.DataGenerator(
            id='data_gen_BE',
            variables=[
                sedml_data_model.Variable(
                    id='var_BE',
                    target="/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='BE']",
                    target_namespaces=self.NAMESPACES,
                    task=doc.tasks[0],
                ),
            ],
            math='var_BE',
        ))
        doc.data_generators.append(sedml_data_model.DataGenerator(
            id='data_gen_Cdh1',
            variables=[
                sedml_data_model.Variable(
                    id='var_Cdh1',
                    target='/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id="Cdh1"]',
                    target_namespaces=self.NAMESPACES,
                    task=doc.tasks[0],
                ),
            ],
            math='var_Cdh1',
        ))
        doc.data_generators.append(sedml_data_model.DataGenerator(
            id='data_gen_Cdc20',
            variables=[
                sedml_data_model.Variable(
                    id='var_Cdc20',
                    target="/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='Cdc20']",
                    target_namespaces=self.NAMESPACES,
                    task=doc.tasks[0],
                ),
            ],
            math='var_Cdc20',
        ))
        doc.outputs.append(sedml_data_model.Report(
            id='report_1',
            data_sets=[
                sedml_data_model.DataSet(id='data_set_time', label='Time', data_generator=doc.data_generators[0]),
                sedml_data_model.DataSet(id='data_set_BE', label='BE', data_generator=doc.data_generators[1]),
                sedml_data_model.DataSet(id='data_set_Cdh1', label='Cdh1', data_generator=doc.data_generators[2]),
                sedml_data_model.DataSet(id='data_set_Cdc20', label='Cdc20', data_generator=doc.data_generators[3]),
            ],
        ))

        append_all_nested_children_to_doc(doc)

        return doc
    def test_exec_sed_task_errors(self):
        with mock.patch.dict('os.environ', {'ALGORITHM_SUBSTITUTION_POLICY': 'NONE'}):
            task = sedml_data_model.Task()
            task.model = sedml_data_model.Model(id='model')
            task.model.source = os.path.join(self.dirname, 'valid-model.xml')
            with open(task.model.source, 'w') as file:
                file.write('<?xml version="1.0" encoding="UTF-8" standalone="no"?>')
                file.write('<sbml2 xmlns="http://www.sbml.org/sbml/level2/version4" level="2" version="4">')
                file.write('  <model id="model">')
                file.write('  </model>')
                file.write('</sbml2>')
            task.model.language = sedml_data_model.ModelLanguage.SBML
            task.model.changes = []
            task.simulation = sedml_data_model.UniformTimeCourseSimulation(
                id='simulation',
                algorithm=sedml_data_model.Algorithm(kisao_id='KISAO_0000448'),
                initial_time=-10.,
                output_start_time=10.,
                output_end_time=20.1,
                number_of_points=10,
            )

            variables = []

            with self.assertRaisesRegex(ValueError, 'could not be imported'):
                core.exec_sed_task(task, variables, log=TaskLog())
            task.model.source = os.path.join(os.path.dirname(__file__), 'fixtures', 'BIOMD0000000297.edited', 'ex1', 'BIOMD0000000297.xml')

            with self.assertRaisesRegex(AlgorithmCannotBeSubstitutedException, 'Algorithms cannot be substituted'):
                core.exec_sed_task(task, variables, log=TaskLog())
            task.simulation.algorithm.kisao_id = 'KISAO_0000029'
            task.simulation.algorithm.changes = [
                sedml_data_model.AlgorithmParameterChange(kisao_id='KISAO_0000531'),
            ]

            with self.assertRaisesRegex(NotImplementedError, 'is not supported. Parameter must'):
                core.exec_sed_task(task, variables, log=TaskLog())
            task.simulation.algorithm.changes[0].kisao_id = 'KISAO_0000488'
            task.simulation.algorithm.changes[0].new_value = 'abc'

            with self.assertRaisesRegex(ValueError, 'not a valid integer'):
                core.exec_sed_task(task, variables, log=TaskLog())
            task.simulation.algorithm.changes[0].new_value = '10'

            with self.assertRaisesRegex(NotImplementedError, 'is not supported. Initial time must be >= 0'):
                core.exec_sed_task(task, variables, log=TaskLog())
            task.simulation.initial_time = 0.

            with self.assertRaisesRegex(NotImplementedError, 'must specify an integer'):
                core.exec_sed_task(task, variables, log=TaskLog())
            task.simulation.output_end_time = 20.
            variables = [
                sedml_data_model.Variable(id='var_1', symbol='unsupported', task=task)
            ]

            with self.assertRaisesRegex(NotImplementedError, 'Symbols must be'):
                core.exec_sed_task(task, variables, log=TaskLog())
            variables = [
                sedml_data_model.Variable(id='var_1', symbol=sedml_data_model.Symbol.time, task=task),
                sedml_data_model.Variable(id='var_2', target='/invalid:target', target_namespaces={'invalid': 'invalid'}, task=task),
            ]

            with self.assertRaisesRegex(ValueError, 'XPaths must reference unique objects.'):
                core.exec_sed_task(task, variables, log=TaskLog())
            variables = [
                sedml_data_model.Variable(id='var_1', symbol=sedml_data_model.Symbol.time, task=task),
                sedml_data_model.Variable(
                    id='BE',
                    target="/sbml:sbml/sbml:model/sbml:listOfReactions/sbml:reaction[@id='R1']",
                    target_namespaces=self.NAMESPACES,
                    task=task
                ),
            ]

            with self.assertRaisesRegex(ValueError, 'Targets must have'):
                core.exec_sed_task(task, variables, log=TaskLog())
            variables = [
                sedml_data_model.Variable(
                    id='time',
                    symbol=sedml_data_model.Symbol.time,
                    task=task
                ),
                sedml_data_model.Variable(
                    id='BE',
                    target="/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='BE']",
                    target_namespaces=self.NAMESPACES,
                    task=task,
                ),
                sedml_data_model.Variable(
                    id='Cdh1',
                    target='/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id="Cdh1"]',
                    target_namespaces=self.NAMESPACES,
                    task=task,
                ),
                sedml_data_model.Variable(
                    id='Cdc20',
                    target="/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='Cdc20']",
                    target_namespaces=self.NAMESPACES,
                    task=task,
                ),
            ]

            task.simulation.algorithm.kisao_id = 'KISAO_0000088'
            task.simulation.algorithm.changes[0].kisao_id = 'KISAO_0000211'
            task.simulation.algorithm.changes[0].new_value = '1e-10'
            variable_results, _ = core.exec_sed_task(task, variables, log=TaskLog())

            self.assertTrue(sorted(variable_results.keys()), sorted([var.id for var in variables]))
            self.assertEqual(variable_results[variables[0].id].shape, (task.simulation.number_of_points + 1,))
            numpy.testing.assert_allclose(
                variable_results['time'],
                numpy.linspace(task.simulation.output_start_time, task.simulation.output_end_time, task.simulation.number_of_points + 1),
            )

        # algorithm substitution
        task = sedml_data_model.Task(
            model=sedml_data_model.Model(
                source=os.path.join(os.path.dirname(__file__), 'fixtures', 'BIOMD0000000297.edited', 'ex1', 'BIOMD0000000297.xml'),
                language=sedml_data_model.ModelLanguage.SBML.value,
                changes=[],
            ),
            simulation=sedml_data_model.UniformTimeCourseSimulation(
                algorithm=sedml_data_model.Algorithm(
                    kisao_id='KISAO_0000088',
                    changes=[
                        sedml_data_model.AlgorithmParameterChange(
                            kisao_id='KISAO_0000211',
                            new_value='1e-10',
                        ),
                    ],
                ),
                initial_time=0.,
                output_start_time=10.,
                output_end_time=20.,
                number_of_points=20,
            ),
        )

        variables = []

        task.simulation.algorithm.changes[0].new_value = 'not a number'
        with mock.patch.dict('os.environ', {'ALGORITHM_SUBSTITUTION_POLICY': 'NONE'}):
            with self.assertRaisesRegex(ValueError, 'is not a valid'):
                core.exec_sed_task(task, variables, log=TaskLog())

        with mock.patch.dict('os.environ', {'ALGORITHM_SUBSTITUTION_POLICY': 'SIMILAR_VARIABLES'}):
            with self.assertWarnsRegex(BioSimulatorsWarning, 'Unsuported value'):
                core.exec_sed_task(task, variables, log=TaskLog())

        task.simulation.algorithm.changes[0].kisao_id = 'KISAO_0000531'
        with mock.patch.dict('os.environ', {'ALGORITHM_SUBSTITUTION_POLICY': 'NONE'}):
            with self.assertRaisesRegex(NotImplementedError, 'is not supported'):
                core.exec_sed_task(task, variables, log=TaskLog())

        with mock.patch.dict('os.environ', {'ALGORITHM_SUBSTITUTION_POLICY': 'SIMILAR_VARIABLES'}):
            with self.assertWarnsRegex(BioSimulatorsWarning, 'was ignored because it is not supported'):
                core.exec_sed_task(task, variables, log=TaskLog())
    def test_exec_sed_task_with_model_changes(self):
        task = sedml_data_model.Task(
            model=sedml_data_model.Model(
                source=os.path.join(os.path.dirname(__file__), 'fixtures', 'BIOMD0000000297.edited', 'ex1', 'BIOMD0000000297.xml'),
                language=sedml_data_model.ModelLanguage.SBML.value,
                changes=[
                    sedml_data_model.ModelAttributeChange(
                        target="/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='kswe_prime']",
                        target_namespaces=self.NAMESPACES,
                        new_value=None,
                    ),
                ],
            ),
            simulation=sedml_data_model.UniformTimeCourseSimulation(
                algorithm=sedml_data_model.Algorithm(
                    kisao_id='KISAO_0000088',
                ),
                initial_time=0.,
                output_start_time=0.,
                output_end_time=20.,
                number_of_points=20,
            ),
        )

        variables = [
            sedml_data_model.Variable(
                id='kswe_prime',
                target="/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='kswe_prime']",
                target_namespaces=self.NAMESPACES,
                task=task,
            ),
        ]

        model, errors = gillespy2.import_SBML(task.model.source)
        for sbml_id in model.get_all_species().keys():
            if sbml_id in ['kswe', 'kmih', 'IEin', 'Cdh1in', 'Mih1', 'Mcmin', 'SBFin', 'BUD', 'flag', 'Swe1T']:
                target = "/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='{}']".format(sbml_id)
            else:
                target = "/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='{}']".format(sbml_id)
            task.model.changes.append(sedml_data_model.ModelAttributeChange(
                target=target,
                target_namespaces=self.NAMESPACES,
                new_value=None,
            ))
            variables.append(sedml_data_model.Variable(
                id=sbml_id,
                target=target,
                target_namespaces=self.NAMESPACES,
                task=task,
            ))

        preprocessed_task = core.preprocess_sed_task(task, variables)

        task.model.changes = []
        results, _ = core.exec_sed_task(task, variables, preprocessed_task=preprocessed_task)
        numpy.testing.assert_allclose(results['kswe_prime'][0], 2.)
        numpy.testing.assert_allclose(results['Clg'][0], 0.053600963)

        results_2, _ = core.exec_sed_task(task, variables, preprocessed_task=preprocessed_task)
        for variable in variables:
            numpy.testing.assert_allclose(results_2[variable.id], results[variable.id])

        task.simulation.output_end_time /= 2
        task.simulation.number_of_points = int(task.simulation.number_of_points / 2)
        results_2a, _ = core.exec_sed_task(task, variables, preprocessed_task=preprocessed_task)
        for sbml_id in model.get_all_species().keys():
            if sbml_id in ['kswe', 'kmih', 'IEin', 'Cdh1in', 'Mih1', 'Mcmin', 'SBFin', 'BUD', 'flag', 'Swe1T']:
                target = "/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='{}']".format(sbml_id)
            else:
                target = "/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='{}']".format(sbml_id)
            task.model.changes.append(sedml_data_model.ModelAttributeChange(
                target=target,
                target_namespaces=self.NAMESPACES,
                new_value=results_2a[sbml_id][-1],
            ))
        results_2b, _ = core.exec_sed_task(task, variables, preprocessed_task=preprocessed_task)
        for variable in variables:
            numpy.testing.assert_allclose(results_2b[variable.id], results[variable.id]
                                          [-(task.simulation.number_of_points + 1):], rtol=1e-3)

        task.model.changes = [
            sedml_data_model.ModelAttributeChange(
                target="/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='kswe_prime']",
                target_namespaces=self.NAMESPACES,
                new_value=3.,
            ),
            sedml_data_model.ModelAttributeChange(
                target="/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='Clg']",
                target_namespaces=self.NAMESPACES,
                new_value=0.0001,
            ),
        ]

        results_2, _ = core.exec_sed_task(task, variables, preprocessed_task=preprocessed_task)
        numpy.testing.assert_allclose(results_2['kswe_prime'][0], 3.)
        numpy.testing.assert_allclose(results_2['Clg'][0], 0.0001)

        task.model.changes[0].new_value = '0.3'
        task.model.changes[1].new_value = '0.0003'

        results_2, _ = core.exec_sed_task(task, variables, preprocessed_task=preprocessed_task)
        numpy.testing.assert_allclose(results_2['kswe_prime'][0], 0.3)
        numpy.testing.assert_allclose(results_2['Clg'][0], 0.0003)

        task.model.changes[0].target = '/sbml:sbml/sbml:model'
        with self.assertRaisesRegex(ValueError, 'cannot be changed'):
            preprocessed_task = core.preprocess_sed_task(task, variables)
    def test_write_read(self):
        shutil.copy(
            os.path.join(os.path.dirname(__file__), '..', 'fixtures',
                         'BIOMD0000000075.xml'),
            os.path.join(self.tmp_dir, 'model.sbml'))

        model1 = data_model.Model(
            id='model1',
            name='Model1',
            source='model.sbml',
            language='urn:sedml:language:sbml',
            changes=[
                data_model.ModelAttributeChange(
                    target='/sbml:sbml/sbml:model[id=\'a\']/@id',
                    new_value='234'),
                data_model.ModelAttributeChange(
                    target='/sbml:sbml/sbml:model[id=\'b\']/@id',
                    new_value='432'),
                data_model.AddElementModelChange(
                    target=
                    '/sbml:sbml/sbml:model[id=\'b\']/sbml:listOfParameters',
                    new_elements=
                    '<sbml:parameter xmlns:sbml="http://www.sbml.org/sbml/level2/version3" id="new_parameter" value="1.0"/>'
                ),
                data_model.AddElementModelChange(
                    target=
                    '/sbml:sbml/sbml:model[id=\'b\']/sbml:listOfParameters',
                    new_elements=
                    '<parameter id="new_parameter_1" value="1.0"/><parameter id="new_parameter_2" value="1.0"/>'
                ),
                data_model.ReplaceElementModelChange(
                    target=
                    '/sbml:sbml/sbml:model[id=\'b\']/sbml:listOfParameters/sbml:parameter[@id=\'p1\']',
                    new_elements='<parameter id="p1" value="1.0"/>'),
                data_model.ReplaceElementModelChange(
                    target=
                    '/sbml:sbml/sbml:model[id=\'b\']/sbml:listOfParameters/sbml:parameter[@id=\'p1\']',
                    new_elements=
                    '<parameter id="p1" value="1.0"/><parameter id="p1" value="1.0"/>'
                ),
                data_model.RemoveElementModelChange(
                    target=
                    '/sbml:sbml/sbml:model[id=\'b\']/sbml:listOfParameters/sbml:parameter[@id=\'p1\']',
                ),
                data_model.ComputeModelChange(
                    target=
                    '/sbml:sbml/sbml:model[id=\'b\']/sbml:listOfParameters/sbml:parameter[@id=\'p1\']',
                    parameters=[
                        data_model.Parameter(id='a', value=1.5),
                        data_model.Parameter(id='b', value=2.25),
                    ],
                    variables=[
                        data_model.Variable(
                            id='x',
                            target='variable_target_x',
                        ),
                        data_model.Variable(
                            id='y',
                            target='variable_target_y',
                        ),
                    ],
                    math='a * x + b * y',
                ),
            ],
        )
        for var in model1.changes[-1].variables:
            var.model = model1

        model2 = data_model.Model(
            id='model2',
            name='Model2',
            source='model.sbml',
            language='urn:sedml:language:sbml',
            changes=[
                data_model.ModelAttributeChange(
                    target='/sbml:sbml/sbml:model[id=\'a\']/@id',
                    new_value='234',
                ),
                data_model.ModelAttributeChange(
                    target='/sbml:sbml/sbml:model[id=\'b\']/@id',
                    new_value='432'),
            ],
        )

        ss_simulation = data_model.SteadyStateSimulation(
            id='simulation1',
            name='Simulation1',
            algorithm=data_model.Algorithm(
                kisao_id='KISAO_0000019',
                changes=[
                    data_model.AlgorithmParameterChange(
                        kisao_id='KISAO_0000211', new_value='1.234'),
                ]),
        )

        one_step_simulation = data_model.OneStepSimulation(
            id='simulation2',
            name='Simulation2',
            algorithm=data_model.Algorithm(
                kisao_id='KISAO_0000019',
                changes=[
                    data_model.AlgorithmParameterChange(
                        kisao_id='KISAO_0000211', new_value='1.234'),
                ]),
            step=10.)

        time_course_simulation = data_model.UniformTimeCourseSimulation(
            id='simulation3',
            name='Simulation3',
            algorithm=data_model.Algorithm(
                kisao_id='KISAO_0000019',
                changes=[
                    data_model.AlgorithmParameterChange(
                        kisao_id='KISAO_0000209', new_value='1.234'),
                    data_model.AlgorithmParameterChange(
                        kisao_id='KISAO_0000211', new_value='4.321'),
                ]),
            initial_time=10.,
            output_start_time=20.,
            output_end_time=30,
            number_of_steps=10)

        task1 = data_model.Task(id='task1',
                                name='Task1',
                                model=model1,
                                simulation=time_course_simulation)
        task2 = data_model.Task(id='task2',
                                name='Task2',
                                model=model2,
                                simulation=time_course_simulation)
        task3 = data_model.RepeatedTask(
            id='task3',
            name='Task3',
            reset_model_for_each_iteration=True,
            changes=[],
            sub_tasks=[
                data_model.SubTask(task=task1, order=1),
                data_model.SubTask(task=task2, order=2),
            ],
            ranges=[
                data_model.UniformRange(
                    id='range1',
                    start=10.,
                    end=20.,
                    number_of_steps=4,
                    type=data_model.UniformRangeType.linear),
                data_model.UniformRange(id='range2',
                                        start=10.,
                                        end=20.,
                                        number_of_steps=4,
                                        type=data_model.UniformRangeType.log),
                data_model.VectorRange(id='range3',
                                       values=[3., 5., 7., 11., 13.]),
            ],
        )
        task3.ranges.append(
            data_model.FunctionalRange(
                id='range4',
                range=task3.ranges[0],
                parameters=[
                    data_model.Parameter(
                        id='x2',
                        value=2.0,
                    ),
                ],
                variables=[
                    data_model.Variable(
                        id='y2',
                        model=model1,
                        target=
                        "/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:Parameter[@id='param_1']",
                    ),
                ],
                math='{} * {} + {}'.format(task3.ranges[0].id, 'x2', 'y2'),
            ), )
        task3.range = task3.ranges[1]
        task3.changes.append(
            data_model.SetValueComputeModelChange(
                model=model1,
                target=
                "/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='p1']",
                range=task3.ranges[0],
                parameters=[],
                variables=[],
                math='range1',
            ), )
        task3.changes.append(
            data_model.SetValueComputeModelChange(
                model=model1,
                target=
                "/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='p1']",
                range=task3.ranges[0],
                parameters=[],
                variables=[
                    data_model.Variable(
                        id='range1_var1',
                        model=model1,
                        target=
                        "/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='p1']",
                    )
                ],
                math='range1 * range1_var1',
            ), )
        task3.changes.append(
            data_model.SetValueComputeModelChange(
                model=model1,
                target=
                "/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='p1']",
                range=task3.ranges[0],
                parameters=[
                    data_model.Parameter(id='range1_p1', value=2.5),
                ],
                variables=[],
                math='range1 * range1_p1',
            ), )

        report = data_model.Report(
            id='report1',
            name='Report1',
            data_sets=[
                data_model.DataSet(
                    id='dataset1',
                    name='Dataset1',
                    label='Dataset-1',
                    data_generator=data_model.DataGenerator(
                        id='dataGen1',
                        name='DataGen1',
                        variables=[
                            data_model.Variable(
                                id='DataGenVar1',
                                name='DataGenVar1',
                                target='/sbml:sbml/sbml:model/@id',
                                task=task1,
                            )
                        ],
                        parameters=[
                            data_model.Parameter(id='DataGenParam1',
                                                 name='DataGenParam1',
                                                 value=2.)
                        ],
                        math='DataGenVar1 - DataGenParam1',
                    )),
            ],
        )

        plot2d = data_model.Plot2D(
            id='plot2d',
            name='Plot2D',
            curves=[
                data_model.Curve(
                    id='curve1',
                    name='Curve1',
                    x_scale=data_model.AxisScale.linear,
                    y_scale=data_model.AxisScale.log,
                    x_data_generator=data_model.DataGenerator(
                        id='xDataGen2',
                        name='XDataGen2',
                        variables=[
                            data_model.Variable(id='xDataGenVar1',
                                                name='XDataGenVar1',
                                                symbol='urn:sedml:symbol:time',
                                                task=task2)
                        ],
                        parameters=[
                            data_model.Parameter(id='xDataGenParam1',
                                                 name='XDataGenParam1',
                                                 value=2.)
                        ],
                        math='xDataGenVar1 * xDataGenParam1',
                    ),
                    y_data_generator=data_model.DataGenerator(
                        id='yDataGen3',
                        name='yDataGen3',
                        variables=[
                            data_model.Variable(
                                id='xDataGenVar2',
                                name='XDataGenVar1',
                                target='/sbml:sbml/sbml:model/@id',
                                task=task2,
                            )
                        ],
                        parameters=[
                            data_model.Parameter(id='xDataGenParam2',
                                                 name='XDataGenParam1',
                                                 value=2.)
                        ],
                        math='xDataGenVar2 * xDataGenParam2',
                    ),
                ),
                data_model.Curve(
                    id='curve2',
                    name='Curve2',
                    x_scale=data_model.AxisScale.linear,
                    y_scale=data_model.AxisScale.log,
                    x_data_generator=data_model.DataGenerator(
                        id='yDataGen4',
                        name='yDataGen4',
                        variables=[
                            data_model.Variable(
                                id='yDataGenVar1',
                                target='/sbml:sbml/sbml:model/@id',
                                task=task1,
                            )
                        ],
                        parameters=[
                            data_model.Parameter(id='YDataGenParam1', value=2.)
                        ],
                        math='yDataGenVar1 + YDataGenParam1',
                    ),
                    y_data_generator=data_model.DataGenerator(
                        id='yDataGen5',
                        name='yDataGen5',
                        variables=[
                            data_model.Variable(
                                id='yDataGenVar2',
                                target='/sbml:sbml/sbml:model/@id',
                                task=task1,
                            )
                        ],
                        parameters=[
                            data_model.Parameter(id='YDataGenParam2',
                                                 value=2.),
                        ],
                        math='yDataGenVar2 + YDataGenParam2',
                    ),
                ),
            ])

        plot3d = data_model.Plot3D(
            id='plot3d',
            name='Plot3D',
            surfaces=[
                data_model.Surface(
                    id='surface1',
                    name='Surface1',
                    x_scale=data_model.AxisScale.linear,
                    y_scale=data_model.AxisScale.log,
                    z_scale=data_model.AxisScale.linear,
                    x_data_generator=data_model.DataGenerator(
                        id='xDataGen6',
                        name='XDataGen6',
                        variables=[
                            data_model.Variable(
                                id='xDataGenVar3',
                                name='XDataGenVar2',
                                target='/sbml:sbml/sbml:model/@id',
                                task=task2,
                            )
                        ],
                        parameters=[
                            data_model.Parameter(id='xDataGenParam3',
                                                 name='XDataGenParam1',
                                                 value=2.)
                        ],
                        math='xDataGenVar3 * xDataGenParam3',
                    ),
                    y_data_generator=data_model.DataGenerator(
                        id='xDataGen8',
                        name='XDataGen8',
                        variables=[
                            data_model.Variable(
                                id='xDataGenVar4',
                                name='XDataGenVar2',
                                target='/sbml:sbml/sbml:model/@id',
                                task=task2,
                            )
                        ],
                        parameters=[
                            data_model.Parameter(id='xDataGenParam4',
                                                 name='XDataGenParam1',
                                                 value=2.)
                        ],
                        math='xDataGenVar4 * xDataGenParam4',
                    ),
                    z_data_generator=data_model.DataGenerator(
                        id='xDataGen9',
                        name='XDataGen9',
                        variables=[
                            data_model.Variable(
                                id='xDataGenVar5',
                                name='XDataGenVar2',
                                target='/sbml:sbml/sbml:model/@id',
                                task=task2,
                            )
                        ],
                        parameters=[
                            data_model.Parameter(id='xDataGenParam5',
                                                 name='XDataGenParam1',
                                                 value=2.)
                        ],
                        math='xDataGenVar5 * xDataGenParam5',
                    ),
                ),
                data_model.Surface(
                    id='surface2',
                    name='Surface2',
                    x_scale=data_model.AxisScale.linear,
                    y_scale=data_model.AxisScale.log,
                    z_scale=data_model.AxisScale.log,
                    x_data_generator=data_model.DataGenerator(
                        id='xDataGen10',
                        name='XDataGen10',
                        variables=[
                            data_model.Variable(
                                id='xDataGenVar6',
                                name='XDataGenVar2',
                                target='/sbml:sbml/sbml:model/@id',
                                task=task2,
                            )
                        ],
                        parameters=[
                            data_model.Parameter(id='xDataGenParam6',
                                                 name='XDataGenParam1',
                                                 value=2.)
                        ],
                        math='xDataGenVar6 * xDataGenParam6',
                    ),
                    y_data_generator=data_model.DataGenerator(
                        id='xDataGen11',
                        name='XDataGen11',
                        variables=[
                            data_model.Variable(
                                id='xDataGenVar7',
                                name='XDataGenVar2',
                                target='/sbml:sbml/sbml:model/@id',
                                task=task2,
                            )
                        ],
                        parameters=[
                            data_model.Parameter(id='xDataGenParam7',
                                                 name='XDataGenParam1',
                                                 value=2.)
                        ],
                        math='xDataGenVar7 * xDataGenParam7',
                    ),
                    z_data_generator=data_model.DataGenerator(
                        id='xDataGen12',
                        name='XDataGen12',
                        variables=[
                            data_model.Variable(
                                id='xDataGenVar8',
                                name='XDataGenVar2',
                                target='/sbml:sbml/sbml:model/@id',
                                task=task2,
                            )
                        ],
                        parameters=[
                            data_model.Parameter(id='xDataGenParam8',
                                                 name='XDataGenParam1',
                                                 value=2.)
                        ],
                        math='xDataGenVar8 * xDataGenParam8',
                    ),
                ),
            ])

        now = datetime.datetime(2020,
                                1,
                                2,
                                1,
                                2,
                                3,
                                tzinfo=dateutil.tz.tzutc())
        document = data_model.SedDocument(
            level=1,
            version=3,
            models=[model1],
            simulations=[time_course_simulation],
            tasks=[task1],
            data_generators=([d.data_generator for d in report.data_sets]),
            outputs=[report],
            metadata=Metadata(
                description="description",
                tags=['tag-1', 'tag-2'],
                authors=[
                    Person(given_name='first',
                           other_name='middle',
                           family_name='last'),
                ],
                references=ExternalReferences(
                    identifiers=None,
                    citations=[
                        Citation(title='creative title',
                                 authors='Author-1 & Author-2',
                                 journal='major journal',
                                 volume='10',
                                 issue='20',
                                 pages='30-40',
                                 year=2020,
                                 identifiers=[
                                     Identifier(
                                         namespace="doi",
                                         id='10.0/1.0',
                                         url="https://doi.org/10.0/1.0"),
                                 ])
                    ]),
                license=OntologyTerm(
                    namespace='SPDX',
                    id='MIT',
                    url='https://spdx.org/licenses/MIT.html',
                ),
                created=now,
                updated=now,
            ),
        )
        self._set_target_namespaces(document)

        filename = os.path.join(self.tmp_dir, 'test.xml')
        io.SedmlSimulationWriter().run(document, filename)

        document2 = io.SedmlSimulationReader().run(filename)
        self.assertTrue(document.is_equal(document2))

        document = data_model.SedDocument(
            level=1,
            version=3,
            models=[model1, model2],
            simulations=[
                ss_simulation, one_step_simulation, time_course_simulation
            ],
            tasks=[task1, task2, task3],
            data_generators=([d.data_generator for d in report.data_sets] +
                             [c.x_data_generator for c in plot2d.curves] +
                             [c.y_data_generator for c in plot2d.curves] +
                             [s.x_data_generator for s in plot3d.surfaces] +
                             [s.y_data_generator for s in plot3d.surfaces] +
                             [s.z_data_generator for s in plot3d.surfaces]),
            outputs=[report, plot2d, plot3d],
            metadata=Metadata(
                description="description",
                license=OntologyTerm(
                    namespace='SPDX',
                    id='MIT',
                    url='https://spdx.org/licenses/MIT.html',
                ),
            ),
        )
        self._set_target_namespaces(document)

        filename = os.path.join(self.tmp_dir, 'test.xml')
        io.SedmlSimulationWriter().run(document, filename)

        document2 = io.SedmlSimulationReader().run(filename)
        self.assertTrue(document.is_equal(document2))

        document2.metadata.license.namespace = None
        document2.metadata.license.url = None
        io.SedmlSimulationWriter().run(document2, filename)
        document3 = io.SedmlSimulationReader().run(filename)
        self.assertTrue(document2.is_equal(document3))

        document3.metadata = None
        io.SedmlSimulationWriter().run(document3, filename)
        document4 = io.SedmlSimulationReader().run(filename)
        self.assertTrue(document4.is_equal(document3))

        document.models[0].changes[
            2].new_elements = '<parameter id="new_parameter" value="1.0/>'
        document.models[0].changes[
            4].new_elements = '<parameter id="new_parameter" value="1.0"/>'
        with self.assertRaisesRegex(ValueError, 'invalid XML'):
            io.SedmlSimulationWriter().run(document, filename)

        document.models[0].changes[
            2].new_elements = '<parameter id="new_parameter" value="1.0"/>'
        document.models[0].changes[
            4].new_elements = '<parameter id="new_parameter" value="1.0/>'
        with self.assertRaisesRegex(ValueError, 'invalid XML'):
            io.SedmlSimulationWriter().run(document, filename)