Putting limits on a fitting in a plot

Viewed 90

I have a graph of data, and have applied a linear fit to it, however, I am not sure why, but the fitted line is well away from the data itself. How would I go about imposing limits on this line so it just fits around my data (and preferably making the data the focus of the graph too!)

Graph output and code below:

Linear Fitted Data

plt.plot(np.log(ts), amps, "1", ms=5, label="Schmitt Analysis (Amplitude against Log(Time))")

##Plot Linear Fit
y1, r, *_ = np.polyfit(amps, np.log(ts), 1, full=True)
f1 = np.poly1d(y1)
plt.plot(amps, f1(amps), label=f"linear ($\chi^2$ = {r[0]:0.2f})")

plt.xlabel("Log(Time)")
plt.ylabel("Amplitude")
plt.title("Schmitt Analysis (Amplitude against Log(Time))")
plt.xlim(0,10)
plt.ylim(-40,80)
plt.legend()

plt.savefig('A_Schmitt.jpg')

The actual data being used:

log(ts) = [ -inf 2.89037176 3.58351894 3.98898405 4.49980967 4.68213123 4.83628191 4.9698133 5.08759634 5.19295685 5.28826703 5.37527841 5.45532112 5.52942909 5.59842196 5.7235851 5.78074352 5.83481074 5.9348942 6.02586597 6.06842559 6.10924758 6.1484683 6.22257627 6.25766759 6.32435896 6.38687932 6.41673228 6.44571982 6.50128967 6.52795792 6.5539334 6.71901315 6.78219206]

amps = [77.78630383833547, 62.92926582239441, 63.84025706577048, 55.489066870438165, 38.60797989548756, 40.771390484048545, 14.679073842876978, 33.95959972488966, 29.41960790300141, 32.93241034391399, 30.927428194781815, 31.086396885182356, 21.52771899125612, 4.27684299160886, 6.432975528727562, 7.500376934048583, 18.730555740591637, 4.355896959987761, 11.677509915219987, 12.865482314301719, 0.6120306267606219, 12.614420497451556, 2.2025029753442404, 9.447046999592711, 4.0688197216393425, 0.546672901996845, 1.12780050608251, 2.2030852358874635, 2.202804718915858, 0.5726686031033587, 0.5465322281618783, 0.5185100682386156, 0.575055917739342, 0.5681697592593679]

Noticing I'd made an error, I managed to get the graph to update a little, but now the fitting has just failed completely.
Graph 2

I've updated the code above to the new version also.

2 Answers

use xlim and ylim

    plt.plot(np.log(ts), amps, "1", ms=5, label="Schmitt Analysis (Log(Amplitude) 
    against Time)")
    
    
    y1, r, *_ = np.polyfit(amps, ts, 1, full=True)
    f1 = np.poly1d(y1)
    plt.plot(amps, f1(amps), label=f"linear ($\chi^2$ = {r[0]:0.2f})")
    
    plt.xlabel("Log(Time)")
    plt.ylabel("Amplitude")
    plt.title("Schmitt Analysis (Amplitude against Log(Time)")
    plt.xlim(0, 10)
    plt.ylim(0, 10)
    plt.legend()
    
    plt.savefig('A_Schmitt.jpg'

)

Two problems here - a typo and the presence of -inf.
First the typo - you attributed logts and amps to y and x, respectively, in your fit, whereas it should be the other way round.
Second, the presence of -inf in your log-transformed time array is not handled well by the fit routine. We can manually exclude the first point with logts[1:].

import numpy as np
from matplotlib import pyplot as plt

#recreating your input - seemingly log(ts) is a numpy array
logts = np.asarray([-np.inf, 2.89037176, 3.58351894, 3.98898405, 4.49980967, 4.68213123, 4.83628191, 4.9698133, 5.08759634, 5.19295685, 5.28826703, 5.37527841, 5.45532112, 5.52942909, 5.59842196, 5.7235851, 5.78074352, 5.83481074, 5.9348942, 6.02586597, 6.06842559, 6.10924758, 6.1484683, 6.22257627, 6.25766759, 6.32435896, 6.38687932, 6.41673228, 6.44571982, 6.50128967, 6.52795792, 6.5539334, 6.71901315, 6.78219206])
amps = [77.78630383833547, 62.92926582239441, 63.84025706577048, 55.489066870438165, 38.60797989548756, 40.771390484048545, 14.679073842876978, 33.95959972488966, 29.41960790300141, 32.93241034391399, 30.927428194781815, 31.086396885182356, 21.52771899125612, 4.27684299160886, 6.432975528727562, 7.500376934048583, 18.730555740591637, 4.355896959987761, 11.677509915219987, 12.865482314301719, 0.6120306267606219, 12.614420497451556, 2.2025029753442404, 9.447046999592711, 4.0688197216393425, 0.546672901996845, 1.12780050608251, 2.2030852358874635, 2.202804718915858, 0.5726686031033587, 0.5465322281618783, 0.5185100682386156, 0.575055917739342, 0.5681697592593679]

#plot raw data
plt.plot(logts, amps, "1", ms=5, label="Schmitt Analysis (Amplitude against Log(Time))")

#linear fit excluding the first point that is an outlier
y1, r, *_ = np.polyfit(logts[1:], amps[1:], 1, full=True)
f1 = np.poly1d(y1)

#get min and max of logts excluding nan and inf values
logtsmin = np.floor(np.nanmin(logts[logts != -np.inf]))
logtsmax = np.ceil(np.nanmax(logts[logts != np.inf]))
#evenly spaced x-values for the fit line plot 
xlogts = np.linspace(logtsmin, logtsmax, 1000)
plt.plot(xlogts, f1(xlogts), label=f"linear ($\chi^2$ = {r[0]:0.2f})")

plt.xlabel("Log(Time)")
plt.ylabel("Amplitude")
plt.title("Schmitt Analysis (Amplitude against Log(Time))")
plt.xlim(logtsmin, logtsmax)
plt.legend()

plt.show()

Sample output:

enter image description here

Related