Repository: spectrochempy/spectrochempy

Issue:
[Bug]: plot_bar() and twinx not working in PCA.screeplot()
### What happened?

See the [PCA example](https://www.spectrochempy.fr/stable/gettingstarted/gallery/auto_examples/analysis/plot_pca_iris.html#sphx-glr-gettingstarted-gallery-auto-examples-analysis-plot-pca-iris-py). Screeplot should display a single figure with a bar plot (explained variance) with blue y axis on the left  + a scatter plot with lines (cumulated variance), with y axis in red on the right.  
- The bar plot is not displayed anymore - this is due to the fact that in `plot1D` line 146  `scatter` is set to `"default"` , the default value of `marker` . As scatter is not None, `line` is set to an ax.plot(...) (line 434+) , and not to ax.bar (line 450+) as it should be.  note that the bar plot is obtained if line 446:
```scatter = "scatter" in method  or marker```
is replaced by:
```scatter = "scatter" in method``` 
 but I don't know why `or marker` was put in the first place :-)

- The second error is related to `twinx` which seems not working anymore: despite `twinx=ax1` is passed, `ax2` is plot in a separate figure. I have tried few workarounds but did not get satiofactory result... 

### What did you expect to happen?

The screeplot as it was before :-)

### Minimal Complete Verifiable Example

_No response_

### Relevant log output

_No response_

### Anything else we need to know?

_No response_

### Environment

INSTALLED VERSIONS
------------------
commit: 53b50aaf9e0a9619a03f17cfa7ab7b6c7dae1479
python: 3.7.10 | packaged by conda-forge | (default, Feb 19 2021, 15:37:01) [MSC v.1916 64 bit (AMD64)]
python-bits: 64
OS: Windows
OS-release: 10
machine: AMD64
processor: Intel64 Family 6 Model 142 Stepping 12, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: ('en_US', 'ISO8859-1')
conda-forge: None
spectrocat: None
defaults: None
quadprog: 0.1.11
brukeropusreader: 1.3
quaternion: 2020.5.19.15.27.24
nmrglue: 0.9-dev
colorama: 0.4.4
dill: 0.3.4
ipython: None
jinja2: 2.11.2
matplotlib: 3.5.1
numba: 0.50.1
numpy: 1.21.2
orderedset: 2.0.3
pint: 0.16.1
plotly: 4.14.3
requests: 2.24.0
scipy: 1.7.1
tqdm: 4.51.0
traitlets: 5.0.5
traittypes: 0.2.1
xlrd: 1.2.0
spectrochempy_data: None
setuptools: 57.4.0
setuptools_scm: 4.1.2
git: 3.1.26
ipywidgets: 7.5.1
ipympl: 0.5.8
jupyterlab: 3.1.7
nodejs: 0.1.1
spectrochempy: 0.2.16.dev29
[Bug]: plot_bar() and twinx not working in PCA.screeplot()
### What happened?

See the [PCA example](https://www.spectrochempy.fr/stable/gettingstarted/gallery/auto_examples/analysis/plot_pca_iris.html#sphx-glr-gettingstarted-gallery-auto-examples-analysis-plot-pca-iris-py). Screeplot should display a single figure with a bar plot (explained variance) with blue y axis on the left  + a scatter plot with lines (cumulated variance), with y axis in red on the right.  
- The bar plot is not displayed anymore - this is due to the fact that in `plot1D` line 146  `scatter` is set to `"default"` , the default value of `marker` . As scatter is not None, `line` is set to an ax.plot(...) (line 434+) , and not to ax.bar (line 450+) as it should be.  note that the bar plot is obtained if line 446:
```scatter = "scatter" in method  or marker```
is replaced by:
```scatter = "scatter" in method``` 
 but I don't know why `or marker` was put in the first place :-)

- The second error is related to `twinx` which seems not working anymore: despite `twinx=ax1` is passed, `ax2` is plot in a separate figure. I have tried few workarounds but did not get satiofactory result... 

### What did you expect to happen?

The screeplot as it was before :-)

### Minimal Complete Verifiable Example

_No response_

### Relevant log output

_No response_

### Anything else we need to know?

_No response_

### Environment

INSTALLED VERSIONS
------------------
commit: 53b50aaf9e0a9619a03f17cfa7ab7b6c7dae1479
python: 3.7.10 | packaged by conda-forge | (default, Feb 19 2021, 15:37:01) [MSC v.1916 64 bit (AMD64)]
python-bits: 64
OS: Windows
OS-release: 10
machine: AMD64
processor: Intel64 Family 6 Model 142 Stepping 12, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: ('en_US', 'ISO8859-1')
conda-forge: None
spectrocat: None
defaults: None
quadprog: 0.1.11
brukeropusreader: 1.3
quaternion: 2020.5.19.15.27.24
nmrglue: 0.9-dev
colorama: 0.4.4
dill: 0.3.4
ipython: None
jinja2: 2.11.2
matplotlib: 3.5.1
numba: 0.50.1
numpy: 1.21.2
orderedset: 2.0.3
pint: 0.16.1
plotly: 4.14.3
requests: 2.24.0
scipy: 1.7.1
tqdm: 4.51.0
traitlets: 5.0.5
traittypes: 0.2.1
xlrd: 1.2.0
spectrochempy_data: None
setuptools: 57.4.0
setuptools_scm: 4.1.2
git: 3.1.26
ipywidgets: 7.5.1
ipympl: 0.5.8
jupyterlab: 3.1.7
nodejs: 0.1.1
spectrochempy: 0.2.16.dev29


Discussion:
Ummmh... looks like my previous refactoring is not completely satisfactory 🙂 ... 

And the tests for plot_1D  notably insufficient... I'll come back to it soon.
Ummmh... looks like my previous refactoring is not completely satisfactory 🙂 ... 

And the tests for plot_1D  notably insufficient... I'll come back to it soon.

Resolving patch:
diff --git a/spectrochempy/core/dataset/ndplot.py b/spectrochempy/core/dataset/ndplot.py
--- a/spectrochempy/core/dataset/ndplot.py
+++ b/spectrochempy/core/dataset/ndplot.py
@@ -502,9 +502,11 @@ def _figure_setup(self, ndim=1, method=None, **kwargs):
         # they will be ignored
         tax = kwargs.get("twinx", None)
         if tax is not None:
-            if isinstance(tax, _Axes):
+            if issubclass(type(tax), mpl.axes.Axes):
                 clear = False
                 ax = tax.twinx()
+                # warning : this currently returns a normal Axes (so units-naive)
+                # TODO: try to solve this
                 ax.name = "main"
                 tax.name = "twin"  # the previous main is renamed!
                 self.ndaxes["main"] = ax
@@ -521,7 +523,7 @@ def _figure_setup(self, ndim=1, method=None, **kwargs):
         if ax is not None:
             # ax given in the plot parameters,
             # in this case we will plot on this ax
-            if isinstance(ax, (_Axes)):
+            if issubclass(type(ax), mpl.axes.Axes):
                 ax.name = "main"
                 self.ndaxes["main"] = ax
             else:
diff --git a/spectrochempy/core/plotters/plot1d.py b/spectrochempy/core/plotters/plot1d.py
--- a/spectrochempy/core/plotters/plot1d.py
+++ b/spectrochempy/core/plotters/plot1d.py
@@ -321,7 +321,7 @@ def plot_1D(dataset, method=None, **kwargs):
         new = new.squeeze()
 
     # is that a plot with twin axis
-    is_twinx = kwargs.pop("twinx", None) is not None
+    is_twinx = kwargs.get("twinx", None) is not None
 
     # if dataset is complex it is possible to overlap
     # with the imaginary component
@@ -342,8 +342,8 @@ def plot_1D(dataset, method=None, **kwargs):
     # ------------------------------------------------------------------------
     method = new._figure_setup(ndim=1, method=method, **kwargs)
 
-    pen = "pen" in method
-    scatter = "scatter" in method or marker
+    pen = "pen" in method or kwargs.pop("pen", False)
+    scatter = "scatter" in method or marker != "auto"
     bar = "bar" in method
 
     ax = new.ndaxes["main"]


Test patch:
diff --git a/tests/test_core/test_plotters/test_plot_1D.py b/tests/test_core/test_plotters/test_plot_1D.py
--- a/tests/test_core/test_plotters/test_plot_1D.py
+++ b/tests/test_core/test_plotters/test_plot_1D.py
@@ -36,6 +36,27 @@ def test_plot_1D():
 
     _ = col.plot_scatter(uselabel=True)
 
+
+def test_issue_375():
+
+    # minimal example
+    n_pc = 3
+
+    color1, color2 = "b", "r"
+
+    ratio = NDDataset([1, 2, 3])
+    cum = ratio.cumsum()
+
+    ax1 = ratio.plot_bar(color=color1, title="Scree plot")
+    assert len(ax1.lines) == 0, "no lines"
+    assert len(ax1.patches) == 3, "bar present"
+    ax2 = cum.plot_scatter(color=color2, pen=True, markersize=7.0, twinx=ax1)
+    assert len(ax2.lines) == 1, "1 lines"
+    assert len(ax2.patches) == 0, "no bar present on the second plot"
+    # TODO: Don't know yet how to get the marker present.
+    ax1.set_title("Scree plot")
+    show()
+
     # nd0.plot(output=os.path.join(figures_dir, 'IR_dataset_1D'),
     #          savedpi=150)
     #
@@ -96,8 +117,6 @@ def test_plot_1D():
     #     raise AssertionError('comparison fails')
     # os.remove('multiple_IR_dataset_1D_scatter.png')
 
-    show()
-
 
 # ======================================================================================================================
 if __name__ == "__main__":