Content uniformity

edited April 2019
how create a custom field to calculate content uniformity( Acceptance value) in EMPOWER3?
give me details about the formula and the parameters of the CF .
M=X̅ if  98.5%≤ X̅≥101.5%
M= 98.5% if X̅<98.5%
M= 101.5% if X̅>101.5%
for 10 tablets

• This would get a bit messy as you need to do a logic test (if/then) on where the mean sits.  Then, using the appropriate M based on the mean, you have a final reported value.  Start by substituting the variables from the USP formula with the names for the fields Empower would use.

You'll need a few different fields:
Field 1, sample field for data entry of label claim...let's call it "LabelClaim"
Field 2, "%LabelClaim" this is a calculated peak field with the formula: Amount/LabelClaim*100
Field 3, this becomes a messy field to do it all at once, so here goes without any testing to confirm:

ABS(98.5*LT(ROUND(SAME…AVE(%LabelClaim), -1), 98.5)+ 101.5* GT(ROUND(SAME…AVE(%LabelClaim), -1), 101.5)+ SAME…AVE(%LabelClaim)*GTE(ROUND(SAME…AVE(%LabelClaim), -1), 98.5)*LTE(ROUND(SAME…AVE(%LabelClaim), -1), 101.5)- SAME…AVE(%LabelClaim))+(2.4* %RSD(SAME…AVE(%LabelClaim))*SAME…AVE(%LabelClaim)/100)

I don't see a standard deviation summary function in Empower, so I've gotten around that with taking the %RSD and back-calculating the standard deviation.

• where in this case n=10

If further evaluation required where n=30 CF does get complicated

If amount quantified in empower then CF required will be mean , stdev and CU for n=10, then create a CF for AV= CU_10+2.4*Std_Dev

with labels for sample are the same

mean = SAME.1..AVE(amount)

Std_dev = %rsd*mean (as above)

Above formula will work but breaking this down makes testing some what simpler

ie

ABS(98.5*LT(mean,98.5)+101.5*GT(mean,101.5)+mean*GTE(mean,98.5)*LTE(mean,101.5)-mean

check out Informs 2017 app . this also gives information on CF for 10 and 30 tablets

• You could also create a peak enum calculated cf and set it to use as position. Have each condition contained within such that ENUM(LT(Std_Dev,98.5),RANGE(Std_Dev,98.5,101.2),GT(Std_Dev,101.2)) and then a further cf using the position so that if you called the first cf "Content_Range" then create a peak real cf like EQ(Content_Range,0)*((ABS(Std_Dev-Average_Content)*100))+EQ(Content_Range,1)*Average_Content+EQ(Content_Range,2)*((Std_Dev+Average_Content)*100) or something similar to match the arguments with the output.
• edited May 2019

This is relatively easy to accomplish.

Break it down so you have a CF for every value you need to calculate.

Acceptance Value then becomes: ABS(M-Average_LC)+(K_Value*STDEV_LC)

Your n=10 or n=30 can then become: ENUM((EQ(Stage,1)&LT(Acceptance_Value,15.0)), (EQ(Stage,2)&LT(Acceptance_Value,15.0)&RANGE(Average_LC,0.75*M,1.25*M)), (EQ(Stage,1)&GT(Acceptance_Value,15.0)), (EQ(Stage,2)&GT(Acceptance_Value,15.0)), (EQ(Stage,2)&LT(Average_LC,0.75*M)|EQ(Stage,2)&GT(Average_LC,1.25*M)))

The translations on the ENUM field above are a simple pass / pass / fail. test 20 more / fail / fail.

Works like a treat

• Biggest challenge here is validating the CF formulae and processing data to obtain various sample data ie Mean range <98.5, >101.5 or X=M for N=10 and N=30 but depends on internal SOP/ procedures
• I've always taken the approach not to validate the logic, but verify the individual parameters and the end result.

When I developed the code I was able to find a stage 1 pass, stage 1 fail, stage 2 pass, and stage 2 fail. Historical data was able to help me find results that were borderline for stage 1 and 2 to use in testing.

The code I posted was written quite a while ago. There may be more elegant ways to tackle this now. However, if its not broken, then don't fix it!

• shaunwat ,

indeed no need to refine this if CF works as is

on that note if n=10 fails (one sample set) then a further n=20 is tested (second sample set) I guess the only option is to 'process only sample set ' to evaluate AV for n=30 for L2 = 25.0 ?

• Hi ydan,

Yes, that is correct. If you generate a failure at n=10 and need to test more, then the only option to generate the correct n=30 data is to combine the two sample sets into a process only sample set.

• This exact scenario and how to use custom fields to perform content uniformity was covered in Waters Inform 2018, google the article or else I can attach it via PM if you need. The only thing that concerned me was some of the peak enum custom fields were very long and had lots of nesting within it,which is not really recommended by Waters (nesting up to 8 levels is the max they recommend) so I wouldn't be using it in projects with non-content uniformity samples as the processing speeds will be very slow.
• Yes, as I believe you can gather I used very little nested functions in my approach. I seen examples online in various forums where people have tried to do this using a single custom field. That is a recipe for disaster in my opinion.

However, it would have been good to have a short cut / cheat / example to follow when I originally did this. I believe I first developed this approach back in 2013-2014, which was around the same time that I tackled dissolution calculations without the dissolution option (that was a fun exercise!).

• There is a presentation (perhaps from Inform2018?) about content uniformity calculations. Perhaps someone has a PDF at hand.
• Here's how I've handled it-
USP_AV: ABS(-1*Ave_PercentClaim+M)+k*SD
L2Range: GTE(PercentClaim,(0.75*M))&LTE(PercentClaim,(1.25*M))
this is a calculated boolean where 0 translates to Outside L2 (25) Range and 1 translates to Within L2 (25) Range (so it's telling you whether there's any point to trying 20 more units if AV>15)
M: GT(AVE_PercentClaim,101.5)*101.5+LT(AVE_PercentClaim,98.5)*98.5+RANGE(AVE_PercentClaim, 98.5, 101.5)*AVE_PercentClaim
SD: SAME.%..%RSD(PercentClaim)*Ave_PercentClaim/100
k: boolean function that defaults to 0 (which translates to 2.4, and 1 translates to 2)

I'll assume users of this will already have appropriate dependent CFs corresponding to PercentClaim, AVE_PercentClaim etc.

• Here is another way to do it that again seems really long and complex but its all there if you have the time to create and test the custom fields:

• As well as the hands on training/tutorial from Inform 2018, at Inform 2017 a customer presented another solution for this.
• so for validation check AV value to say 14DP ?

then logic been Pass L1, Test 20 units ,Pass L2,Fail L2, failed

CU can be reduced to 6 CF and not 21 as shown in document

The main frustration here is that you have to process results to retrieve CF results

• Just type the assay results in Excel and check the criteria?
• agreed , but to show comparison to excel Empower sample set (once dilution manipulated to achaive required mean result) needs to be processed

So to test all five logics (or 6 if n=10 or n=30 fo rsome reason) then 6 results sets are required (sample set as a cf test run)

• Here is another way to do it that again seems really long and complex but its all there if you have the time to create and test the custom fields:

Hello,
In your algorithm absent describe of  “Weight_Percent_As_Is” field.
Could you please describe it for me.
• Hi ,

As discussed earlier the number of CF can be reduced to 8  with 1 user input

• I will provide the answer to this so that you can easily perform the calculation using Empower and I have validated it as well.

1.  The AV value has a challenge here: M=X̅ if 98.5%≤ X̅≥101.5%
Even if you enumerate a custom field that part of it is a no go but think about in that the value of |M-X̅| will always collapse to zero!

I set up the following custom fields
(CF1) AV = Mv * |M- X̅|+ ks
(CF2 is Enum) M = 0 if  98.5%≤ X̅≥101.5%
M= 98.5% if X̅<98.5%
M= 101.5% if X̅>101.5%
(CF3 is ENUM)  Mv = 0 if  98.5%≤ X̅≥101.5%
Mv = 1 if X̅<98.5%
Mv = 1 if X̅>101.5%
(CF4)  s = (RSD * X̅)/100
(CF5)  k = 2.4 if Count of data points = 10
k = 2.0 if Count of data points = 30

Now because Std Dev is not a function available for a custom field in Empower we use CF4

Also notice that (1 * |M-X̅|) = |M-X̅| ! Anythinh below 98.5 or above 101.5 is calculated correctly.
and
(0 * |0-X̅|) = 0*|-X̅| = 0*X̅ = 0!  This is what |M-X̅| would be for any mean value.

The challenge has always been for getting Empower to understand the reasoning behind the criteria and since  M=X̅ if 98.5%≤ X̅≥101.5% is not possible you collapse that value to zero with a multiplier of 0 while using 1 as a multiplier for the other two conditions.

If you need help with the creating these functions in Empower please reach out to me.

Arthur Sergi

• The PDF presentation above is extremely complicated and requires user input.  In addition, there is an inherent weakness which is the same as my solution regarding the k value.  Why would a user not select 10 or 30 results and report those thus providing no result?
• indeed ,, ,These CF can then be reduced to 4 CF's if only for first term
• edited October 2022
asergi said:
I will provide the answer to this so that you can easily perform the calculation using Empower and I have validated it as well.

1.  The AV value has a challenge here: M=X̅ if 98.5%≤ X̅≥101.5%
Even if you enumerate a custom field that part of it is a no go but think about in that the value of |M-X̅| will always collapse to zero!

I set up the following custom fields
(CF1) AV = Mv * |M- X̅|+ ks
(CF2 is Enum) M = 0 if  98.5%≤ X̅≥101.5%
M= 98.5% if X̅<98.5%
M= 101.5% if X̅>101.5%
(CF3 is ENUM)  Mv = 0 if  98.5%≤ X̅≥101.5%
Mv = 1 if X̅<98.5%
Mv = 1 if X̅>101.5%
(CF4)  s = (RSD * X̅)/100
(CF5)  k = 2.4 if Count of data points = 10
k = 2.0 if Count of data points = 30

Now because Std Dev is not a function available for a custom field in Empower we use CF4

Also notice that (1 * |M-X̅|) = |M-X̅| ! Anythinh below 98.5 or above 101.5 is calculated correctly.
and
(0 * |0-X̅|) = 0*|-X̅| = 0*X̅ = 0!  This is what |M-X̅| would be for any mean value.

The challenge has always been for getting Empower to understand the reasoning behind the criteria and since  M=X̅ if 98.5%≤ X̅≥101.5% is not possible you collapse that value to zero with a multiplier of 0 while using 1 as a multiplier for the other two conditions.

If you need help with the creating these functions in Empower please reach out to me.

Arthur Sergi

How did u create CF5 for k value please?
• I just made k a default of 2.4 with 2.0 as the alternate option when I wrote similar CFs (user keyboard input, sample property - I think). The real challenge is what to do when your target API amount is not 100% of LC (and this does happen for some drugs). It is also "fun" trying to get Empower to report just 1 instance of the AV result when there are 10 or 30 lines in your result table - several approaches, all with different potential issues.
• MJS said:
This would get a bit messy as you need to do a logic test (if/then) on where the mean sits.  Then, using the appropriate M based on the mean, you have a final reported value.  Start by substituting the variables from the USP formula with the names for the fields Empower would use.

You'll need a few different fields:
Field 1, sample field for data entry of label claim...let's call it "LabelClaim"
Field 2, "%LabelClaim" this is a calculated peak field with the formula: Amount/LabelClaim*100
Field 3, this becomes a messy field to do it all at once, so here goes without any testing to confirm:

ABS(98.5*LT(ROUND(SAME…AVE(%LabelClaim), -1), 98.5)+ 101.5* GT(ROUND(SAME…AVE(%LabelClaim), -1), 101.5)+ SAME…AVE(%LabelClaim)*GTE(ROUND(SAME…AVE(%LabelClaim), -1), 98.5)*LTE(ROUND(SAME…AVE(%LabelClaim), -1), 101.5)- SAME…AVE(%LabelClaim))+(2.4* %RSD(SAME…AVE(%LabelClaim))*SAME…AVE(%LabelClaim)/100)

I don't see a standard deviation summary function in Empower, so I've gotten around that with taking the %RSD and back-calculating the standard deviation.

For Field 3: Please say field type and data type.