Package ca.eandb.jmist.framework.job

Source Code of ca.eandb.jmist.framework.job.MaterialPhotometerJob$PhotometerTaskWorker

/**
* Java Modular Image Synthesis Toolkit (JMIST)
* Copyright (C) 2008-2013 Bradley W. Kimmel
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package ca.eandb.jmist.framework.job;

import java.io.IOException;
import java.io.PrintStream;
import java.io.Serializable;

import ca.eandb.jdcp.job.AbstractParallelizableJob;
import ca.eandb.jdcp.job.TaskWorker;
import ca.eandb.jmist.framework.Material;
import ca.eandb.jmist.framework.color.Color;
import ca.eandb.jmist.framework.color.ColorModel;
import ca.eandb.jmist.framework.color.WavelengthPacket;
import ca.eandb.jmist.framework.measurement.CollectorSphere;
import ca.eandb.jmist.framework.measurement.ColorSensorArray;
import ca.eandb.jmist.framework.measurement.MaterialPhotometer;
import ca.eandb.jmist.math.SphericalCoordinates;
import ca.eandb.util.io.Archive;
import ca.eandb.util.progress.ProgressMonitor;

/**
* @author Brad Kimmel
*
*/
public final class MaterialPhotometerJob extends AbstractParallelizableJob {

  /** Serialization version ID. */
  private static final long serialVersionUID = -1521758677633805555L;

  public MaterialPhotometerJob(Material[] specimens,
      SphericalCoordinates[] incidentAngles, WavelengthPacket[] wavelengths,
      long samplesPerMeasurement, long samplesPerTask, CollectorSphere collector) {

    this.worker            = new PhotometerTaskWorker(collector);
    this.specimens          = specimens.clone();
    this.incidentAngles        = incidentAngles.clone();
    this.wavelengths        = wavelengths.clone();
    this.samplesPerMeasurement    = samplesPerMeasurement;
    this.samplesPerTask        = samplesPerTask;
    this.totalTasks          = specimens.length
                        * wavelengths.length
                        * incidentAngles.length
                        * ((int) (samplesPerMeasurement / samplesPerTask) + ((samplesPerMeasurement % samplesPerTask) > 0 ? 1
                            : 0));


  }

  public MaterialPhotometerJob(Material specimen,
      SphericalCoordinates[] incidentAngles, WavelengthPacket[] wavelengths,
      long samplesPerMeasurement, long samplesPerTask, CollectorSphere collector) {
    this(new Material[]{ specimen }, incidentAngles, wavelengths, samplesPerMeasurement, samplesPerTask, collector);
  }

  /* (non-Javadoc)
   * @see ca.eandb.jdcp.job.AbstractParallelizableJob#initialize()
   */
  @Override
  public void initialize() {
    this.results = new ColorSensorArray[wavelengths.length * incidentAngles.length * specimens.length];
    for (int i = 0; i < this.results.length; i++) {
      ColorModel colorModel = this.getWavelength(i).getColorModel();
      this.results[i] = new ColorSensorArray(worker.collector.sensors(), colorModel);
      maxChannels = Math.max(maxChannels, colorModel.getNumChannels());
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see ca.eandb.jmist.framework.ParallelizableJob#getNextTask()
   */
  public Object getNextTask() {

    if (!this.isComplete()) {

      PhotometerTask task = this.getPhotometerTask(this.nextMeasurementIndex);

      if (++this.nextMeasurementIndex >= this.results.length) {
        this.outstandingSamplesPerMeasurement += this.samplesPerTask;
        this.nextMeasurementIndex = 0;
      }

      return task;

    } else {

      return null;

    }

  }

  private PhotometerTask getPhotometerTask(int measurementIndex) {
    return new PhotometerTask(
        this.getSpecimen(measurementIndex),
        this.getIncidentAngle(measurementIndex),
        this.getWavelength(measurementIndex),
        this.samplesPerTask,
        measurementIndex
    );
  }

  private Material getSpecimen(int measurementIndex) {
    return this.specimens[measurementIndex / (wavelengths.length * incidentAngles.length)];
  }

  private SphericalCoordinates getIncidentAngle(int measurementIndex) {
    int specimenMeasurementIndex = measurementIndex % (wavelengths.length * incidentAngles.length);
    return this.incidentAngles[specimenMeasurementIndex / this.wavelengths.length];
  }

  private WavelengthPacket getWavelength(int measurementIndex) {
    int specimenMeasurementIndex = measurementIndex % (wavelengths.length * incidentAngles.length);
    return this.wavelengths[specimenMeasurementIndex % this.wavelengths.length];
  }

  /* (non-Javadoc)
   * @see ca.eandb.jmist.framework.ParallelizableJob#submitTaskResults(java.lang.Object, java.lang.Object, ca.eandb.util.progress.ProgressMonitor)
   */
  public void submitTaskResults(Object task, Object results,
      ProgressMonitor monitor) {

    PhotometerTask    info    = (PhotometerTask) task;
    ColorSensorArray  sensorArray  = (ColorSensorArray) results;

    this.results[info.measurementIndex].merge(sensorArray);

    monitor.notifyProgress(++this.tasksReturned, this.totalTasks);

  }

  /* (non-Javadoc)
   * @see ca.eandb.jmist.framework.ParallelizableJob#isComplete()
   */
  public boolean isComplete() {
    return this.outstandingSamplesPerMeasurement >= this.samplesPerMeasurement;
  }

  private final String colorToCSV(Color color) {
    double[] values = color.toArray();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < maxChannels; i++) {
      if (i > 0) {
        sb.append(",");
      }
      if (i < values.length) {
        sb.append(values[i]);
      }
    }
    return sb.toString();
  }

  /* (non-Javadoc)
   * @see ca.eandb.jmist.framework.ParallelizableJob#finish()
   */
  public void finish() {

    PrintStream out = new PrintStream(createFileOutputStream("photometer.csv"));

    this.writeColumnHeadings(out);

    for (int specimenIndex = 0, n = 0; specimenIndex < this.specimens.length; specimenIndex++) {

      for (int incidentAngleIndex = 0; incidentAngleIndex < this.incidentAngles.length; incidentAngleIndex++) {

        SphericalCoordinates      incidentAngle      = this.incidentAngles[incidentAngleIndex];

        for (int wavelengthIndex = 0; wavelengthIndex < this.wavelengths.length; wavelengthIndex++, n++) {

          WavelengthPacket      wavelength        = this.wavelengths[wavelengthIndex];
          ColorSensorArray      sensorArray        = this.results[n];

          for (int sensor = 0; sensor < worker.collector.sensors(); sensor++) {

            SphericalCoordinates  exitantAngle      = worker.collector.getSensorCenter(sensor);
            double          solidAngle        = worker.collector.getSensorSolidAngle(sensor);
            double          projectedSolidAngle    = worker.collector.getSensorProjectedSolidAngle(sensor);
            Color          raw            = sensorArray.getTotalWeight(sensor);
            Color          reflectance        = raw.divide(this.outstandingSamplesPerMeasurement);

            out.printf(
                "%d,%f,%f,%d,%d,%f,%f,%f,%f,%d,%s,%s,%s,%s",
                specimenIndex,
                incidentAngle.polar(),
                incidentAngle.azimuthal(),
                wavelengthIndex,
                sensor,
                exitantAngle.polar(),
                exitantAngle.azimuthal(),
                solidAngle,
                projectedSolidAngle,
                this.outstandingSamplesPerMeasurement,
                colorToCSV(raw),
                colorToCSV(reflectance),
                colorToCSV(reflectance.divide(projectedSolidAngle)),
                colorToCSV(reflectance.divide(solidAngle))
            );
            out.println();

          }

        }

      }

    }

    out.close();

  }

  /**
   * Writes the CSV column headings to the result stream.
   * @param out The <code>PrintStream</code> to write the column headings to.
   */
  private void writeColumnHeadings(PrintStream out) {

    out.print("\"Specimen\",");
    out.print("\"Incident Polar (radians)\",");
    out.print("\"Incident Azimuthal (radians)\",");
    out.print("\"Wavelength Packet\",");
    out.print("\"Sensor\",");
    out.print("\"Exitant Polar (radians)\",");
    out.print("\"Exitant Azimuthal (radians)\",");
    out.print("\"Solid Angle (sr)\",");
    out.print("\"Projected Solid Angle (sr)\",");
    out.print("\"Samples\",");

    if (wavelengths.length == 1) {

    }

    for (int i = 0; i < maxChannels; i++) {
      out.printf("\"Raw (%s)\",", wavelengths.length > 1 ? Integer.toString(i) : wavelengths[0].getColorModel().getChannelName(i));
    }
    for (int i = 0; i < maxChannels; i++) {
      out.printf("\"Reflectance (%s)\",", wavelengths.length > 1 ? Integer.toString(i) : wavelengths[0].getColorModel().getChannelName(i));
    }
    for (int i = 0; i < maxChannels; i++) {
      out.printf("\"BSDF (%s)\",", wavelengths.length > 1 ? Integer.toString(i) : wavelengths[0].getColorModel().getChannelName(i));
    }
    for (int i = 0; i < maxChannels - 1; i++) {
      out.printf("\"SPF (%s)\",", wavelengths.length > 1 ? Integer.toString(i) : wavelengths[0].getColorModel().getChannelName(i));
    }
    out.printf("\"SPF (%s)\"", wavelengths.length > 1 ? Integer.toString(maxChannels - 1) : wavelengths[0].getColorModel().getChannelName(maxChannels - 1));
    out.println();

  }

  /* (non-Javadoc)
   * @see ca.eandb.jdcp.job.AbstractParallelizableJob#archiveState(ca.eandb.util.io.Archive)
   */
  @Override
  protected void archiveState(Archive ar) throws IOException, ClassNotFoundException {
    results = (ColorSensorArray[]) ar.archiveObject(results);
    nextMeasurementIndex = ar.archiveInt(nextMeasurementIndex);
    outstandingSamplesPerMeasurement = ar.archiveLong(outstandingSamplesPerMeasurement);
    tasksReturned = ar.archiveInt(tasksReturned);
    maxChannels = ar.archiveInt(maxChannels);
  }

  /* (non-Javadoc)
   * @see ca.eandb.jmist.framework.ParallelizableJob#worker()
   */
  public TaskWorker worker() {
    return this.worker;
  }

  private static class PhotometerTask implements Serializable {

    /** Serialization version ID. */
    private static final long serialVersionUID = 4238727637644746732L;

    public final Material        specimen;
    public final SphericalCoordinates  incident;
    public final WavelengthPacket    wavelength;
    public final long          samples;
    public final int          measurementIndex;

    public PhotometerTask(Material specimen,
        SphericalCoordinates incident, WavelengthPacket wavelength, long samples,
        int measurementIndex) {
      this.specimen      = specimen;
      this.incident      = incident;
      this.wavelength      = wavelength;
      this.samples      = samples;
      this.measurementIndex  = measurementIndex;
    }

  }

  private static class PhotometerTaskWorker implements TaskWorker, Serializable {

    /** Serialization version ID. */
    private static final long serialVersionUID = -6729377656284858068L;

    /**
     * Creates a new <code>PhotometerTaskWorker</code>.
     * @param specimen The <code>SurfaceScatterer</code> to be measured.
     * @param collector The prototype <code>CollectorSphere</code> from
     *     which clones are constructed to record hits to.
     */
    public PhotometerTaskWorker(CollectorSphere collector) {
      this.collector = collector;
    }

    /* (non-Javadoc)
     * @see ca.eandb.jmist.framework.TaskWorker#performTask(java.lang.Object, ca.eandb.util.progress.ProgressMonitor)
     */
    public Object performTask(Object task, ProgressMonitor monitor) {

      PhotometerTask    info      = (PhotometerTask) task;
      MaterialPhotometer  photometer    = new MaterialPhotometer(collector, info.wavelength.getColorModel());

      photometer.setSpecimen(info.specimen);
      photometer.setIncidentAngle(info.incident);
      photometer.setWavelengthPacket(info.wavelength);
      photometer.castPhotons(info.samples, monitor);

      return photometer.getSensorArray();

    }

    /**
     * The prototype <code>CollectorSphere</code> from which clones are
     * constructed to record hits to.
     */
    private final CollectorSphere collector;

  }

  /** The <code>TaskWorker</code> that performs the work for this job. */
  private final PhotometerTaskWorker worker;

  private final Material[] specimens;
  private final WavelengthPacket[] wavelengths;
  private final SphericalCoordinates[] incidentAngles;
  private final long samplesPerMeasurement;
  private final long samplesPerTask;
  private final int totalTasks;
  private transient int maxChannels;
  private transient ColorSensorArray[] results;
  private transient int nextMeasurementIndex = 0;
  private transient long outstandingSamplesPerMeasurement = 0;
  private transient int tasksReturned = 0;

}
TOP

Related Classes of ca.eandb.jmist.framework.job.MaterialPhotometerJob$PhotometerTaskWorker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.