title: Scipy Curve Fit Optimize not working for log scale values
body: <p>So I am trying to fit a set of data points to this equation:</p>
  
  <p>abs(I) = Io(exp((qV)/(nKT)) - 1) --- Shockley diode equation</p>
  
  <p>to a bunch of data points I was given. Knowing the V and the I values, I need to optimize the Io and the n values to get me data closely matching the data set I was given. </p>
  
  <p>However, scipy optimize curve fit is not giving me the values I want, which is where n = ~1.15 and Io = ~1.8E-13, and is instead giving me n = 2.12 and I = 2.11E-11. I suspect this is due to the data set values being very small numbers, messing with the optimization, but even when i set the initial guess to be n = 1.15 and Io = 1.8E-13, the optimization values do not change.</p>
  
  <p>Does anyone have any tips on how to fix this?</p>
  
  <pre><code>import numpy as np
  import math
  import matplotlib.pyplot as plt
  from scipy.optimize import curve_fit
  
  
  Voltage = np.array([-0.5 , -0.49, -0.48, -0.47, -0.46, -0.45, -0.44, -0.43, -0.42,
         -0.41, -0.4 , -0.39, -0.38, -0.37, -0.36, -0.35, -0.34, -0.33,
         -0.32, -0.31, -0.3 , -0.29, -0.28, -0.27, -0.26, -0.25, -0.24,
         -0.23, -0.22, -0.21, -0.2 , -0.19, -0.18, -0.17, -0.16, -0.15,
         -0.14, -0.13, -0.12, -0.11, -0.1 , -0.09, -0.08, -0.07, -0.06,
         -0.05, -0.04, -0.03, -0.02, -0.01,  0.  ,  0.01,  0.02,  0.03,
          0.04,  0.05,  0.06,  0.07,  0.08,  0.09,  0.1 ,  0.11,  0.12,
          0.13,  0.14,  0.15,  0.16,  0.17,  0.18,  0.19,  0.2 ,  0.21,
          0.22,  0.23,  0.24,  0.25,  0.26,  0.27,  0.28,  0.29,  0.3 ,
          0.31,  0.32,  0.33,  0.34,  0.35,  0.36,  0.37,  0.38,  0.39,  0.4 ])
  Current = np.array([  6.99000000e-13,   6.83000000e-13,   6.57000000e-13,
           6.46000000e-13,   6.19000000e-13,   6.07000000e-13,
           5.86000000e-13,   5.73000000e-13,   5.55000000e-13,
           5.37000000e-13,   5.27000000e-13,   5.08000000e-13,
           4.92000000e-13,   4.75000000e-13,   4.61000000e-13,
           4.43000000e-13,   4.32000000e-13,   4.18000000e-13,
           3.99000000e-13,   3.91000000e-13,   3.79000000e-13,
           3.66000000e-13,   3.54000000e-13,   3.43000000e-13,
           3.34000000e-13,   3.18000000e-13,   3.06000000e-13,
           2.96000000e-13,   2.86000000e-13,   2.77000000e-13,
           2.66000000e-13,   2.59000000e-13,   2.54000000e-13,
           2.43000000e-13,   2.33000000e-13,   2.22000000e-13,
           2.16000000e-13,   2.07000000e-13,   2.00000000e-13,
           1.94000000e-13,   1.85000000e-13,   1.77000000e-13,
           1.68000000e-13,   1.58000000e-13,   1.48000000e-13,
           1.35000000e-13,   1.21000000e-13,   1.03000000e-13,
           7.53000000e-14,   4.32000000e-14,   2.33000000e-15,
           6.46000000e-14,   1.57000000e-13,   2.82000000e-13,
           4.58000000e-13,   7.07000000e-13,   1.06000000e-12,
           1.57000000e-12,   2.28000000e-12,   3.29000000e-12,
           4.75000000e-12,   6.80000000e-12,   9.76000000e-12,
           1.39000000e-11,   1.82000000e-11,   2.57000000e-11,
           3.67000000e-11,   5.21000000e-11,   7.39000000e-11,
           1.04000000e-10,   1.62000000e-10,   2.27000000e-10,
           3.21000000e-10,   4.48000000e-10,   6.21000000e-10,
           8.70000000e-10,   1.20000000e-09,   1.66000000e-09,
           2.27000000e-09,   3.08000000e-09,   4.13000000e-09,
           5.46000000e-09,   7.05000000e-09,   8.85000000e-09,
           1.11000000e-08,   1.39000000e-08,   1.74000000e-08,
           2.05000000e-08,   2.28000000e-08,   2.52000000e-08,
           2.91000000e-08])
  
  def diode_function(V, n, Io):
      kt = 300 * 1.38 * math.pow(10, -23)
      q = 1.60 * math.pow(10, -19)
      I_final = Io * (np.exp( (q * V) / (n * kt) ) - 1)
      return abs(I_final)
  
  
  p0 = [1.15, 1.8e-13]
  popt, pcov = curve_fit(diode_function, Voltage, Current, p0 = p0)
  
  print(popt)
  
  fig = plt.figure()
  ax = fig.add_subplot(121)
  ax.set_title('I_d vs V_d')
  ax.set_xlabel('V_d')
  ax.set_ylabel('I_d')
  ax.set_yscale('log')
  plt.plot(Voltage, Current, 'ko', label="Original Data")
  plt.plot(Voltage, diode_function(Voltage, *popt), 'r-', label="Fitted Curve")
  plt.legend(loc='best')
  
  
  
  ax = fig.add_subplot(122)
  ax.set_title('I_d vs V_d')
  ax.set_xlabel('V_d')
  ax.set_ylabel('I_d')
  ax.set_yscale('log')
  popt = [1.15,1.8e-13]
  plt.plot(Voltage, Current, 'ko', label="Original Data")
  plt.plot(Voltage, diode_function(Voltage, *popt), 'r-', label="Fitted Curve")
  plt.legend(loc='best')
  plt.show()
  </code></pre>
  
  <p>Picture of the graph:
  <a href="https://i.stack.imgur.com/nf3kz.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/nf3kz.png" alt="enter image description here"></a>
  </p>
  
  <p>The left graph is with scipy optimization and the right graph is the one I want</p>