# [depends] ABC_data.dat# This py-file loads data file 'ABC_data.dat'.fromparestoimportParestofrommiscimportgnuplotsaveimportnumpyasnpimportmatplotlib.pyplotaspltfromscipy.interpolateimportinterp1dimportosplt.ion()model=Paresto()model.print_level=1model.transcription='shooting'model.nlp_solver_options={'ipopt':{'mumps_scaling':0}}model.x=['ca','cb','cc']model.p=['k1','k2']model.d=['m_ca','m_cb','m_cc']# Define the massbal_ode functiondefmassbal_ode(t,x,p):r1=p.k1*x.car2=p.k2*x.cbxdot=[-r1,r1-r2,r2]returnxdotncase=1ifncase==1:# fit A,B,Cdeflsq(t,y,p):return[y.ca-y.m_ca,y.cb-y.m_cb,y.cc-y.m_cc]nmeas=[0,1,2]elifncase==2:# fit A onlydeflsq(t,y,p):return[y.ca-y.m_ca]nmeas=[0]elifncase==3:# fit B onlydeflsq(t,y,p):return[y.cb-y.m_cb]nmeas=[1]elifncase==4:# fit C onlydeflsq(t,y,p):return[y.cc-y.m_cc]nmeas=[2]else:raiseValueError('Invalid ncase')# Set up the modeltfinal=6nplot=75tplot=np.linspace(0,tfinal,nplot)tabledat=np.loadtxt('ABC_data.dat')# Extract the first columntmeas=tabledat[:,0]ymeas=tabledat[:,1:4]combined_times=np.concatenate((tmeas,tplot))tplot,ic=np.unique(combined_times,return_inverse=True)meas_ind=ic[:len(tmeas)]# Step 2: Interpolating Measurementsinterpolator=interp1d(tmeas,ymeas,axis=0,kind='previous',fill_value='extrapolate')y_noisy=interpolator(tplot)# Step 3: Handling NaN Valuesy_noisy[np.isnan(y_noisy)]=0.0y_noisy=np.reshape(y_noisy.T,(3,-1,1))model.ode=massbal_odemodel.lsq=lsqmodel.tout=tplotmodel.nsets=1model.lsq_ind=meas_ind# Initialize Paresto instancemodel.initialize()xsim,_=model.simulate({'k1':0.5,'k2':3.0,'ca':1.0,'cb':0.0,'cc':0.0})# Initial conditionsca0=1.0cb0=0.0cc0=0.0model.ic.k1=0.5model.ic.k2=3.0model.ic.ca=ca0model.ic.cb=cb0model.ic.cc=cc0model.lb_ub()model.lb.k1=1e-4model.lb.k2=1e-4model.ub.k1=10model.ub.k2=10est,yy,pp=model.optimize(y_noisy)conf=model.confidence(est,0.95)print('Estimated parameters')print('\n'.join(f'{k}: {float(v)}'fork,vinest.theta.items()))print('Bounding box intervals')print('\n'.join(f'{k}: {float(v)}'fork,vinconf.bbox.items()))ifos.getenv('OMIT_PLOTS')!='true':# Plot the model fit to the noisy measurementsplt.figure()plt.plot(model.tout,est.x[nmeas,:].reshape(-1,len(tplot)).T)plt.plot(tmeas,ymeas[:,nmeas],'o')plt.xlabel('Time')plt.ylabel('Values')plt.title('Model Fit to Noisy Measurements')plt.show()ifncase!=1:plt.figure()plt.plot(model.tout,est.x.reshape(-1,len(tplot)).T)plt.plot(tmeas,ymeas,'o')plt.xlabel('Time')plt.ylabel('Values')plt.title('Model Fit for All Measurements')plt.show()# Save model fit (ind 0) and raw measurements (ind 1) so gnuplot can# pull both with "ind 0" / "ind 1" — matches Octave's `save ABC.dat tableest tabledat`.tableest=np.column_stack((model.tout,est.x.reshape(-1,len(tplot)).T))gnuplotsave('ABC.dat',{'tableest':tableest,'tabledat':tabledat})