<commit_before>package org.timepedia.chronoscope.client.data;

import org.timepedia.chronoscope.client.Dataset;
import org.timepedia.chronoscope.client.util.ArgChecker;
import org.timepedia.chronoscope.client.util.Array2D;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * An ordered set of {@link MipMap} objects, where each MipMap represents
 * a compressed version of the raw {@link Dataset}.
 *   
 * @author <NAME>
 */
public class MipMapChain {
  private Map<String,MipMap> name2mipmap;
  private List<MipMap> mipMaps;
  private int rangeTupleSize;
  
  private Array2D mipMappedDomain;
  private Array2D[] mipMappedRangeTuples;
  
  public String toString() {
    String ret = "{";
    ret += " rangeTupleSize: " + rangeTupleSize;
    ret += ", mipMaps: [";
    for (MipMap m : mipMaps) {
      ret += "\n"  + m.toString() + ",";
    }
    ret += "]";
    ret += ",\n miMappedDomain: " + mipMappedDomain.toString();
    ret += ",\n miMappedTuples: ";
    for (Array2D d: mipMappedRangeTuples) {
      ret += d.toString();
    }
    ret += "}\n";

    return ret;
  }

  public MipMapChain(Array2D mipMappedDomain, List<Array2D> mipMappedRangeTuples) {
    this(mipMappedDomain, mipMappedRangeTuples, null);
  }

  public MipMapChain(Array2D mipMappedDomain, List<Array2D> mipMappedRangeTuples,
        List<String> mipLevelNames) {
    
    validate(mipMappedDomain, mipMappedRangeTuples);
    this.mipMappedDomain = mipMappedDomain;
    this.mipMappedRangeTuples = mipMappedRangeTuples.toArray(new Array2D[0]);
    this.rangeTupleSize = mipMappedRangeTuples.size();
    
    final int numMipLevels = mipMappedDomain.numRows();
    
    this.mipMaps = new ArrayList<MipMap>();
    for (int i = 0; i < numMipLevels; i++) {
      addMipLevel();
    }
    
    if (mipLevelNames != null) {
      if (mipLevelNames.size() != numMipLevels) {
        throw new IllegalArgumentException("mipLevelNames.size() != numMipLevels");
      }
      this.name2mipmap = new HashMap<String,MipMap>();
      for (int i = 0; i < numMipLevels; i++) {
        String mipLevelName = mipLevelNames.get(i);
        if (mipLevelName != null) {
          this.name2mipmap.put(mipLevelName, this.mipMaps.get(i));
        }
      }
    }
  }

  public void clear() {
    this.mipMappedDomain = null;
    this.mipMappedRangeTuples = null;
    this.rangeTupleSize = 0;
    this.mipMaps.clear();
    this.name2mipmap.clear();
  }
  
  void addMipLevel() {
    final int currHighestMipLevel = mipMaps.size() - 1;
    MipMap nextMipMap = 
      new MipMap(mipMappedDomain, mipMappedRangeTuples, currHighestMipLevel + 1);
    if (!this.mipMaps.isEmpty()) {
      MipMap currMipMap = this.mipMaps.get(currHighestMipLevel);
      currMipMap.nextMipMap = nextMipMap;
    }
    this.mipMaps.add(nextMipMap);
  }
  
  /**
   * Returns the "densest" (having the most data points) MipMap in this chain whose
   * number of datapoints is not greater than <tt>maxDataPoints</tt>.
   */
  public MipMap findHighestResolution(int maxDataPoints) {
    MipMap mipMap = getMipMap(0);
    while (true) {
      int numPoints = mipMap.size();
      if (numPoints <= maxDataPoints) {
        return mipMap;
      }
      mipMap = mipMap.next();
    }<commit_msg>Fixing a NPE introduced in r1256 which makes fail mutations on non grouped datasets<commit_after>package org.timepedia.chronoscope.client.data;

import org.timepedia.chronoscope.client.Dataset;
import org.timepedia.chronoscope.client.util.ArgChecker;
import org.timepedia.chronoscope.client.util.Array2D;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * An ordered set of {@link MipMap} objects, where each MipMap represents
 * a compressed version of the raw {@link Dataset}.
 *   
 * @author <NAME>
 */
public class MipMapChain {
  private Map<String,MipMap> name2mipmap;
  private List<MipMap> mipMaps;
  private int rangeTupleSize;
  
  private Array2D mipMappedDomain;
  private Array2D[] mipMappedRangeTuples;
  
  public String toString() {
    String ret = "{";
    ret += " rangeTupleSize: " + rangeTupleSize;
    ret += ", mipMaps: [";
    for (MipMap m : mipMaps) {
      ret += "\n"  + m.toString() + ",";
    }
    ret += "]";
    ret += ",\n miMappedDomain: " + mipMappedDomain.toString();
    ret += ",\n miMappedTuples: ";
    for (Array2D d: mipMappedRangeTuples) {
      ret += d.toString();
    }
    ret += "}\n";

    return ret;
  }

  public MipMapChain(Array2D mipMappedDomain, List<Array2D> mipMappedRangeTuples) {
    this(mipMappedDomain, mipMappedRangeTuples, null);
  }

  public MipMapChain(Array2D mipMappedDomain, List<Array2D> mipMappedRangeTuples,
        List<String> mipLevelNames) {
    
    validate(mipMappedDomain, mipMappedRangeTuples);
    this.mipMappedDomain = mipMappedDomain;
    this.mipMappedRangeTuples = mipMappedRangeTuples.toArray(new Array2D[0]);
    this.rangeTupleSize = mipMappedRangeTuples.size();
    
    final int numMipLevels = mipMappedDomain.numRows();
    
    this.mipMaps = new ArrayList<MipMap>();
    for (int i = 0; i < numMipLevels; i++) {
      addMipLevel();
    }
    
    if (mipLevelNames != null) {
      if (mipLevelNames.size() != numMipLevels) {
        throw new IllegalArgumentException("mipLevelNames.size() != numMipLevels");
      }
      this.name2mipmap = new HashMap<String,MipMap>();
      for (int i = 0; i < numMipLevels; i++) {
        String mipLevelName = mipLevelNames.get(i);
        if (mipLevelName != null) {
          this.name2mipmap.put(mipLevelName, this.mipMaps.get(i));
        }
      }
    }
  }

  public void clear() {
    this.mipMappedDomain = null;
    this.mipMappedRangeTuples = null;
    this.rangeTupleSize = 0;
    this.mipMaps.clear();
    if (this.name2mipmap != null) {
      this.name2mipmap.clear();
    }
  }
  
  void addMipLevel() {
    final int currHighestMipLevel = mipMaps.size() - 1;
    MipMap nextMipMap = 
      new MipMap(mipMappedDomain, mipMappedRangeTuples, currHighestMipLevel + 1);
    if (!this.mipMaps.isEmpty()) {
      MipMap currMipMap = this.mipMaps.get(currHighestMipLevel);
      currMipMap.nextMipMap = nextMipMap;
    }
    this.mipMaps.add(nextMipMap);
  }
  
  /**
   * Returns the "densest" (having the most data points) MipMap in this chain whose
   * number of datapoints is not greater than <tt>maxDataPoints</tt>.
   */
  public MipMap findHighestResolution(int maxDataPoints) {
    MipMap mipMap = getMipMap(0);
    while (true) {
      int numPoints = mipMap.size();
      if (numPoints <= maxDataPoints) {
        return mipMap;
      }
      mipMap = mipMap.next();
    }
{'fraction_non_alphanumeric': 0.12049819927971188, 'fraction_numerical': 0.006752701080432173, 'mean_word_length': 3.194461925739459, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6651438', 'n_tokens_mistral': 2468, 'n_tokens_neox': 2400, 'n_words': 476}