0

I have generated the following plot with matplotlib from Jupyter. The plots have the same x-axis so I want to merge them, i.e. to have a common x-axis for both the plots.

plot This is the code I have used. How to integrate the result in this code?

import numpy as np 
import pandas as pd
from scipy.optimize import curve_fit    
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
from matplotlib.colors import ListedColormap, LinearSegmentedColormap

file1 = '1.dat'
file2 = '1SED.dat'

data1 = pd.read_csv(file1, delimiter='\s+', header=None, engine='python')
data1.columns = ['Wavelength','Obs.Flux','Obs.Error','Flux','Error','FluxMod','Fitted','Excess','(F-Fm)']

data2 = pd.read_csv(file2, delimiter='\s+', header=None, engine='python')
data2.columns = ['wave','cflux']


def fit_data():

fig = plt.figure(1,figsize=(10,9))

plt.subplot(211)
np.linspace(1000,3E4)
plt.plot(data2['wave'], data2['cflux'],   color='cornflowerblue', linestyle= '-', lw=0.5)
plt.scatter(data1['Wavelength'], data1['Obs.Flux'],  marker='o', color='red', s=75)

#plt.xlabel('$\lambda (\AA)$',size=15)
plt.ylabel('$F_{\lambda} (erg/cm^{2}/s/\AA)$',size=15)
plt.yscale('log')
plt.xscale('log')
plt.ylim(1E-18,4E-17)
plt.xlim(1000,2E4)
plt.title('Star No. 1')

plt.subplot(212)
plt.plot(data1['Wavelength'], data1['(F-Fm)'],  marker='o', color='red')
plt.plot(data1['Wavelength'], data1['(F-Fm)'],  linestyle='-', color='red', lw=1.5)
plt.xlabel('$\lambda (\AA)$',size=15)
plt.xscale('log')

plt.savefig("1SED")

plt.show()
plt.close()

fit_data()

I tried using the edit you suggested and have received the following error

TypeError                                 Traceback (most recent call last)
<ipython-input-8-d43e496e030f> in <module>()
     32     plt.close()
     33 
---> 34 fit_data()


<ipython-input-8-d43e496e030f> in fit_data()
     16 #... other commands to be applied on ax1
     17 
---> 18     ax2 = fig.add_subplot(212, sharex=True)
     19     ax2.plot(data1['Wavelength'], data1['(F-Fm)'],  marker='o', color='red')
     20     ax2.plot(data1['Wavelength'], data1['(F-Fm)'],  linestyle='-', color='red', lw=1.5)

~/anaconda3/lib/python3.6/site-packages/matplotlib/figure.py in add_subplot(self, *args, **kwargs)
   1072                     self._axstack.remove(ax)
   1073 
-> 1074             a = subplot_class_factory(projection_class)(self, *args, **kwargs)
   1075 
   1076         self._axstack.add(key, a)

~/anaconda3/lib/python3.6/site-packages/matplotlib/axes/_subplots.py in __init__(self, fig, *args, **kwargs)
     71 
     72         # _axes_class is set in the subplot_class_factory
---> 73         self._axes_class.__init__(self, fig, self.figbox, **kwargs)
     74 
     75     def __reduce__(self):

~/anaconda3/lib/python3.6/site-packages/matplotlib/axes/_base.py in __init__(self, fig, rect, facecolor, frameon, sharex, sharey, label, xscale, yscale, axisbg, **kwargs)
    496         self._sharey = sharey
    497         if sharex is not None:
--> 498             self._shared_x_axes.join(self, sharex)
    499             if sharex._adjustable == 'box':
    500                 sharex._adjustable = 'datalim'

~/anaconda3/lib/python3.6/site-packages/matplotlib/cbook/__init__.py in join(self, a, *args)
   1493 
   1494         for arg in args:
-> 1495             set_b = mapping.get(ref(arg))
   1496             if set_b is None:
   1497                 set_a.append(ref(arg))

TypeError: cannot create weak reference to 'bool' object
BRMBU
  • 31
  • 1
  • 10
  • Possible duplicate of [matplotlib share x axis but don't show x axis tick labels for both, just one](https://stackoverflow.com/questions/4209467/matplotlib-share-x-axis-but-dont-show-x-axis-tick-labels-for-both-just-one) – OriolAbril Jun 05 '18 at 20:48
  • No, I want the top of the lower graph (border) and the bottom of the first graph (border) to sit on each other. I was able to do this on Origin in Windows. But want to do the same here – BRMBU Jun 05 '18 at 23:13
  • They you have to combine the upper answer with this one https://stackoverflow.com/questions/20057260/how-to-remove-gaps-between-subplots-in-matplotlib – OriolAbril Jun 06 '18 at 09:52
  • Or directly take a look at this matplotlib example https://matplotlib.org/2.0.0/examples/pylab_examples/subplots_demo.html – OriolAbril Jun 06 '18 at 09:53
  • I have edited the question and added my code. Could you help out? – BRMBU Jun 07 '18 at 05:36

1 Answers1

1

To personalize the subplots like this, the object oriented API of matplotlib makes the code much simpler.

You already have fig = plt.figure(..., then you would need to do ax1 = fig.add_subplot(211) and modify most of the methods called, in general, adding a set_ in front of the name (i.e. xlabel, yscale, title...) works, in case of doubt, consult the axes class documentation.

In addition, the answers from the other links I commented can be used. The main differences with the code above are using sharex=True in order to force both subplots to have the same xaxis, and after plotting, using the setp and subplots_adjust to remove the labels and the space.

Therefore, the code would look like:

fig = plt.figure(1,figsize=(10,9))

ax1= fig.add_subplot(211)
ax1.plot(data2['wave'], data2['cflux'],   color='cornflowerblue', linestyle= '-', lw=0.5)
ax1.scatter(data1['Wavelength'], data1['Obs.Flux'],  marker='o', color='red', s=75)

ax1.set_ylabel('$F_{\lambda} (erg/cm^{2}/s/\AA)$',size=15)
ax1.set_yscale('log')
#... other commands to be applied on ax1

ax2 = fig.add_subplot(212, sharex=ax1)
#... other commands to be applied on ax2

plt.setp(ax1.get_xticklabels(), visible=False) # hide labels
fig.subplots_adjust(hspace=0) # remove vertical space between subplots
OriolAbril
  • 7,315
  • 4
  • 29
  • 40
  • I have tried the code, It compiles and prints out the first plot but not the second. I have included the error in the original question – BRMBU Jun 07 '18 at 11:50
  • @Bryan Oh, sorry, I don't know why I wrote True. I have corrected it. It should be ax1, in order to tell matplotlib with whom should the xaxis be shared – OriolAbril Jun 07 '18 at 15:34
  • Ok. I tried to compile it by removing that statement and it worked . – BRMBU Jun 07 '18 at 15:38
  • I have another problem. I need to add error bars to the first plot. With TOPCAT it was easy to do so. I tried using the help from matplotlib page but it terminates with an error. Anyidea how it can be fixed? – BRMBU Jun 07 '18 at 15:39
  • Then just do `ax1.errorbar()` instead of `ax1.scatter` or `ax1.plot`. Here is the documentation of the errorbar method: https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.errorbar.html#matplotlib.axes.Axes.errorbar – OriolAbril Jun 07 '18 at 15:53
  • I end up getting an error which says Value Error: in safezip, Len(args[0])=6 but Len(args[1]=1 – BRMBU Jun 07 '18 at 15:57
  • What syntax are you using to call the errorbar? could you comment it? – OriolAbril Jun 07 '18 at 16:08
  • ax1.errorbar(data1['Wavelength'], data1['Obs.Flux'], yerr=['Error'], fmt='.k', ecolor='black', color='black', elinewidth=3, capsize=2)) – BRMBU Jun 07 '18 at 16:13
  • Last comment, because I think it will solve the issue, otherwise we should move to the chat. You are missing the `data['Error']` (there is only `['Error']`), thus, matplotlib understands that your input is a list of length 1 and with strings inside. And crashes – OriolAbril Jun 07 '18 at 16:17
  • Thank you it worked. Could you share your mail id to contact – BRMBU Jun 07 '18 at 16:31
  • I'd rather not, I tend to follow questions about python, matplotlib, numpy and so on, so if you ask more questions I'll probably end up answering another one, and there is many people here who are much better teachers than me – OriolAbril Jun 07 '18 at 16:51
  • Ok. Thank you. Is there someway I can resize the subplots individually? – BRMBU Jun 09 '18 at 12:10
  • Yes, you can take a look at the [matplotlib documentation](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplot.html#matplotlib.pyplot.subplot), the [examples](https://matplotlib.org/gallery/subplots_axes_and_figures/subplots_demo.html) or search here at stackoverflow for both matplotlib and suplot tag at the same time: https://stackoverflow.com/questions/tagged/matplotlib+subplot – OriolAbril Jun 09 '18 at 13:03
  • I have tried using aspect ratio to get the lower plot to resize but that doesn't happen since only the x axis is in the log scale and the y axis is linear (That is the way the plot has to be). In the grid I want the upper plot to be bigger and the lower plot to be smaller. Is that possible? – BRMBU Jun 19 '18 at 12:51
  • It will probably be possible. Search about it and see if there are any questions or tutorials about that, and if this ia not the case, ask a new question – OriolAbril Jun 19 '18 at 13:50