It’s going to take a while to extract a MWE from the package and pluto notebook, so I’ll post the question first in case I get lucky. Note that I am self-taught and relatively new to Julia, so my code is probably bad.
I’m writing a package for data analysis, part of which is using helium pycnometry to determine sample volume. Needing to get data analysis for an experiment done faster, I started with a Pluto notebook for a specific dataset and am working to make a general package using PlutoDevMacros and VSCodium to transfer functions from Pluto to the package. Every function except one copy/pasted easily.
The MethodError’s list of arguments matches the function call for the Pycnometry function (below). This worked fine in Pluto and is a direct copy-paste in the package. I get the same error message whether I call the function from Pluto or use a script in VSCodiuim.
As I read the error, It is an error calling the function and not a problem in the function. The arguments in parentheses match the keyword arguments I defined, but the arguments after that add an argument that I did not define or call: the true at the beginning I think the hexadecimal at the end relates to the MethodError and not the function call. I do not know where it comes from, and assume that addition means Julia can’t find a function with the correct arguments to call.
Does anyone know where those two arguments come from and what to do about it?
Note: I’ve deleted the actual dataframes from the output–it did not look like they would be readable. The warning is the output from my Catch statement.
Warning: function AnalyzeCellInjections!: Analysis Failed: MethodError(Core.kwcall, ((dry = false, InjectionGas = "helium", MaxItr = 100, InitialGuess = 25 mL, LeakAnalysis = true), true, 4×6 DataFrame, 4×10 DataFrame, 5.36 mL), 0x0000000000009925)
Function AnalyzeCellInjections below, the call to Pycnometry function is in the Try Catch near the end, data is stored in a struct for later output, cell.SourceInjectionData is the 4x6 dataframe in the error, and cell.InjectionData is the 4x10 dataframe
function AnalyzeCellInjections!(Cells::OrderedDict{Symbol, CellDefinition}; Dry = true, Pycnometry = false,
ExpFactors::Union{Missing, Integer} = missing, MaxItr::Integer = 100, LeakAnalysis::Bool = false,
Delayed::Union{Missing, Dates.Period} = missing, InitialGuess = 25u"mL")
for (key, cell) in pairs(Cells)
@info "Processing " * string(cell.Description)
if !cell.GasCell
MatchSourceData!(Cells, key)
FlagEquilibriumPeriods!(cell.Data, cell.Injections, :InjIn; EquilPeriod = cell.Param.EquilPeriod, Advance = cell.Param.IgnorePeriod, Delay = cell.Param.GCDelay, GasCell = cell.GasCell, Delayed = Delayed)
if !ismissing(ExpFactors)
if ExpFactors == 2
cell.ExpFactors = Get2ExpFactors(cell.Data, cell.Injections, ValidInj = cell.Param.ValidInj)
elseif ExpFactors == 1
cell.ExpFactors = Get1ExpFactors(cell.Data, cell.Injections, ValidInj = cell.Param.ValidInj)
elseif ExpFactors == 0
cell.ExpFactors = GetLines(cell.Data, cell.Injections, ValidInj = cell.Param.ValidInj)
else
@warn "function AnalyzeCellInjections!: Invalid number of exponentials specified"
end
end
cell.InjectionData = GetInjectionData(cell.Data, cell.Injections, :InjIn, σₙ = Cells[cell.GasKey].σₙ, ExpFactors = cell.ExpFactors, GasCell = cell.GasCell, Delayed = ismissing(Delayed) ? false : true)
try
if Pycnometry
cell.Volume, cell.AdjVolume, cell.CombinedData = Pycnometry(cell.SourceInjectionData, cell.InjectionData,
Cells[cell.GasKey].Volume; dry = Dry, InjectionGas = Cells[cell.GasKey].InjectionGas, MaxItr = MaxItr,
InitialGuess = InitialGuess, LeakAnalysis = LeakAnalysis
)
else
cell.CombinedData = InjectionAnalyis(cell.SourceInjectionData, cell.InjectionData; InjectionGas = Cells[cell.GasKey].InjectionGas, SampleMass = cell.SampleMass, RamanDissolvedConc = cell.RamanDissolvedConc, WaterMass = cell.WaterMass, HeadSpaceVolume = cell.Volume, GasCellVolume = Cells[cell.GasKey].Volume, MolesHe = cell.MolesHe)
end
catch error
@warn "function AnalyzeCellInjections!: Analysis Failed: " * string(error)
@debug string(key) * " Injection Data"
@debug cell.InjectionData[:, 3:6]
@debug string(cell.GasKey) * " Injection Data"
@debug cell.SourceInjectionData[:, 3:6]
end
end
end
return nothing
end
Pycnometry function
function Pycnometry(SourceInjectionData::DataFrame, TargetInjectionData::DataFrame, GasCellVolume::Quantities;
dry::Bool = true, InjectionGas::String = "helium", MaxItr::Integer = 100, InitialGuess::Quantities = 25u"ml",
LeakAnalysis::Bool = false)
println("Pycnometry function called")
InjectModel = SingleFluid(InjectionGas)
HeN₂H₂O_GERG2008 = GERG2008(["helium", "nitrogen", "water"])
#=
drop uncertainty from measurements: Mole fractions must total 1.0 for Clapeyron (or use actual moles),
and the vector of mole fractions/moles does not work with the @uncertain macro to get uncertainties from
incompatible functions
=#
zForH2Ocalc = 1
Tₒ = Measurements.value(TargetInjectionData.TargetTempBef[1])
Pₒ = Measurements.value(TargetInjectionData.TargetPressBef[1])
PP_H2O = PH2O(Tₒ) |> u"psi"
if dry
PP_H2O = 0u"psi"
PP_N2 = Pₒ
MF_H2O = PP_H2O / Pₒ
MF_N2 = PP_N2 / Pₒ
MF_He = 0 # not yet injected
GasMixPre = [MF_He, MF_N2, MF_H2O]
elseif Pₒ >= PP_H2O
PP_N2 = Pₒ - PP_H2O
MF_H2O = PP_H2O / Pₒ
MF_N2 = PP_N2 / Pₒ
MF_He = 0 # not yet injected
GasMixPre = [MF_He, MF_N2, MF_H2O]
else
PP_N2 = 0u"psi"
MF_H2O = 1
MF_N2 = 0
MF_He = 0 # not yet injected
GasMixPre = [MF_He, MF_N2, MF_H2O] #assume entire pressure is water vapor
end
CombinedData = DataFrame()
z = zFac(HeN₂H₂O_GERG2008, TargetInjectionData.TargetPressBef[1], TargetInjectionData.TargetTempBef[1], GasMixPre)
TotalMolesBefore = MolesPresent(TargetInjectionData.TargetPressBef[1], TargetInjectionData.TargetTempBef[1], z,
InitialGuess
) |> u"mmol"
CurrentVolume = InitialGuess
PrevVolume = 0.0u"mL"
if LeakAnalysis
AdjCurrentVolume = InitialGuess
AdjPrevVolume = 0.0u"mL"
TotalMolesGasLeaked = zeros(nrow(TargetInjectionData)) .* u"mmol"
else
AdjCurrentVolume = InitialGuess
AdjPrevVolume = InitialGuess
end
i = 0 # infinite loop break counter
while (abs(PrevVolume - CurrentVolume) > 1e-10u"mL") || (abs(AdjPrevVolume - AdjCurrentVolume) > 1e-10u"mL")
CombinedData = innerjoin(SourceInjectionData, TargetInjectionData, on = :Injection)
PrevVolume = CurrentVolume
AdjPrevVolume = AdjCurrentVolume
@transform! CombinedData @astable begin
:PSatH2O = dry ? (0u"psi" .* ones(nrow(CombinedData))) : PSat_H2Ounc.(:TargetTempAft)
:MolesH2O = MolesPresent.(:PSatH2O, :TargetTempAft, zForH2Ocalc, CurrentVolume)
:MolesN2BefPyc = TotalMolesBefore * MF_N2 .* ones(nrow(CombinedData))
:zSourceBef = zFac.(InjectModel, :SourcePressBef, :SourceTempBef)
:zSourceAft = zFac.(InjectModel, :SourcePressAft, :SourceTempAft)
:SourceMolesGasBef = MolesPresent.(:SourcePressBef, :SourceTempBef, :zSourceBef, GasCellVolume) .|> u"mmol"
:SourceMolesGasAft = MolesPresent.(:SourcePressAft, :SourceTempAft, :zSourceAft, GasCellVolume) .|> u"mmol"
:MolesGasInjected = :SourceMolesGasBef - :SourceMolesGasAft .|> u"mmol"
:TotalMolesGasInjected = cumsum(:MolesGasInjected) .|> u"mmol"
:TotalMolesGasBefInj = :TotalMolesGasInjected - :MolesGasInjected
end
CombinedData.zTargetBef .= 1.0
CombinedData.zTargetAft .= 1.0
CombinedData.Volume .= (0.0±0.0)u"mL"
if LeakAnalysis
CombinedData.zAdjTargetAft .= 1.0
CombinedData.AdjVolume .= (0.0±0.0)u"mL"
end
for (i, row) in enumerate(eachrow(CombinedData))
if InjectionGas == "nitrogen"
GasMixBef = Measurements.value.([0u"mmol", row.MolesN2BefPyc + row.TotalMolesGasBefInj, row.MolesH2O])
GasMixAft = Measurements.value.([0u"mmol", row.MolesN2BefPyc + row.TotalMolesGasInjected, row.MolesH2O])
else
GasMixBef = Measurements.value.([row.TotalMolesGasBefInj, row.MolesN2BefPyc, row.MolesH2O])
GasMixAft = Measurements.value.([row.TotalMolesGasInjected, row.MolesN2BefPyc, row.MolesH2O])
end
CombinedData.zTargetBef[i] = compressibility_factor(HeN₂H₂O_GERG2008, Measurements.value(row.TargetPressBef),
Measurements.value(row.TargetTempBef), GasMixBef
)
CombinedData.zTargetAft[i] = compressibility_factor(HeN₂H₂O_GERG2008, Measurements.value(row.TargetPressAft),
Measurements.value(row.TargetTempAft), GasMixAft
)
CombinedData.Volume[i] = PycVolume.(row.TargetPressAft, row.TargetTempAft, row.zTargetAft,
(row.MolesN2BefPyc + row.MolesH2O + row.TotalMolesGasInjected)
)
end
if LeakAnalysis
#need adj moles h20 and n2
for (i, row) in enumerate(eachrow(CombinedData))
if InjectionGas == "nitrogen"
AdjGasMixAft = Measurements.value.([0u"mmol", row.MolesN2BefPyc + row.TotalMolesGasInjected -
TotalMolesGasLeaked[i], row.MolesH2O]
)
else
AdjGasMixAft = Measurements.value.([row.TotalMolesGasInjected - TotalMolesGasLeaked[i],
row.MolesN2BefPyc, row.MolesH2O]
)
end
CombinedData.zAdjTargetAft[i] = compressibility_factor(HeN₂H₂O_GERG2008,
Measurements.value(row.LeakRateAdjPressureAft), Measurements.value(row.TargetTempAft), AdjGasMixAft
)
end
@transform! CombinedData @astable begin
:MolesGasLeaked = MolesPresent.(:LeakRateAdjPressureAft, :TargetTempAft, :zAdjTargetAft,
AdjCurrentVolume) - MolesPresent.(:TargetPressAft, :TargetTempAft, :zTargetAft, AdjCurrentVolume
)
:TotalMolesGasLeaked = cumsum(:MolesGasLeaked)
:RemainingMolesGas = :TotalMolesGasInjected - :TotalMolesGasLeaked
:InitialMolesGas = :RemainingMolesGas + :MolesGasLeaked
:AdjVolume = PycVolume.(:LeakRateAdjPressureAft, :TargetTempAft, :zAdjTargetAft, :RemainingMolesGas)
end
end
zForH2Ocalc = CombinedData.zTargetAft
givenunit = unit(mean(CombinedData.Volume))
CurrentVolume = weightedmean(ustrip.(CombinedData.Volume)) * givenunit
if LeakAnalysis
Adjgivenunit = unit(mean(CombinedData.AdjVolume))
AdjCurrentVolume = weightedmean(ustrip.(CombinedData.AdjVolume)) * Adjgivenunit
TotalMolesGasLeaked = CombinedData.TotalMolesGasLeaked
end
TotalMolesBefore = MolesPresent(CombinedData.TargetPressBef[1], CombinedData.TargetTempBef[1],
CombinedData.zTargetBef[1], CurrentVolume
) |> u"mmol"
i += 1
if i >= MaxItr
@warn "Maximum Iterations reached"
break
end
end
@debug "Iterations: " * string(i)
# weightedmean function gives the weighted mean of a set of measurements using inverses of variances as weights
# weightedmean function is not compatible with units, get the given unit, strip it from the vector,
# calculate weighted mean and add the unit back
givenunit = unit(mean(CombinedData.Volume)) #using the mean will cause errors if the units do not match
TargetVolume = weightedmean(ustrip.(CombinedData.Volume)) * givenunit
if LeakAnalysis
Adjgivenunit = unit(mean(CombinedData.AdjVolume)) #using the mean will cause errors if the units do not match
AdjTargetVolume = weightedmean(ustrip.(CombinedData.AdjVolume)) * Adjgivenunit
else
AdjTargetVolume = missing
end
return TargetVolume, AdjTargetVolume, CombinedData
end