Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

**Changes in version 5.11 (not released yet)**

- Updated the Yost/ACS algorithm to extend the second-to-last range of the "year for lookup" by one year and to implement the A,B,C,D codes that are found in other census tract lookups.
- Added 2023 calculated field for Rural Urban Continuum algorithm.
- Updated the lookup for item #194 in the PRCDA algorithm to use 2024 PRCDA counties
- Removed the 2017 calculated field from the PRCDA algorithm.
- Added missing census2020 input field to Tract-Estimated Congressional Districts; this only affects documentation, the logic was actually using the field.
- Updated dependencies.

Expand Down
2 changes: 0 additions & 2 deletions src/main/java/com/imsweb/algorithms/Algorithms.java
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ public final class Algorithms {
public static final String FIELD_IARC_MP_INDICATOR = "iarcMpIndicator";
public static final String FIELD_COUNTY_AT_DX_ANALYSIS_FLAG = "countyAtDxAnalysisFlag";
public static final String FIELD_IHS_PRCDA = "ihsPurchRefCareDeliveryArea";
public static final String FIELD_IHS_PRCDA_2017 = "ihsPurchRefCareDeliveryArea2017";
public static final String FIELD_UIHO = "urbanIndianHealthOrganization";
public static final String FIELD_UIHO_CITY = "uihoFacility";
public static final String FIELD_ACS_YOST_QUINTILE_US = "yostQuintileUS";
Expand Down Expand Up @@ -360,7 +359,6 @@ public static void initialize() {
addField(AlgorithmField.of(FIELD_IARC_MP_INDICATOR, 9400, 1, "IARC Multiple Primary Indicator", "IARC MP", DATA_LEVEL_TUMOR, false));
addField(AlgorithmField.of(FIELD_COUNTY_AT_DX_ANALYSIS_FLAG, 9440, 4, "County at DX Analysis Flag", "DX Anlys Cty Fg", DATA_LEVEL_TUMOR, false));
addField(AlgorithmField.of(FIELD_RURAL_CONT_2023, 9470, 2, "RuralUrban Continuum 2023", "Rur Urb Cont 23", DATA_LEVEL_TUMOR, false));
addField(AlgorithmField.of(FIELD_IHS_PRCDA_2017, 9970, 1, "IHS PRCDA 2017", "IHS PRCDA 2017", DATA_LEVEL_TUMOR, false));
addField(AlgorithmField.of(FIELD_ACS_YOST_QUINTILE_US, 9610, 1, "Yost Quintile (Across States)", "Yost US", DATA_LEVEL_TUMOR, false));
addField(AlgorithmField.of(FIELD_ACS_YOST_QUINTILE_STATE, 9611, 1, "Yost Quintile (State Specific)", "Yost State", DATA_LEVEL_TUMOR, false));
addField(AlgorithmField.of(FIELD_ACS_POV_ALL_RACES, 9612, 6, "ACS Pct Poverty (All Races)", "ACS Pov All", DATA_LEVEL_TUMOR, false));
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/imsweb/algorithms/StateCountyInputDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public boolean hasUnknownStateOrCounty() {
return isUnknownStateOrCounty(_addressAtDxState, _countyAtDxAnalysis);
}

public static boolean isInValidCounty(String county) {
public static boolean isInvalidCounty(String county) {
return !(isValidCounty(county) || isUnknownCounty(county));
}

Expand All @@ -66,7 +66,7 @@ public static boolean isInvalidState(String state) {
}

public static boolean isInvalidStateOrCounty(String state, String county) {
return isInvalidState(state) || isInValidCounty(county);
return isInvalidState(state) || isInvalidCounty(county);
}

public static boolean isUnknownCounty(String county) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void applyRecodes() {
_censusTract2020 = _censusTract2020 == null ? "" : _censusTract2020.trim();
}

private String getCensusTractVariable(CensusTract censusTract) {
protected String getCensusTractVariable(CensusTract censusTract) {
if (CensusTract.CENSUS_2000.equals(censusTract))
return _censusTract2000;
if (CensusTract.CENSUS_2010.equals(censusTract))
Expand All @@ -53,7 +53,7 @@ public static boolean isInvalidCensusTract(String censusTract) {
}

public static boolean isInvalidStateCountyOrCensusTract(String state, String county, String censusTract) {
return isInvalidState(state) || isInValidCounty(county) || isInvalidCensusTract(censusTract);
return isInvalidState(state) || isInvalidCounty(county) || isInvalidCensusTract(censusTract);
}

public static boolean isUnknownCensusTract(String censusTract) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,6 @@ public void initializePrcdaData(Map<String, Map<String, CountyData>> data) {
for (Map.Entry<String, CountyData> countyEntry : stateEntry.getValue().entrySet()) {
CountyData countyData = stateData.getData().computeIfAbsent(countyEntry.getKey(), k -> new CountyData());
countyData.setPrcda(countyEntry.getValue().getPrcda());
countyData.setPrcda2017(countyEntry.getValue().getPrcda2017());
}
}
}
Expand Down
9 changes: 0 additions & 9 deletions src/main/java/com/imsweb/algorithms/internal/CountyData.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ public class CountyData {

// prcda, uiho data
private String _prcda;
private String _prcda2017;
private String _uiho;
private String _uihoCity;

Expand All @@ -30,18 +29,10 @@ public String getPrcda() {
return _prcda;
}

public String getPrcda2017() {
return _prcda2017;
}

public void setPrcda(String prcda) {
_prcda = prcda;
}

public void setPrcda2017(String prcda2017) {
_prcda2017 = prcda2017;
}

public String getUiho() {
return _uiho;
}
Expand Down
4 changes: 0 additions & 4 deletions src/main/java/com/imsweb/algorithms/prcda/PrcdaAlgorithm.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import static com.imsweb.algorithms.Algorithms.FIELD_COUNTY_AT_DX_ANALYSIS;
import static com.imsweb.algorithms.Algorithms.FIELD_IHS_PRCDA;
import static com.imsweb.algorithms.Algorithms.FIELD_IHS_PRCDA_2017;
import static com.imsweb.algorithms.Algorithms.FIELD_STATE_DX;
import static com.imsweb.algorithms.prcda.PrcdaUtils.PRCDA_UNKNOWN;

Expand All @@ -29,10 +28,8 @@ public PrcdaAlgorithm() {
_inputFields.add(Algorithms.getField(FIELD_COUNTY_AT_DX_ANALYSIS));

_outputFields.add(Algorithms.getField(FIELD_IHS_PRCDA));
_outputFields.add(Algorithms.getField(FIELD_IHS_PRCDA_2017));

_unknownValues.put(FIELD_IHS_PRCDA, Collections.singletonList(PRCDA_UNKNOWN));
_unknownValues.put(FIELD_IHS_PRCDA_2017, Collections.singletonList(PRCDA_UNKNOWN));
}

@Override
Expand All @@ -48,7 +45,6 @@ public AlgorithmOutput execute(AlgorithmInput input) {

Map<String, Object> outputTumor = new HashMap<>();
outputTumor.put(FIELD_IHS_PRCDA, outputDto.getPrcda());
outputTumor.put(FIELD_IHS_PRCDA_2017, outputDto.getPrcda2017());

Utils.addTumorOutput(outputPatient, outputTumor);
}
Expand Down
29 changes: 3 additions & 26 deletions src/main/java/com/imsweb/algorithms/prcda/PrcdaDataProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,7 @@
*/
public class PrcdaDataProvider {

private enum PrcdaYear {
YR2017, YR2020;

public static PrcdaYear getDefault() {
return YR2020;
}
}

public String getPrcda(String state, String county) {
return getPrcdaData(PrcdaYear.getDefault(), state, county);
}

public String getPrcda2017(String state, String county) {
return getPrcdaData(PrcdaYear.YR2017, state, county);
}

private String getPrcdaData(PrcdaYear prcdaYear, String state, String county) {
prcdaYear = prcdaYear == null ? PrcdaYear.getDefault() : prcdaYear;

if (ENTIRE_STATE_PRCDA.contains(state))
return PRCDA_YES;
else if (ENTIRE_STATE_NON_PRCDA.contains(state))
Expand All @@ -67,10 +49,7 @@ else if (isInvalidStateOrCounty(state, county) || isUnknownStateOrCounty(state,
if (countyData == null)
return PRCDA_NO;

if (PrcdaYear.YR2017.equals(prcdaYear))
return countyData.getPrcda2017();
else
return countyData.getPrcda();
return countyData.getPrcda();
}

private Map<String, Map<String, CountyData>> loadPrcdaData() {
Expand All @@ -80,11 +59,9 @@ private Map<String, Map<String, CountyData>> loadPrcdaData() {

String state = line.getField(0);
String county = line.getField(1);
String prcda2017 = line.getField(2);
String prcda2020 = line.getField(3);
String prcda2024 = line.getField(2);
CountyData dto = result.computeIfAbsent(state, k -> new HashMap<>()).computeIfAbsent(county, k -> new CountyData());
dto.setPrcda2017(StringUtils.leftPad(prcda2017, 1, '0'));
dto.setPrcda(StringUtils.leftPad(prcda2020, 1, '0'));
dto.setPrcda(StringUtils.leftPad(prcda2024, 1, '0'));
});

return result;
Expand Down
9 changes: 0 additions & 9 deletions src/main/java/com/imsweb/algorithms/prcda/PrcdaOutputDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,12 @@
public class PrcdaOutputDto {

private String _prcda;
private String _prcda2017;

public String getPrcda() {
return _prcda;
}

public String getPrcda2017() {
return _prcda2017;
}

public void setPrcda(String str) {
_prcda = str;
}

public void setPrcda2017(String str) {
_prcda2017 = str;
}
}
12 changes: 3 additions & 9 deletions src/main/java/com/imsweb/algorithms/prcda/PrcdaUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
public final class PrcdaUtils {

public static final String ALG_NAME = "NPCR PRCDA Linkage Program";
public static final String ALG_VERSION = "version 2.2 released in June 2022";
public static final String ALG_VERSION = "July 30, 2026";

public static final String PRCDA_NO = "0";
public static final String PRCDA_YES = "1";
Expand Down Expand Up @@ -53,7 +53,7 @@ private PrcdaUtils() {
}

/**
* Calculates PRCDA and PRCDA2017 for the provided record
* Calculates PRCDA for the provided record
* <br/><br/>
* The provided record doesn't need to contain all the input variables, but the algorithm will use the following ones:
* <ul>
Expand All @@ -62,7 +62,7 @@ private PrcdaUtils() {
* </ul>
* All those properties are defined as constants in this class.
* <br/><br/>
* PRCDA and PRCDA2017 will have one the following values:
* PRCDA will have one the following values:
* 0 = Not a PRCDA county
* 1 = PRCDA county
* 9 = Unknown
Expand All @@ -77,28 +77,22 @@ public static PrcdaOutputDto computePrcda(StateCountyInputDto input) {

if (ENTIRE_STATE_PRCDA.contains(input.getAddressAtDxState())) {
result.setPrcda(PRCDA_YES);
result.setPrcda2017(PRCDA_YES);
}
else if (ENTIRE_STATE_NON_PRCDA.contains(input.getAddressAtDxState())) {
result.setPrcda(PRCDA_NO);
result.setPrcda2017(PRCDA_NO);
}
else {
if (input.hasInvalidStateOrCounty() || input.hasUnknownStateOrCounty() || input.countyIsNotReported()) {
result.setPrcda(PRCDA_UNKNOWN);
result.setPrcda2017(PRCDA_UNKNOWN);
}
else {
result.setPrcda(_PROVIDER.getPrcda(input.getAddressAtDxState(), input.getCountyAtDxAnalysis()));
result.setPrcda2017(_PROVIDER.getPrcda2017(input.getAddressAtDxState(), input.getCountyAtDxAnalysis()));
}
}

// get methods should never return null, but let's make sure we don't return null value anyway
if (result.getPrcda() == null)
result.setPrcda(PRCDA_NO);
if (result.getPrcda2017() == null)
result.setPrcda2017(PRCDA_NO);

return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
public final class RuralUrbanUtils {

public static final String ALG_NAME = "NAACCR Rural Urban Program";
public static final String ALG_VERSION = "released in September 2025";
public static final String ALG_VERSION = "July 8, 2026";

// unknown values for each code
public static final String URBAN_RURAL_INDICATOR_CODE_UNKNOWN = "C";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,54 +1,77 @@
package com.imsweb.algorithms.yostacspoverty;

public class YostAcsPovertyInputDto {
import com.imsweb.algorithms.StateCountyTractInputDto;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

private String _addressAtDxState;
import static com.imsweb.algorithms.yostacspoverty.YostAcsPovertyUtils.YOST_ACS_CENSUS_TRACT_PIVOT_YEAR;

private String _countyAtDxAnalysis;
public class YostAcsPovertyInputDto extends StateCountyTractInputDto {

private String _censusTract2010;

private String _censusTract2020;
private static final String MISSING_YEAR = "";

private String _dateOfDiagnosis;
private String _yearOfDiagnosis;

public String getAddressAtDxState() {
return _addressAtDxState;
@Override
public void applyRecodes() {
super.applyRecodes();
_dateOfDiagnosis = _dateOfDiagnosis == null ? "" : _dateOfDiagnosis.trim();
_yearOfDiagnosis = _yearOfDiagnosis == null ? "" : _yearOfDiagnosis.trim();
}

public void setAddressAtDxState(String addressAtDxState) {
_addressAtDxState = addressAtDxState;
public int computeYearOfDiagnosis() {
if (isValidYear(_yearOfDiagnosis)) {
return Integer.parseInt(_yearOfDiagnosis);
}
return -1;
}

public String getCountyAtDxAnalysis() {
return _countyAtDxAnalysis;
public String getDateOfDiagnosis() {
return _dateOfDiagnosis;
}

public void setCountyAtDxAnalysis(String countyAtDxAnalysis) {
_countyAtDxAnalysis = countyAtDxAnalysis;
public void setDateOfDiagnosis(String dateOfDiagnosis) {
_dateOfDiagnosis = dateOfDiagnosis;
_yearOfDiagnosis = dateOfDiagnosis == null ? null : StringUtils.rightPad(dateOfDiagnosis, 4).substring(0, 4).trim();
}

public String getCensusTract2010() {
return _censusTract2010;
public boolean hasInvalidStateCountyCensusTractOrYear() {
if (isInvalidState(getAddressAtDxState()) || isInvalidCounty(getCountyAtDxAnalysis()) || isInvalidYear(_yearOfDiagnosis))
return true;
// if year is missing we don't know which census tract is the right one to use, so just check both
if (isUnknownYear(_yearOfDiagnosis))
return isInvalidCensusTract(getCensusTract2010()) || isInvalidCensusTract(getCensusTract2020());
// year isn't missing, so check the census tract we'll end up using for the lookup
int dxYear = Integer.parseInt(_yearOfDiagnosis);
CensusTract censusTract = dxYear <= YOST_ACS_CENSUS_TRACT_PIVOT_YEAR ? CensusTract.CENSUS_2010 : CensusTract.CENSUS_2020;
return isInvalidCensusTract(getCensusTractVariable(censusTract));
}

public void setCensusTract2010(String censusTract2010) {
_censusTract2010 = censusTract2010;
public boolean hasUnknownStateCountyCensusTractOrYear() {
if (isUnknownState(getAddressAtDxState()) || isUnknownCounty(getCountyAtDxAnalysis()) || isUnknownYear(_yearOfDiagnosis))
return true;
// if year is invalid we don't know which census tract is the right one to use, so just check both
if (isInvalidYear(_yearOfDiagnosis))
return isUnknownCensusTract(getCensusTract2010()) || isUnknownCensusTract(getCensusTract2020());
// year isn't invalid, so check the census tract we'll end up using for the lookup
int dxYear = Integer.parseInt(_yearOfDiagnosis);
CensusTract censusTract = dxYear <= YOST_ACS_CENSUS_TRACT_PIVOT_YEAR ? CensusTract.CENSUS_2010 : CensusTract.CENSUS_2020;
return isUnknownCensusTract(getCensusTractVariable(censusTract));
}

public String getCensusTract2020() {
return _censusTract2020;
public static boolean isInvalidYear(String year) {
return !(isValidYear(year) || isUnknownYear(year));
}

public void setCensusTract2020(String censusTract2020) {
_censusTract2020 = censusTract2020;
public static boolean isUnknownYear(String year) {
return MISSING_YEAR.equals(year);
}

public String getDateOfDiagnosis() {
return _dateOfDiagnosis;
// this is private because it's meant to be more of a helper function
// I want users of this class to use the "Invalid" and "Unknown" functions
private static boolean isValidYear(String year) {
return year != null && year.length() == 4 && NumberUtils.isDigits(year);
}

public void setDateOfDiagnosis(String dateOfDiagnosis) {
_dateOfDiagnosis = dateOfDiagnosis;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ public String getYostQuintileUS() {
return _yostQuintileUS;
}

public void setAllFields(String value) {
_yostQuintileUS = value;
_yostQuintileState = value;
_acsPctPovAllRaces = value;
_acsPctPovWhite = value;
_acsPctPovBlack = value;
_acsPctPovAIAN = value;
_acsPctPovAsianNHOPI = value;
_acsPctPovWhiteNonHisp = value;
_acsPctPovHispanic = value;
}

public void setYostQuintileUS(String yostQuintileUS) {
_yostQuintileUS = yostQuintileUS;
}
Expand Down
Loading
Loading