diff --git a/spectrafit/plugins/notebook.py b/spectrafit/plugins/notebook.py index 6a40a0639..21ba5dd5b 100644 --- a/spectrafit/plugins/notebook.py +++ b/spectrafit/plugins/notebook.py @@ -249,6 +249,29 @@ def plot_dataframe(self, args_plot: PlotAPI, df: pd.DataFrame) -> None: ) fig.show() + def plot_global_fit(self, args_plot: PlotAPI, df: pd.DataFrame) -> None: + """Plot the global dataframe according to the PlotAPI arguments. + + Args: + args_plot (PlotAPI): PlotAPI object for the settings of the plot. + df (pd.DataFrame): Dataframe to plot. + """ + for i in range( + 1, + sum(1 for _col in df.columns if _col.startswith(ColumnNamesAPI().fit)) + 1, + ): + _col = [col for col in df.columns if col.endswith(str(i))] + _col.append(ColumnNamesAPI().energy) + _df = df[_col] + _df = _df.rename( + columns={ + f"{ColumnNamesAPI().intensity}_{i}": ColumnNamesAPI().intensity, + f"{ColumnNamesAPI().fit}_{i}": ColumnNamesAPI().fit, + f"{ColumnNamesAPI().residual}_{i}": ColumnNamesAPI().residual, + } + ) + self.plot_2dataframes(args_plot, _df) + def plot_metric( self, args_plot: PlotAPI, @@ -385,7 +408,7 @@ def export_df(self, df: pd.DataFrame, args: FnameAPI) -> None: and suffix. """ df.to_csv( - self.fname2Path( + self.fname2path( fname=args.fname, prefix=args.prefix, suffix=args.suffix, @@ -403,7 +426,7 @@ def export_report(self, report: Dict[Any, Any], args: FnameAPI) -> None: and suffix. """ with open( - self.fname2Path( + self.fname2path( fname=args.fname, prefix=args.prefix, suffix=args.suffix, @@ -414,7 +437,7 @@ def export_report(self, report: Dict[Any, Any], args: FnameAPI) -> None: tomli_w.dump(report, f) @staticmethod - def fname2Path( + def fname2path( fname: str, suffix: str, prefix: Optional[str] = None, @@ -932,7 +955,10 @@ def plot_preprocessed_df(self) -> None: def plot_fit_df(self) -> None: """Plot the fit.""" - self.plot_2dataframes(args_plot=self.args_plot, df_1=self.df_fit) + if self.global_ == 1: + self.plot_global_fit(args_plot=self.args_plot, df=self.df_fit) + else: + self.plot_2dataframes(args_plot=self.args_plot, df_1=self.df_fit) def plot_current_metric( self, diff --git a/spectrafit/plugins/test/test_notebook.py b/spectrafit/plugins/test/test_notebook.py index 50b7e0408..14985470e 100644 --- a/spectrafit/plugins/test/test_notebook.py +++ b/spectrafit/plugins/test/test_notebook.py @@ -6,6 +6,7 @@ from typing import Any from typing import Dict from typing import List +from typing import Union from unittest import mock import pandas as pd @@ -45,6 +46,15 @@ def dataframe_2_fixture() -> pd.DataFrame: ) +@pytest.fixture(name="dataframe_global") +def dataframe_global_fixture() -> pd.DataFrame: + """Create a DataFrameDisplay object.""" + return pd.read_csv( + "https://github.com/Anselmoo/spectrafit/blob/" + "9cf51ce020925228be26468763466c7fd91fedf0/Examples/example_6_fit.csv?raw=true" + ) + + @pytest.fixture(name="x_column") def x_column_fixture(dataframe: pd.DataFrame) -> str: """Create a x_column object.""" @@ -138,7 +148,7 @@ def class_spectrafit_fixture( dataframe_2: pd.DataFrame, initial_model: List[Dict[str, Dict[str, Dict[str, Any]]]], tmp_path: Path, -) -> Dict[Any, Any]: +) -> Dict[str, Union[SpectraFitNotebook, Path]]: """Create a SpectraFitNotebook object.""" _df = pd.DataFrame(data={"x": [1, 2, 3], "y": [1, 2, 3]}) sp = SpectraFitNotebook( @@ -155,6 +165,30 @@ def class_spectrafit_fixture( return {"sp": sp, "tmpdir": tmp_path} +@pytest.fixture(name="class_spectrafit_fit_global") +def class_spectrafit_fixture_fit_global( + dataframe_global: pd.DataFrame, + initial_model: List[Dict[str, Dict[str, Dict[str, Any]]]], + tmp_path: Path, +) -> Dict[str, Union[SpectraFitNotebook, Path]]: + """Create a SpectraFitNotebook object.""" + dataframe_init = pd.read_csv( + "https://github.com/Anselmoo/spectrafit/blob/" + "9cf51ce020925228be26468763466c7fd91fedf0/Examples/data_global.csv?raw=true" + ) + + sp = SpectraFitNotebook( + df=dataframe_init, + x_column="energy", + y_column=["y_1", "y_2", "y_3"], + fname="test", + folder=str(tmp_path), + ) + sp.df_fit = dataframe_global + sp.initial_model = initial_model + return {"sp": sp, "tmpdir": tmp_path} + + @pytest.fixture(name="class_spectrafit_fit") def class_spectrafit_fixture_fit( dataframe: pd.DataFrame, x_column: str, y_column: str, tmp_path: Path @@ -227,6 +261,16 @@ def test_dataframe_plot_4(self, dataframe_2: pd.DataFrame) -> None: ) mock_show.assert_called_once() + def test_dataframe_plot_global(self, dataframe_global: pd.DataFrame) -> None: + """Test global plot.""" + pp = DataFramePlot() + with mock.patch(__plotly_io_show__) as mock_show: + pp.plot_global_fit( + args_plot=PlotAPI(x="Energy", y="Intensity", title="Test"), + df=dataframe_global, + ) + mock_show.assert_called() + def test_dataframe_display_all(dataframe: pd.DataFrame) -> None: """Test the DataFrameDisplay class.""" @@ -270,9 +314,9 @@ def test_export_report(self, dataframe: pd.DataFrame, tmp_path: Path) -> None: def test_static_fname(self) -> None: """Test the static function of generating PathPosixs.""" - assert isinstance(ExportResults.fname2Path(fname="test", suffix="csv"), Path) + assert isinstance(ExportResults.fname2path(fname="test", suffix="csv"), Path) assert isinstance( - ExportResults.fname2Path( + ExportResults.fname2path( fname="test", suffix="csv", folder="tmp", prefix="prefix" ), Path, @@ -350,19 +394,19 @@ def test_export_df(self, class_spectrafit: Dict[Any, Any]) -> None: class_spectrafit["sp"].export_df_org class_spectrafit["sp"].export_df_pre class_spectrafit["sp"].export_df_metric - assert ExportResults.fname2Path( + assert ExportResults.fname2path( folder=class_spectrafit["tmpdir"], fname="test", prefix="act", suffix="csv" ).exists() - assert ExportResults.fname2Path( + assert ExportResults.fname2path( folder=class_spectrafit["tmpdir"], fname="test", prefix="fit", suffix="csv" ).exists() - assert ExportResults.fname2Path( + assert ExportResults.fname2path( folder=class_spectrafit["tmpdir"], fname="test", prefix="org", suffix="csv" ).exists() - assert ExportResults.fname2Path( + assert ExportResults.fname2path( folder=class_spectrafit["tmpdir"], fname="test", prefix="pre", suffix="csv" ).exists() - assert ExportResults.fname2Path( + assert ExportResults.fname2path( folder=class_spectrafit["tmpdir"], fname="test", prefix="metric", @@ -413,6 +457,17 @@ def test_plot_fit( class_spectrafit["sp"].plot_fit_df() mock_show.assert_called_once() + @pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows") + @pytest.mark.webtest + def test_plot_global( + self, + class_spectrafit_fit_global: Dict[Any, Any], + ) -> None: + """Test the plot function for global fitting routine.""" + with mock.patch(__plotly_io_show__) as mock_show: + class_spectrafit_fit_global["sp"].plot_fit_df() + mock_show.assert_called() + def test_display( self, class_spectrafit: Dict[Any, Any], @@ -437,7 +492,7 @@ def test_generate_report( sp.df_fit = dataframe_2 sp.generate_report - assert ExportResults.fname2Path( + assert ExportResults.fname2path( folder=sp.export_args_out.folder, fname="test", suffix="lock", diff --git a/spectrafit/test/test_input.py b/spectrafit/test/test_input.py index 44509dfad..0eb521745 100644 --- a/spectrafit/test/test_input.py +++ b/spectrafit/test/test_input.py @@ -11,6 +11,9 @@ from numpy.testing import assert_almost_equal +BUILTINS_INPUT = "builtins.input" + + class TestCommandLineRunner: """Testing the command line interface.""" @@ -18,7 +21,7 @@ def test_version(self, monkeypatch: Any, script_runner: Any) -> None: """Testing the version command.""" from spectrafit import __version__ - monkeypatch.setattr("builtins.input", lambda _: "y") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "y") ret = script_runner.run( "spectrafit", "_", @@ -32,7 +35,7 @@ def test_version(self, monkeypatch: Any, script_runner: Any) -> None: def test_extended(self, monkeypatch: Any, script_runner: Any) -> None: """Testing the extended command.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -49,7 +52,7 @@ def test_extended(self, monkeypatch: Any, script_runner: Any) -> None: ) def test_extended_verbose(self, monkeypatch: Any, script_runner: Any) -> None: """Testing the extended with verbose command.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -72,7 +75,7 @@ def test_json_input( self, monkeypatch: Any, script_runner: Any, tmp_path: Path ) -> None: """Testing json support.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -95,7 +98,7 @@ def test_yml_input( self, monkeypatch: Any, script_runner: Any, tmp_path: Path ) -> None: """Testing yml support.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -118,7 +121,7 @@ def test_yaml_input( self, monkeypatch: Any, script_runner: Any, tmp_path: Path ) -> None: """Testing yaml support.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -141,7 +144,7 @@ def test_toml_input( self, monkeypatch: Any, script_runner: Any, tmp_path: Path ) -> None: """Testing toml support.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -161,7 +164,7 @@ class TestFileFormatOutput: def test_outputs(self, monkeypatch: Any, script_runner: Any) -> None: """Testing correct number of outputs.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") _ = script_runner.run( "spectrafit", "_", @@ -179,7 +182,7 @@ class TestMoreFeatures: def test_default_options(self, monkeypatch: Any, script_runner: Any) -> None: """Testing verbose support.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -193,7 +196,7 @@ def test_energyrange_e0( self, monkeypatch: Any, script_runner: Any, tmp_path: Path ) -> None: """Testing lower energy range cut.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -214,7 +217,7 @@ def test_energyrange_e1( self, monkeypatch: Any, script_runner: Any, tmp_path: Path ) -> None: """Testing upper energy range cut.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -236,7 +239,7 @@ def test_energyrange_e0e1( self, monkeypatch: Any, script_runner: Any, tmp_path: Path ) -> None: """Testing lower and upper energy range cut.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -264,7 +267,7 @@ def test_energyrange_e0e1( ) def test_all_models(self, monkeypatch: Any, script_runner: Any) -> None: """Testing test all models of spectrafit.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -276,7 +279,7 @@ def test_all_models(self, monkeypatch: Any, script_runner: Any) -> None: def test_not_allowed_input_1(self, monkeypatch: Any, script_runner: Any) -> None: """Testing test all models of spectrafit.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") fname = "spectrafit/test/scripts/test_wrong.pp" ret = script_runner.run( "spectrafit", @@ -288,7 +291,7 @@ def test_not_allowed_input_1(self, monkeypatch: Any, script_runner: Any) -> None def test_not_allowed_input_2(self, monkeypatch: Any, script_runner: Any) -> None: """Testing missing mininizmer parameter in input.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -299,7 +302,7 @@ def test_not_allowed_input_2(self, monkeypatch: Any, script_runner: Any) -> None def test_not_allowed_input_3(self, monkeypatch: Any, script_runner: Any) -> None: """Testing missing optimizer parameter in input.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -310,7 +313,7 @@ def test_not_allowed_input_3(self, monkeypatch: Any, script_runner: Any) -> None def test_no_input(self, monkeypatch: Any, script_runner: Any) -> None: """Testing no provided input for spectrafit.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "spectrafit/test/test_data.csv", @@ -323,7 +326,7 @@ def test_conf_interval( self, monkeypatch: Any, script_runner: Any, tmp_path: Path ) -> None: """Testing upper energy range cut.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -338,7 +341,7 @@ def test_conf_interval( def test_get_no_errors(self, monkeypatch: Any, script_runner: Any) -> None: """Testing for no errorbars for spectrafit.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -349,7 +352,7 @@ def test_get_no_errors(self, monkeypatch: Any, script_runner: Any) -> None: def test_load_noglobal(self, monkeypatch: Any, script_runner: Any) -> None: """Testing for no errorbars for spectrafit.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", @@ -362,7 +365,7 @@ def test_load_noglobal(self, monkeypatch: Any, script_runner: Any) -> None: def test_non_numeric_data(self, monkeypatch: Any, script_runner: Any) -> None: """Testing missing mininizmer parameter in input.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", "-i", "spectrafit/test/scripts/test_input_9.json" ) @@ -374,7 +377,7 @@ class TestGlobalFitting: def test_global_fitting_0(self, monkeypatch: Any, script_runner: Any) -> None: """Testing global fitting.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", "-i", "spectrafit/test/scripts/test_input_global_0.json" ) @@ -397,7 +400,7 @@ def test_global_fitting_0(self, monkeypatch: Any, script_runner: Any) -> None: def test_global_fitting_1(self, monkeypatch: Any, script_runner: Any) -> None: """Testing global fitting.""" - monkeypatch.setattr("builtins.input", lambda _: "n") + monkeypatch.setattr(BUILTINS_INPUT, lambda _: "n") ret = script_runner.run( "spectrafit", "_", "-i", "spectrafit/test/scripts/test_input_global_1.json" )