r424 - in trunk: coser-business/src/main/java/fr/ifremer/coser/services coser-ui/src/main/java/fr/ifremer/coser/ui/common
Author: chatellier Date: 2010-12-16 17:22:30 +0000 (Thu, 16 Dec 2010) New Revision: 424 Log: Modify length structure graph using matrix proxy and provider (less memory usage / java heap space for big matrix) Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/services/ProjectService.java trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/common/DataHandler.java Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/services/ProjectService.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/services/ProjectService.java 2010-12-15 17:59:14 UTC (rev 423) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/services/ProjectService.java 2010-12-16 17:22:30 UTC (rev 424) @@ -62,8 +62,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.math.util.MathUtils; +import org.nuiton.math.matrix.DimensionHelper; import org.nuiton.math.matrix.MatrixFactory; import org.nuiton.math.matrix.MatrixND; +import org.nuiton.math.matrix.MatrixProvider; import fr.ifremer.coser.CoserBusinessConfig; import fr.ifremer.coser.CoserBusinessException; @@ -2279,11 +2281,14 @@ * Calcul. Sommer TAILLES$Nombres par classe de longueur (TAILLES$Longueur) * sur tous les traits d'une année (ou tous les années si regroupé) * + * * @param project project * @param dataContainer data container * @return matrix 4 dimension + * + * @deprecated replaced by matrix proxy */ - public MatrixND getLengthStructure(Project project, AbstractDataContainer dataContainer) { + public MatrixND getLengthStructureNonProxy(Project project, AbstractDataContainer dataContainer) { // load map traitname > stratename Map<String, String> haulAndStratas = new HashMap<String, String>(); @@ -2455,8 +2460,239 @@ return matrix; } + + /** + * Présentation du graphique : histogramme de distribution en tailles par + * espèce, par strate et par année (une planche par espèce et par année) + * pour toute la série. Avec la possibilité de voir regroupé l'ensemble des + * années. + * + * Données. TAILLES$Nombres et TAILLES$Longueur + * Calcul. Sommer TAILLES$Nombres par classe de longueur (TAILLES$Longueur) + * sur tous les traits d'une année (ou tous les années si regroupé) + * + * Second version : matrix proxy et provider. + * + * @param project project + * @param dataContainer data container + * @return matrix proxy with 4 dimension + */ + public MatrixND getLengthStructure(Project project, AbstractDataContainer dataContainer) { + // load map traitname > stratename + Map<String, String> haulAndStratas = new HashMap<String, String>(); + Iterator<String[]> itHaul = dataContainer.getHaul().iterator(); + itHaul.next(); // skip header + while (itHaul.hasNext()) { + String[] tuple = itHaul.next(); + String haul = tuple[Haul.INDEX_HAUL]; + String strataName = tuple[Haul.INDEX_STRATUM]; + haulAndStratas.put(haul, strataName); + } + + // dimensions + Set<Double> lengthSet = new HashSet<Double>(); + Set<String> speciesSet = new HashSet<String>(); + Set<String> strataSet = new HashSet<String>(); + Set<String> yearsSet = new HashSet<String>(); + + Iterator<String[]> itData = dataContainer.getLength().iterator(); + itData.next(); // skip header + while (itData.hasNext()) { + String[] tuple = itData.next(); + + String year = tuple[Length.INDEX_YEAR]; + String haul = tuple[Length.INDEX_HAUL]; + String species = tuple[Length.INDEX_SPECIES]; + String lengthAsString = tuple[Length.INDEX_LENGTH]; + String strata = haulAndStratas.get(haul); + + if (strata == null) { + if (log.isWarnEnabled()) { + log.warn("No strata for haul " + haul); + } + continue; + } + + // remember for matrix spemantics + speciesSet.add(species); + strataSet.add(strata); + yearsSet.add(year); + + // get correct length step + // plain or half centimeters + try { + double length = Double.parseDouble(lengthAsString); + + // get length step to use + double ceil = Math.ceil(length); + double floor = Math.floor(length); + // ne pas prendre 0.5 car 10.0 serait arrondit à 10.5 + double round = Math.floor(length + 0.499999); + + // on prend le pas ou demi pas le plus proche + if (ceil == round) { + length = floor + 0.5; + } + else { + length = floor; + } + + lengthSet.add(length); + } + catch (NumberFormatException ex) { + if (log.isWarnEnabled()) { + log.warn("Can't parse length as double : " + lengthAsString); + } + } + } + + // convert map to matrixND + List<Double> lengthSem = new ArrayList<Double>(lengthSet); + Collections.sort(lengthSem); + List<String> speciesSem = new ArrayList<String>(speciesSet); + Collections.sort(speciesSem); + List<String> strataSem = new ArrayList<String>(strataSet); + Collections.sort(strataSem); + List<String> yearsSem = new ArrayList<String>(yearsSet); + Collections.sort(yearsSem); + + if (log.isDebugEnabled()) { + log.debug(_("Creating matrix : %d*%d*%d*%d", lengthSem.size(), speciesSem.size(), strataSem.size(), yearsSem.size())); + } + + MatrixND matrix = MatrixFactory.getInstance().createProxy(n_("coser.business.matrix.lengthstructure"), + new List<?>[] { lengthSem , speciesSem, strataSem, yearsSem}, + new String[] {n_("coser.business.common.length"), + n_("coser.business.common.species"), + n_("coser.business.common.strata"), + n_("coser.business.common.years")}, + new LengthStructureMatrixProvider(project, dataContainer)); + + return matrix; + } + /** + * Length structure matrix provider. + */ + class LengthStructureMatrixProvider implements MatrixProvider { + + protected Project project; + + protected AbstractDataContainer container; + + public LengthStructureMatrixProvider(Project project, AbstractDataContainer container) { + this.project = project; + this.container = container; + } + + /* + * @see org.nuiton.math.matrix.MatrixProvider#fillValues(org.nuiton.math.matrix.MatrixND) + */ + @Override + public void fillValues(MatrixND matrix) { + fillLengthStructureMatrix(project, container, matrix); + } + } + + /** + * Length structure matrix provider filler part. + * + * @param project project + * @param dataContainer data container + * @param matrix non proxy matrix to fill (inited with 0.0) + */ + public void fillLengthStructureMatrix(Project project, AbstractDataContainer dataContainer, MatrixND matrix) { + + // load map traitname > stratename + Map<String, String> haulAndStratas = new HashMap<String, String>(); + Iterator<String[]> itHaul = dataContainer.getHaul().iterator(); + itHaul.next(); // skip header + while (itHaul.hasNext()) { + String[] tuple = itHaul.next(); + String haul = tuple[Haul.INDEX_HAUL]; + String strataName = tuple[Haul.INDEX_STRATUM]; + haulAndStratas.put(haul, strataName); + } + DimensionHelper dimHelper = new DimensionHelper(); + + Iterator<String[]> itData = dataContainer.getLength().iterator(); + itData.next(); // skip header + while (itData.hasNext()) { + String[] tuple = itData.next(); + + String year = tuple[Length.INDEX_YEAR]; + String haul = tuple[Length.INDEX_HAUL]; + String species = tuple[Length.INDEX_SPECIES]; + String lengthAsString = tuple[Length.INDEX_LENGTH]; + String numberAsString = tuple[Length.INDEX_NUMBER]; + String strata = haulAndStratas.get(haul); + + if (strata == null) { + if (log.isWarnEnabled()) { + log.warn("No strata for haul " + haul); + } + continue; + } + + // quitte l'iteration courante si les dimensions demandée + // ne sont pas dans la matrice reduite + if (!matrix.getSemantic(1).contains(species)) { + continue; + } + if (!matrix.getSemantic(2).contains(strata)) { + continue; + } + if (!matrix.getSemantic(3).contains(year)) { + continue; + } + + // get correct length step + // plain or half centimeters + try { + double length = Double.parseDouble(lengthAsString); + + // get length step to use + double ceil = Math.ceil(length); + double floor = Math.floor(length); + // ne pas prendre 0.5 car 10.0 serait arrondit à 10.5 + double round = Math.floor(length + 0.499999); + + // on prend le pas ou demi pas le plus proche + if (ceil == round) { + length = floor + 0.5; + } + else { + length = floor; + } + + if (!matrix.getSemantic(0).contains(length)) { + continue; + } + + try { + double number = Double.parseDouble(numberAsString); + + // dimHelper is more performant + double currentNumber = matrix.getValue(dimHelper.get(length, species, strata, year)); + currentNumber += number; + matrix.setValue(dimHelper.get(length, species, strata, year), currentNumber); + } + catch (NumberFormatException ex) { + if (log.isWarnEnabled()) { + log.warn("Can't parse number as double : " + numberAsString); + } + } + } + catch (NumberFormatException ex) { + if (log.isWarnEnabled()) { + log.warn("Can't parse length as double : " + lengthAsString); + } + } + } + } + + /** * Extrait les données de la selection * * @param project project Modified: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/common/DataHandler.java =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/common/DataHandler.java 2010-12-15 17:59:14 UTC (rev 423) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/common/DataHandler.java 2010-12-16 17:22:30 UTC (rev 424) @@ -65,10 +65,10 @@ public void run() { try { setWaitCursor(parent); - + // get matrix MatrixND matrix = projectService.getLengthStructure(project, container); - + // display matrix viewer component JFrame matrixViewerFrame = new JFrame(_("coser.ui.graph.lengthStructure")); matrixViewerFrame.setName("lengthstructureframe");
participants (1)
-
chatellier@users.labs.libre-entreprise.org