Changeset 1957


Ignore:
Timestamp:
Apr 30, 2013, 10:04:56 AM (9 years ago)
Author:
olle
Message:

Refs #487. First version of the INCA export.

Location:
extensions/net.sf.basedb.reggie/trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • extensions/net.sf.basedb.reggie/trunk/resources/index.jsp

    r1953 r1957  
    341341            <ul>
    342342            <li><a href="personal/export_monthly_oplist.jsp?ID=<%=ID%>">Export monthly operation list</a>
     343            <li><a href="personal/export_inca.jsp?ID=<%=ID%>">INCA export</a>
    343344            </ul>
    344345          </dd>
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/ExportServlet.java

    r1741 r1957  
    55import java.util.Calendar;
    66import java.util.Date;
     7import java.util.HashMap;
    78import java.util.List;
    89import java.util.Set;
     
    2021import net.sf.basedb.core.DbControl;
    2122import net.sf.basedb.core.ItemQuery;
     23import net.sf.basedb.core.ItemSubtype;
     24import net.sf.basedb.core.MeasuredBioMaterial;
    2225import net.sf.basedb.core.Sample;
    2326import net.sf.basedb.core.SessionControl;
     
    5760    try
    5861    {
    59       if ("ExportMonthlyOpList".equals(cmd))
     62      if ("ExportMonthlyOpList".equals(cmd) || "ExportINCA".equals(cmd))
    6063      {
    6164        boolean exportSubtype = Values.getBoolean(req.getParameter("exportSubtype"));
     
    6467        // This can be any time point in the desired month/year
    6568        long timeInMillis = Values.getLong(req.getParameter("time"));
    66         // Negative value indicate that we should load the whole year
     69        // A value of 1 (1970.01.01 00:00:00 001) indicates no time restriction
     70        boolean allSamples = (timeInMillis == 1);
     71        // Negative value indicates that we should load the whole year
    6772        boolean fullYear = timeInMillis < 0;
    6873        timeInMillis = Math.abs(timeInMillis);
     
    9398        // ...that has a creation date (=operation date) between the start and end time points
    9499        specimenQuery.join(Hql.innerJoin(null, "creationEvent", "ce", true));
    95         specimenQuery.restrict(Restrictions.gteq(Hql.property("ce", "eventDate"), Expressions.parameter("start", start)));
    96         specimenQuery.restrict(Restrictions.lt(Hql.property("ce", "eventDate"), Expressions.parameter("end", end)));
    97        
    98         // FETCH JOIN of CASE and PATIENT + the CASE creation event
    99         // for performance reasons
    100         specimenQuery.join(Hql.innerJoin(null, "parent", "cse", true));
    101         specimenQuery.join(Hql.innerJoin("cse", "creationEvent", "ce2", true));
    102         specimenQuery.join(Hql.innerJoin("cse", "parent", "pat", true));
    103        
    104         // ...only include 'Specimen' or 'NoSpecimen' items
    105         specimenQuery.restrict(
    106           Restrictions.or(
    107             Subtype.SPECIMEN.restriction(dc, null),
    108             Subtype.NO_SPECIMEN.restriction(dc, null)
    109           ));
     100        if (!allSamples)
     101        {
     102          specimenQuery.restrict(Restrictions.gteq(Hql.property("ce", "eventDate"), Expressions.parameter("start", start)));
     103          specimenQuery.restrict(Restrictions.lt(Hql.property("ce", "eventDate"), Expressions.parameter("end", end)));
     104        }
     105
     106        if ("ExportMonthlyOpList".equals(cmd))
     107        {
     108          // FETCH JOIN of CASE and PATIENT + the CASE creation event
     109          // for performance reasons
     110          specimenQuery.join(Hql.innerJoin(null, "parent", "cse", true));
     111          specimenQuery.join(Hql.innerJoin("cse", "creationEvent", "ce2", true));
     112          specimenQuery.join(Hql.innerJoin("cse", "parent", "pat", true));
     113         
     114          // ...only include 'Specimen' or 'NoSpecimen' items
     115          specimenQuery.restrict(
     116            Restrictions.or(
     117              Subtype.SPECIMEN.restriction(dc, null),
     118              Subtype.NO_SPECIMEN.restriction(dc, null)
     119            ));
     120        }
     121        else if ("ExportINCA".equals(cmd))
     122        {
     123          // ...include 'Specimen', 'NoSpecimen', and 'Blood' items
     124          specimenQuery.restrict(
     125            Restrictions.or(
     126              Subtype.SPECIMEN.restriction(dc, null),
     127              Subtype.NO_SPECIMEN.restriction(dc, null),
     128              Subtype.BLOOD.restriction(dc, null)
     129            ));
     130        }
    110131       
    111132        List<Sample> samples = specimenQuery.list(dc);
     
    116137        Set<PersonalOpDate> opDates = new TreeSet<PersonalOpDate>();
    117138        Pattern caseNamePattern = Pattern.compile("\\..*"); // Pattern to strip suffix from case name (eg. everything after first '.')
    118         for (Sample s : samples)
    119         {
    120           // Check the BiopsyType annotation
    121           // We should only export those with 'SpecimenSurgery' or a missing value
    122           String biopsyType = (String)Annotationtype.BIOPSY_TYPE.getAnnotationValue(dc, manager, s);
    123          
    124           if (biopsyType == null || biopsyType.equals("SpecimenSurgery"))
     139        if ("ExportMonthlyOpList".equals(cmd))
     140        {
     141          for (Sample s : samples)
    125142          {
    126             // The parent is the 'Case' and the grandparent is the 'Patient'
    127             // Ignore samples that don't have parent items
    128             BioMaterial theCase = s.getParent();
    129             if (theCase instanceof Sample)
    130             {
    131               BioMaterial patient = ((Sample)theCase).getParent();
    132               if (patient instanceof BioSource)
    133               {
    134                 // Get the personal number of the patient
    135                 String pnr = (String)Annotationtype.PERSONAL_NUMBER.getAnnotationValue(dc, manager, patient);
    136 
    137                 if (pnr != null)
    138                 {
    139                   // Finally, we now have the information that should be exported
    140                   Site site = Site.findByCaseName(s.getName());
    141                   String laterality = (String)Annotationtype.LATERALITY.getAnnotationValue(dc, manager, theCase);
    142                   String consent = (String)Annotationtype.CONSENT.getAnnotationValue(dc, manager, theCase);
    143                   String opDate = dateFormat.format(s.getCreationEvent().getEventDate());
    144                   String subtype = exportSubtype ? s.getItemSubtype().getName() : null;
    145                   String patientId = exportPatientId ? patient.getName() : null;
    146                   String caseName = caseNamePattern.matcher(s.getName()).replaceFirst("");
    147                   opDates.add(new PersonalOpDate(pnr, opDate, site, laterality, subtype, caseName, consent, patientId));
     143            // Check the BiopsyType annotation
     144            // We should only export those with 'SpecimenSurgery' or a missing value
     145            String biopsyType = (String)Annotationtype.BIOPSY_TYPE.getAnnotationValue(dc, manager, s);
     146           
     147            if (biopsyType == null || biopsyType.equals("SpecimenSurgery"))
     148            {
     149              // The parent is the 'Case' and the grandparent is the 'Patient'
     150              // Ignore samples that don't have parent items
     151              BioMaterial theCase = s.getParent();
     152              if (theCase instanceof Sample)
     153              {
     154                BioMaterial patient = ((Sample)theCase).getParent();
     155                if (patient instanceof BioSource)
     156                {
     157                  // Get the personal number of the patient
     158                  String pnr = (String)Annotationtype.PERSONAL_NUMBER.getAnnotationValue(dc, manager, patient);
     159
     160                  if (pnr != null)
     161                  {
     162                    // Finally, we now have the information that should be exported
     163                    Site site = Site.findByCaseName(s.getName());
     164                    String laterality = (String)Annotationtype.LATERALITY.getAnnotationValue(dc, manager, theCase);
     165                    String consent = (String)Annotationtype.CONSENT.getAnnotationValue(dc, manager, theCase);
     166                    String opDate = dateFormat.format(s.getCreationEvent().getEventDate());
     167                    String subtype = exportSubtype ? s.getItemSubtype().getName() : null;
     168                    String patientId = exportPatientId ? patient.getName() : null;
     169                    String caseName = caseNamePattern.matcher(s.getName()).replaceFirst("");
     170                    opDates.add(new PersonalOpDate(pnr, opDate, site, laterality, subtype, caseName, consent, patientId));
     171                  }
    148172                }
    149173              }
     
    151175          }
    152176        }
    153        
     177        else if ("ExportINCA".equals(cmd))
     178        {
     179          // Get item subtype constants for later use
     180          ItemSubtype subtypeSpecimen = Subtype.SPECIMEN.load(dc);
     181          ItemSubtype subtypeNoSpecimen = Subtype.NO_SPECIMEN.load(dc);
     182          ItemSubtype subtypeBlood = Subtype.BLOOD.load(dc);
     183
     184          // Step 1: Store up to two entries for each patient, one for each laterality
     185          //         represented by a Specimen/NoSpecimen, or if no Specimen or
     186          //         NoSpecimen exists, a blood sample. Priority Specimen > NoSpecimen > Blood.
     187          HashMap<String,Sample> patientNumberSampleLeftHashMap = new HashMap<String,Sample>();
     188          HashMap<String,Sample> patientNumberSampleRightHashMap = new HashMap<String,Sample>();
     189          for (Sample s : samples)
     190          {
     191            // Find patient id
     192            BioMaterial theCase = null;
     193            BioMaterial patient = null;
     194            String laterality = null;
     195            if (s.getItemSubtype().equals(subtypeBlood))
     196            {
     197              // The parent is the 'Patient' for blood samples and cases
     198              patient = s.getParent();
     199            }
     200            else if (s.getItemSubtype().equals(subtypeSpecimen) || s.getItemSubtype().equals(subtypeNoSpecimen))
     201            {
     202              // The parent is the 'Case' and the grandparent is the 'Patient' for specimens and no specimens
     203              theCase = (MeasuredBioMaterial) s.getParent();
     204              if (theCase != null && theCase instanceof Sample)
     205              {
     206                patient = ((Sample)theCase).getParent();
     207                laterality = (String)Annotationtype.LATERALITY.getAnnotationValue(dc, manager, theCase);
     208              }
     209            }
     210
     211            if (patient instanceof BioSource)
     212            {
     213              // Check if patient number exists in hash map
     214              String patientNumber = patient.getName();
     215              if (patientNumber != null)
     216              {
     217                if (laterality != null && laterality.equals("LEFT"))
     218                {
     219                  // Optional update of hash map for left laterality
     220                  patientNumberSampleLeftHashMap = updatePatientNumberSampleHashMap(dc, manager,
     221                      patientNumberSampleLeftHashMap, patientNumber, s, laterality);
     222                }
     223                else if (laterality != null && laterality.equals("RIGHT"))
     224                {
     225                  // Optional update of hash map for right laterality
     226                  patientNumberSampleRightHashMap = updatePatientNumberSampleHashMap(dc, manager,
     227                      patientNumberSampleRightHashMap, patientNumber, s, laterality);
     228                }
     229                else if (laterality == null || laterality.equals(""))
     230                {
     231                  // We do not know what the laterality is (if any),
     232                  // so both hash maps are updated.
     233                  patientNumberSampleLeftHashMap = updatePatientNumberSampleHashMap(dc, manager,
     234                      patientNumberSampleLeftHashMap, patientNumber, s, laterality);
     235                  patientNumberSampleRightHashMap = updatePatientNumberSampleHashMap(dc, manager,
     236                      patientNumberSampleRightHashMap, patientNumber, s, laterality);
     237                }
     238              }
     239            }
     240          }
     241
     242          // Step 2: Export up to two entries for each patient, with priority Specimen > NoSpecimen > Blood
     243          for (Sample s : samples)
     244          {
     245            // Check if sample stored for patient number
     246            if (!patientNumberSampleLeftHashMap.containsValue(s) && !patientNumberSampleRightHashMap.containsValue(s))
     247            {
     248              continue;
     249            }
     250            // Find patient id
     251            BioMaterial theCase = null;
     252            BioMaterial patient = null;
     253            if (s.getItemSubtype().equals(subtypeBlood))
     254            {
     255              // The parent is the 'Patient' for blood samples and cases
     256              patient = s.getParent();
     257              // Only include blood sample if both samples for
     258              // left and right laterality are blood samples
     259              Sample sampleLeft = patientNumberSampleLeftHashMap.get(patient.getName());
     260              Sample sampleRight = patientNumberSampleRightHashMap.get(patient.getName());
     261              if (sampleLeft == null || !sampleLeft.getItemSubtype().equals(subtypeBlood))
     262              {
     263                continue;
     264              }
     265              else if (sampleRight == null || !sampleRight.getItemSubtype().equals(subtypeBlood))
     266              {
     267                continue;
     268              }
     269            }
     270            else if (s.getItemSubtype().equals(subtypeSpecimen) || s.getItemSubtype().equals(subtypeNoSpecimen))
     271            {
     272              // The parent is the 'Case' and the grandparent is the 'Patient' for specimens and no specimens
     273              theCase = (MeasuredBioMaterial) s.getParent();
     274              if (theCase != null && theCase instanceof Sample)
     275              {
     276                patient = ((Sample)theCase).getParent();
     277              }
     278            }
     279
     280            if (patient instanceof BioSource)
     281            {
     282              // Get the personal number of the patient
     283              String pnr = (String)Annotationtype.PERSONAL_NUMBER.getAnnotationValue(dc, manager, patient);
     284
     285              if (pnr != null)
     286              {
     287                // Finally, we now have the information that should be exported
     288                Site site = Site.findByCaseName(s.getName());
     289                String laterality = null;
     290                String consent = null;
     291                if (theCase != null)
     292                {
     293                  laterality = (String)Annotationtype.LATERALITY.getAnnotationValue(dc, manager, theCase);
     294                  // For specimen and no specimen samples, consent is coupled to the case
     295                  consent = (String)Annotationtype.CONSENT.getAnnotationValue(dc, manager, theCase);
     296                }
     297                else
     298                {
     299                  // For blood samples, consent is coupled to the sample
     300                  consent = (String)Annotationtype.CONSENT.getAnnotationValue(dc, manager, s);
     301                }
     302                String opDate = dateFormat.format(s.getCreationEvent().getEventDate());
     303                String subtype = exportSubtype ? s.getItemSubtype().getName() : null;
     304                String patientId = exportPatientId ? patient.getName() : null;
     305                String caseName = caseNamePattern.matcher(s.getName()).replaceFirst("");
     306                if (subtype.equals("Blood"))
     307                {
     308                  subtype = "BloodOnly";
     309                }
     310                opDates.add(new PersonalOpDate(pnr, opDate, site, laterality, subtype, caseName, consent, patientId));
     311              }
     312            }
     313          }
     314        }
     315
     316        // Default settings for monthly operation list export
     317        String filenamePrefix = "opdates-";
     318        String tableHeaderStart = "PersonalNr\tScanBId\tOpDate\tLaterality\tSite";
    154319        DateFormatter monthFormat = new DateFormatter(fullYear ? "yyyy-'all'" : "yyyy-MM");
    155         resp.setHeader("Content-Disposition", "attachment; filename=opdates-" + monthFormat.format(start) + ".tsv");
     320        String dateString = monthFormat.format(start);
     321        if (allSamples)
     322        {
     323          // Set date string to period from 2010 to current month
     324          Date today = new Date();
     325          dateString = "2010-" + monthFormat.format(today);
     326        }
     327        if ("ExportINCA".equals(cmd))
     328        {
     329          filenamePrefix = "incaexport-";
     330          tableHeaderStart = "PersonalNo\tScanBId\tDate\tLaterality\tSite";
     331        }
     332        // Write export file
     333        resp.setHeader("Content-Disposition", "attachment; filename=" + filenamePrefix + dateString + ".tsv");
    156334        resp.setContentType("text/plain");
    157335        resp.setCharacterEncoding("UTF-8");
    158336        PrintWriter os = resp.getWriter();
    159         os.write("PersonalNr\tScanBId\tOpDate\tLaterality\tSite");
    160         if (exportSubtype) os.write("\tSpecimen");
     337        os.write(tableHeaderStart);
     338        if (exportSubtype) os.write("\tSample");
    161339        if (exportPatientId) os.write("\tPatientId");
    162340        os.write("\tConsent\n");
     
    183361   
    184362  }
     363
     364  private HashMap<String, Sample> updatePatientNumberSampleHashMap(
     365      DbControl dc, SnapshotManager manager,
     366      HashMap<String, Sample> patientNumberSampleHashMap, String patientNumber,
     367      Sample s, String laterality)
     368  {
     369    // Get item subtype constants
     370    ItemSubtype subtypeSpecimen = Subtype.SPECIMEN.load(dc);
     371    ItemSubtype subtypeNoSpecimen = Subtype.NO_SPECIMEN.load(dc);
     372    ItemSubtype subtypeBlood = Subtype.BLOOD.load(dc);
     373    // Sample data retrieval
     374    Sample storedSample = null;
     375    ItemSubtype storedSampleSubtype = null;
     376    String storedSampleLaterality = null;
     377    if (patientNumberSampleHashMap.containsKey(patientNumber))
     378    {
     379      storedSample = (Sample) patientNumberSampleHashMap.get(patientNumber);
     380      storedSampleSubtype = storedSample.getItemSubtype();
     381      if (storedSampleSubtype.equals(subtypeSpecimen) || storedSampleSubtype.equals(subtypeNoSpecimen))
     382      {
     383        // The parent is the 'Case' for specimens and no specimens
     384        BioMaterial curCase = (MeasuredBioMaterial) storedSample.getParent();
     385        if (curCase != null && curCase instanceof Sample)
     386        {
     387          storedSampleLaterality = (String)Annotationtype.LATERALITY.getAnnotationValue(dc, manager, curCase);
     388        }
     389      }
     390    }
     391    // Update section
     392    if (storedSampleSubtype == null)
     393    {
     394      // Patient number not in hash map, store sample
     395      patientNumberSampleHashMap.put(patientNumber, s);
     396    }
     397    else if (storedSampleSubtype.equals(subtypeSpecimen))
     398    {
     399      if (s.getItemSubtype().equals(subtypeSpecimen))
     400      {
     401        // Replace stored entry if sample has laterality and stored sample does not
     402        // If laterality equal, store sample if specimen with earlier date
     403        if ((storedSampleLaterality == null || storedSampleLaterality.equals(""))
     404            && (laterality != null && !laterality.equals("")))
     405        {
     406          patientNumberSampleHashMap.put(patientNumber, s);
     407        }
     408        else if (s.getCreationEvent().getEventDate().before(storedSample.getCreationEvent().getEventDate()))
     409        {
     410          patientNumberSampleHashMap.put(patientNumber, s);
     411        }
     412      }
     413    }
     414    else if (storedSampleSubtype.equals(subtypeNoSpecimen))
     415    {
     416      // Replace stored entry if sample equals specimen
     417      if (s.getItemSubtype().equals(subtypeSpecimen))
     418      {
     419        patientNumberSampleHashMap.put(patientNumber, s);
     420      }
     421      else if (s.getItemSubtype().equals(subtypeNoSpecimen))
     422      {
     423        // Replace stored entry if sample has laterality and stored sample does not
     424        // If laterality equal, store sample if specimen with earlier date
     425        if ((storedSampleLaterality == null || storedSampleLaterality.equals(""))
     426            && (laterality != null && !laterality.equals("")))
     427        {
     428          patientNumberSampleHashMap.put(patientNumber, s);
     429        }
     430        else if (s.getCreationEvent().getEventDate().before(storedSample.getCreationEvent().getEventDate()))
     431        {
     432          patientNumberSampleHashMap.put(patientNumber, s);
     433        }
     434      }
     435    }
     436    else if (storedSampleSubtype.equals(subtypeBlood))
     437    {
     438      // Replace stored entry if sample equals specimen or no specimen
     439      if (s.getItemSubtype().equals(subtypeSpecimen)
     440          || s.getItemSubtype().equals(subtypeNoSpecimen))
     441      {
     442        patientNumberSampleHashMap.put(patientNumber, s);
     443      }
     444      else if (s.getItemSubtype().equals(subtypeBlood))
     445      {
     446        // Store sample if blood sample with earlier date
     447        if (s.getCreationEvent().getEventDate().before(storedSample.getCreationEvent().getEventDate()))
     448        {
     449          patientNumberSampleHashMap.put(patientNumber, s);
     450        }
     451      }
     452    }
     453    return patientNumberSampleHashMap;
     454  }
     455
    185456
    186457  class PersonalOpDate
Note: See TracChangeset for help on using the changeset viewer.