def __init__(self, parent=None):
        BaseFrame.__init__(self, parent, -1, lang.getstr("measurement_report"))
        self.Bind(wx.EVT_CLOSE, self.OnClose)

        self.SetIcons(config.get_icon_bundle([256, 48, 32, 16], appname))

        res = TempXmlResource(get_data_path(os.path.join("xrc", "report.xrc")))
        res.InsertHandler(xh_fancytext.StaticFancyTextCtrlXmlHandler())
        res.InsertHandler(
            xh_filebrowsebutton.FileBrowseButtonWithHistoryXmlHandler())
        res.InsertHandler(xh_hstretchstatbmp.HStretchStaticBitmapXmlHandler())
        res.InsertHandler(xh_bitmapctrls.BitmapButton())
        res.InsertHandler(xh_bitmapctrls.StaticBitmap())
        self.panel = res.LoadPanel(self, "panel")

        self.Sizer = wx.BoxSizer(wx.VERTICAL)
        self.Sizer.Add(self.panel, 1, flag=wx.EXPAND)

        self.set_child_ctrls_as_attrs(self)

        self.measurement_report_btn = wx.Button(self.panel, -1,
                                                lang.getstr("measure"))
        self.panel.Sizer.Insert(2,
                                self.measurement_report_btn,
                                flag=wx.RIGHT | wx.BOTTOM | wx.ALIGN_RIGHT,
                                border=16)

        self.worker = worker.Worker(self)
        self.worker.set_argyll_version("xicclu")

        BaseFrame.setup_language(self)
        self.mr_setup_language()
        self.mr_init_controls()
        self.mr_update_controls()
        self.mr_init_frame()
 def _validate(self, resp, url, validate):
     raw = resp.read()
     if isinstance(validate, dict):
         data = json.loads(raw)
         components = urllib.parse.urlparse(url)
         api = components.path[1:]
         query = urllib.parse.parse_qs(components.query)
         if "m" in query:
             method = query["m"][0]
             if data.get(method) == "Error" and "msg" in data:
                 raise http.client.HTTPException("%s: %s" %
                                                 (self.host, data["msg"]))
         for key, value in validate.items():
             if key not in data:
                 raise http.client.HTTPException(
                     lang.getstr("response.invalid.missing_key",
                                 (self.host, key, raw)))
             elif value is not None and data[key] != value:
                 raise http.client.HTTPException(
                     lang.getstr("response.invalid.value",
                                 (self.host, key, value, raw)))
         data["raw"] = raw
         return data
     elif validate:
         if raw != validate:
             raise http.client.HTTPException(
                 lang.getstr("response.invalid", (self.host, raw)))
     return raw
 def wait(self):
     self.listening = True
     if self.logfile:
         try:
             host = get_network_addr()
         except error:
             host = gethostname()
         self.logfile.write(
             lang.getstr("webserver.waiting") + (" %s:%s\n" %
                                                 (host, self.port)))
     self.socket.settimeout(1)
     while self.listening:
         try:
             self.conn, addr = self.get_request()
         except timeout:
             continue
         self.conn.settimeout(1)
         break
     self.socket.settimeout(None)
     if self.listening:
         try:
             self.process_request(self.conn, addr)
         except:
             self.handle_error(self.conn, addr)
             self.disconnect_client()
         else:
             self._thread = threading.Thread(
                 target=self.serve_forever,
                 name="WebWinHTTPPatternGeneratorServerThread")
             self._thread.start()
             safe_print(lang.getstr("connection.established"))
Beispiel #4
0
 def wait(self):
     self.listening = True
     if self.logfile:
         self.logfile.write(
             lang.getstr("connecting.to", ("Chromecast", " " + self.name)) +
             "\n")
     if not hasattr(self, "_cc"):
         # Find our ChromeCast
         try:
             self._cc = next(cc for cc in get_chromecasts() if safe_unicode(
                 cc.device.friendly_name, "UTF-8") == self.name)
         except StopIteration:
             self.listening = False
             raise
         self._cc.register_handler(self._controller)
     # Wait for ChromeCast device to be ready
     while self.listening:
         self._cc.wait(0.05)
         if self._cc.status:
             break
     if self.listening:
         # Launch pattern generator app
         self._controller.launch()
         # Wait for it
         while (self.listening
                and self._cc.app_id != self._controller.supporting_app_id):
             sleep(0.05)
         self.conn = True
         safe_print(lang.getstr("connection.established"))
Beispiel #5
0
 def toggle_draw(self, event):
     """ Toggle between spectral and CIE plot """
     if self.canvas.GetEnableLegend():
         self.draw_ccxx()
         self.toggle_btn.SetLabel(lang.getstr("spectral"))
     else:
         self.draw_cie()
         self.toggle_btn.SetLabel(lang.getstr("whitepoint.xy"))
Beispiel #6
0
 def __init__(self, html, embed, view, force, cache):
     BaseFrame.__init__(self,
                        None,
                        wx.ID_ANY,
                        lang.getstr("vrml_to_x3d_converter"),
                        style=wx.DEFAULT_FRAME_STYLE
                        & ~(wx.MAXIMIZE_BOX | wx.RESIZE_BORDER),
                        name="vrml2x3dframe")
     self.SetIcons(
         config.get_icon_bundle([256, 48, 32, 16],
                                appname + "-VRML-to-X3D-converter"))
     self.Bind(wx.EVT_CLOSE, self.OnClose)
     self.cache = cache
     self.embed = embed
     self.force = force
     self.html = html
     self.worker = Worker(self)
     sizer = wx.BoxSizer(wx.HORIZONTAL)
     self.SetSizer(sizer)
     panel = wx.Panel(self)
     sizer.Add(panel)
     panelsizer = wx.BoxSizer(wx.HORIZONTAL)
     panel.SetSizer(panelsizer)
     self.btn = BitmapButton(panel,
                             wx.ID_ANY,
                             config.geticon(256, "3d-primitives"),
                             style=wx.NO_BORDER)
     self.btn.SetToolTipString(lang.getstr("file.select"))
     self.btn.Bind(
         wx.EVT_BUTTON,
         lambda event: vrmlfile2x3dfile(None,
                                        html=html,
                                        embed=embed,
                                        view=view,
                                        force=force,
                                        cache=cache,
                                        worker=self.worker))
     self.droptarget = FileDrop(self)
     vrml_drop_handler = lambda vrmlpath: vrmlfile2x3dfile(vrmlpath,
                                                           html=html,
                                                           embed=embed,
                                                           view=view,
                                                           force=force,
                                                           cache=cache,
                                                           worker=self.
                                                           worker)
     self.droptarget.drophandlers = {
         ".vrml": vrml_drop_handler,
         ".vrml.gz": vrml_drop_handler,
         ".wrl": vrml_drop_handler,
         ".wrl.gz": vrml_drop_handler,
         ".wrz": vrml_drop_handler
     }
     self.btn.SetDropTarget(self.droptarget)
     panelsizer.Add(self.btn, flag=wx.ALL, border=12)
     self.Fit()
     self.SetMinSize(self.GetSize())
     self.SetMaxSize(self.GetSize())
Beispiel #7
0
def create(report_path, placeholders2data, pack=True, templatename="report"):
    """ Create a report with all placeholders substituted by data. """
    # read report template
    templatefilename = "%s.html" % templatename
    report_html_template_path = get_data_path(
        os.path.join("report", templatefilename))
    if not report_html_template_path:
        raise IOError(lang.getstr("file.missing", templatefilename))
    try:
        report_html_template = codecs.open(report_html_template_path, "r",
                                           "UTF-8")
    except (IOError, OSError) as exception:
        raise exception.__class__(
            lang.getstr("error.file.open", report_html_template_path))
    report_html = report_html_template.read()
    report_html_template.close()

    # create report
    for placeholder, data in placeholders2data.items():
        report_html = report_html.replace(placeholder, data)

    for include in ("base.css", "compare.css", "print.css",
                    "jsapi-packages.js", "jsapi-patches.js",
                    "compare.constants.js", "compare.variables.js",
                    "compare.functions.js", "compare.init.js",
                    "uniformity.functions.js"):
        path = get_data_path(os.path.join("report", include))
        if not path:
            raise IOError(lang.getstr("file.missing", include))
        try:
            f = codecs.open(path, "r", "UTF-8")
        except (IOError, OSError) as exception:
            raise exception.__class__(lang.getstr("error.file.open", path))
        if include.endswith(".js"):
            js = f.read()
            if pack:
                packer = jspacker.JavaScriptPacker()
                js = packer.pack(js, 62, True).strip()
            report_html = report_html.replace(
                'src="%s">' % include, ">/*<![CDATA[*/\n" + js + "\n/*]]>*/")
        else:
            report_html = report_html.replace('@import "%s";' % include,
                                              f.read().strip())
        f.close()

    # write report
    try:
        report_html_file = codecs.open(report_path, "w", "UTF-8")
    except (IOError, OSError) as exception:
        raise exception.__class__(
            lang.getstr("error.file.create", report_path) + "\n\n" +
            safe_unicode(exception))
    report_html_file.write(report_html)
    report_html_file.close()
Beispiel #8
0
def vrmlfile2x3dfile(vrmlpath,
                     x3dpath,
                     html=True,
                     embed=False,
                     force=False,
                     cache=True,
                     worker=None):
    """
	Convert VRML file located at vrmlpath to HTML and write to x3dpath
	
	"""
    filename, ext = os.path.splitext(vrmlpath)
    if ext.lower() in (".gz", ".wrz"):
        cls = GzipFileProper
    else:
        cls = open
    with cls(vrmlpath, "rb") as vrmlfile:
        vrml = vrmlfile.read()
    if worker:
        worker.recent.write(
            "%s %s\n" %
            (lang.getstr("converting"), os.path.basename(vrmlpath)))
    _safe_print(lang.getstr("converting"), vrmlpath)
    filename, ext = os.path.splitext(x3dpath)
    try:
        x3d = vrml2x3dom(vrml, worker)
        if not x3d:
            _safe_print(lang.getstr("aborted"))
            return False
        if not html:
            _safe_print("Writing", x3dpath)
            with open(x3dpath, "wb") as x3dfile:
                x3dfile.write(x3d.x3d())
        else:
            html = x3d.html(title=os.path.basename(filename),
                            embed=embed,
                            force=force,
                            cache=cache)
            _safe_print("Writing", x3dpath + ".html")
            with open(x3dpath + ".html", "wb") as htmlfile:
                htmlfile.write(html)
    except KeyboardInterrupt:
        x3d = False
    except VRMLParseError as exception:
        return exception
    except EnvironmentError as exception:
        return exception
    except Exception as exception:
        import traceback
        _safe_print(traceback.format_exc())
        return exception
    return True
Beispiel #9
0
 def send_command_handler(self, command, additional_commands=None):
     self.add_text("\n")
     command = command.strip()
     if not command:
         self.add_text("> ")
         return
     data = split_command_line(command)
     response = self.process_data_local(data)
     if response == "ok":
         pass
     elif isinstance(response, list):
         self.add_text("\n".join(response))
         self.add_text("\n> ")
     elif not self or not self.conn:
         self.add_error_text(lang.getstr("not_connected") + "\n")
         self.add_text("> ")
     else:
         self.busy = True
         delayedresult.startWorker(self.check_result,
                                   self.send_command,
                                   cargs=(self.get_response,
                                          additional_commands),
                                   wargs=(command, ))
     self.history.insert(len(self.history) - 1, command)
     if len(self.history) > 1000:
         del self.history[0]
     self.historypos = len(self.history) - 1
Beispiel #10
0
 def get_app_info(self):
     commands = ["setresponseformat plain", "getcommands", "getappname"]
     try:
         for command in commands:
             self.conn.send_command(command)
             response = self.conn.get_single_response()
             if command == "getcommands":
                 self.commands = response.splitlines()
             elif command == "getappname":
                 wx.CallAfter(
                     self.add_text,
                     lang.getstr("connected.to.at",
                                 ((response, ) + self.conn.getpeername())) +
                     "\n%s\n" % lang.getstr("scripting-client.cmdhelptext"))
     except socket.error as exception:
         return exception
Beispiel #11
0
 def disconnect(self):
     if self.conn:
         try:
             peer = self.conn.getpeername()
             self.conn.shutdown(socket.SHUT_RDWR)
         except socket.error as exception:
             if exception.errno != errno.ENOTCONN:
                 self.add_text(safe_unicode(exception) + "\n")
         else:
             self.add_text(lang.getstr("disconnected.from", peer) + "\n")
         self.conn.close()
         del self.conn
         self.conn = None
         self.commands = []
     else:
         self.add_error_text(lang.getstr("not_connected") + "\n")
Beispiel #12
0
 def connect_handler(self, ip_port):
     ip, port = ip_port.split(":", 1)
     try:
         port = int(port)
     except ValueError:
         self.add_error_text(lang.getstr("port.invalid", port) + "\n")
         self.add_text("> ")
         return
     if self.conn:
         self.disconnect()
     self.add_text(lang.getstr("connecting.to", (ip, port)) + "\n")
     self.busy = True
     delayedresult.startWorker(self.check_result,
                               self.connect,
                               cargs=(self.get_app_info, None, False),
                               wargs=(ip, port))
    def mr_setup_language(self):
        # Shared with main window

        for which in ("chart", "simulation_profile", "devlink_profile",
                      "output_profile"):
            if which.endswith("_profile"):
                wildcard = lang.getstr("filetype.icc") + "|*.icc;*.icm"
            else:
                wildcard = (lang.getstr("filetype.ti1_ti3_txt") +
                            "|*.cgats;*.cie;*.ti1;*.ti2;*.ti3;*.txt")
            msg = {
                "chart": "measurement_report_choose_chart_or_reference",
                "devlink_profile": "devicelink_profile",
                "output_profile": "measurement_report_choose_profile"
            }.get(which, which)
            kwargs = dict(toolTip=lang.getstr(msg).rstrip(":"),
                          dialogTitle=lang.getstr(msg),
                          fileMask=wildcard)
            ctrl = getattr(self, "%s_ctrl" % which)
            for name, value in kwargs.items():
                setattr(ctrl, name, value)

        items = []
        for item in ("Gamma 2.2", "trc.rec1886", "custom"):
            items.append(lang.getstr(item))
        self.mr_trc_ctrl.SetItems(items)

        self.trc_gamma_types_ab = {0: "b", 1: "B"}
        self.trc_gamma_types_ba = {"b": 0, "B": 1}
        self.mr_trc_gamma_type_ctrl.SetItems([
            lang.getstr("trc.type.relative"),
            lang.getstr("trc.type.absolute")
        ])
Beispiel #14
0
 def __call__(self, idata):
     if not isinstance(idata, str):
         verbose = self.verbose
         if self.convert_video_rgb_to_clut65:
             devi_devip = self.devi_devip
         else:
             devi_devip = lambda v: v
         scale = float(self.scale)
         idata = list(idata)  # Make a copy
         for i, v in enumerate(idata):
             if isinstance(v, (float, int)):
                 self([idata])
                 return
             if not isinstance(v, str):
                 if verbose:
                     for n in v:
                         if not isinstance(n, (float, int)):
                             raise TypeError("xicclu: Expecting list of "
                                             "strings or n-tuples with "
                                             "floats")
                 idata[i] = " ".join(
                     str(devi_devip(n / scale) * scale) for n in v)
     else:
         idata = idata.splitlines()
     numrows = len(idata)
     chunklen = 1000
     i = 0
     p = self.subprocess
     prevperc = -1
     while True:
         # Process in chunks to prevent broken pipe if input data is too
         # large
         if getattr(sys, "_sigbreak", False) and not self.subprocess_abort:
             self.subprocess_abort = True
             safe_print("Got SIGBREAK, aborting subprocess...")
         if self.subprocess_abort or self.thread_abort:
             if p.poll() is None:
                 p.stdin.write("\n")
                 p.stdin.close()
                 p.wait()
             raise Info(lang.getstr("aborted"))
         if p.poll() is None:
             # We don't use communicate() because it will end the
             # process
             p.stdin.write("\n".join(idata[chunklen * i:chunklen *
                                           (i + 1)]) + "\n")
             p.stdin.flush()
         else:
             # Error
             break
         perc = round(chunklen * (i + 1) / float(numrows) * 100)
         if perc > prevperc and self.logfile:
             self.logfile.write("\r%i%%" % min(perc, 100))
             prevperc = perc
         if chunklen * (i + 1) > numrows - 1:
             break
         i += 1
 def wait(self):
     self.listening = True
     if self.logfile:
         try:
             host = get_network_addr()
         except error:
             host = gethostname()
         self.logfile.write(
             lang.getstr("connection.waiting") + (" %s:%s\n" %
                                                  (host, self.port)))
     while self.listening:
         try:
             self.conn, addr = self.socket.accept()
         except timeout:
             continue
         self.conn.settimeout(1)
         break
     if self.listening:
         safe_print(lang.getstr("connection.established"))
 def measure_darken_background_ctrl_handler(self, event):
     if self.measure_darken_background_cb.GetValue() and \
        getcfg("measure.darken_background.show_warning"):
         dlg = ConfirmDialog(self,
                             msg=lang.getstr("measure.darken_background."
                                             "warning"),
                             ok=lang.getstr("ok"),
                             cancel=lang.getstr("cancel"),
                             bitmap=geticon(32, "dialog-warning"))
         chk = wx.CheckBox(dlg, -1, lang.getstr("dialog.do_not_show_again"))
         dlg.Bind(wx.EVT_CHECKBOX,
                  self.measure_darken_background_warning_handler,
                  id=chk.GetId())
         dlg.sizer3.Add(chk, flag=wx.TOP | wx.ALIGN_LEFT, border=12)
         dlg.sizer0.SetSizeHints(dlg)
         dlg.sizer0.Layout()
         rslt = dlg.ShowModal()
         if rslt == wx.ID_CANCEL:
             self.measure_darken_background_cb.SetValue(False)
     setcfg("measure.darken_background",
            int(self.measure_darken_background_cb.GetValue()))
Beispiel #17
0
	def get_single_response(self):
		# Buffer received data until EOT (response end marker) and return
		# single response (additional data will still be in the buffer)
		while not "\4" in self.recv_buffer:
			incoming = self.recv(4096)
			if incoming == "":
				raise socket.error(lang.getstr("connection.broken"))
			self.recv_buffer += incoming
		end = self.recv_buffer.find("\4")
		single_response = self.recv_buffer[:end]
		self.recv_buffer = self.recv_buffer[end + 1:]
		return safe_unicode(single_response, "UTF-8")
Beispiel #18
0
 def __init__(self,
              profile,
              intent="r",
              direction="f",
              order="n",
              pcs=None,
              scale=1,
              cwd=None,
              startupinfo=None,
              use_icclu=False,
              use_cam_clipping=False,
              logfile=None,
              worker=None,
              show_actual_if_clipped=False,
              input_encoding=None,
              output_encoding=None,
              output_format=None,
              reverse=False,
              output_stream=None,
              convert_video_rgb_to_clut65=False,
              verbose=1):
     WorkerBase.__init__(self)
     self.logfile = logfile
     self.worker = worker
     self.output_stream = output_stream
     self._in = []
     self._args = (profile.fileName, intent, direction, order, pcs, scale,
                   cwd, startupinfo, use_icclu, use_cam_clipping, None,
                   show_actual_if_clipped, input_encoding, output_encoding,
                   lang.getstr("aborted"), output_format, reverse,
                   convert_video_rgb_to_clut65, verbose)
     self._out = []
     num_cpus = mp.cpu_count()
     if isinstance(profile.tags.get("A2B0"), ICCP.LUT16Type):
         size = profile.tags.A2B0.clut_grid_steps
         self.num_workers = min(max(num_cpus, 1), size)
         if num_cpus > 2:
             self.num_workers = int(self.num_workers * 0.75)
         self.num_batches = size // 9
     else:
         if num_cpus > 2:
             self.num_workers = 2
         else:
             self.num_workers = num_cpus
         self.num_batches = 1
Beispiel #19
0
 def check_result(self,
                  delayedResult,
                  get_response=False,
                  additional_commands=None,
                  colorize=True):
     try:
         result = delayedResult.get()
     except Exception as exception:
         if hasattr(exception, "originalTraceback"):
             self.add_text(exception.originalTraceback)
         result = exception
     if result:
         if isinstance(result, socket.socket):
             self.conn = result
             result = lang.getstr("connection.established")
         text = "%s\n" % safe_unicode(result)
         self.add_text(text)
         if colorize or isinstance(result, Exception):
             end = self.console.GetLastPosition()
             start = end - len(text)
             if isinstance(result, Exception):
                 color = ERRORCOLOR
             else:
                 color = RESPONSECOLOR
             self.mark_text(start, end, color)
     if get_response and not isinstance(result, Exception):
         delayedresult.startWorker(self.check_result,
                                   get_response,
                                   cargs=(False, additional_commands))
     else:
         self.add_text("> ")
         if additional_commands:
             self.add_text(additional_commands[0].rstrip("\n"))
             if additional_commands[0].endswith("\n"):
                 self.send_command_handler(additional_commands[0],
                                           additional_commands[1:])
                 return
         self.console.SetFocus()
         self.busy = False
Beispiel #20
0
 def parse_txt(self, txt):
     if not txt:
         return
     self.logger.info("%r" % txt)
     if "Setting up the instrument" in txt:
         self.Pulse(lang.getstr("instrument.initializing"))
     if "Spot read failed" in txt:
         self.last_error = txt
     if "Result is XYZ:" in txt:
         # Result is XYZ: d.dddddd d.dddddd d.dddddd, D50 Lab: d.dddddd d.dddddd d.dddddd
         #							CCT = ddddK (Delta E d.dddddd)
         # Closest Planckian temperature = ddddK (Delta E d.dddddd)
         # Closest Daylight temperature  = ddddK (Delta E d.dddddd)
         XYZ = re.search("XYZ:\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)", txt)
         self.results[self.index].append(
             {"XYZ": [float(value) for value in XYZ.groups()]})
         self.last_error = None
     loci = {"t": "Daylight", "T": "Planckian"}
     for locus in list(loci.values()):
         if locus in txt:
             CT = re.search(
                 "Closest\s+%s\s+temperature\s+=\s+(\d+)K" % locus, txt,
                 re.I)
             self.results[self.index][-1]["C%sT" % locus[0]] = int(
                 CT.groups()[0])
     if "key to take a reading" in txt and not self.last_error:
         safe_print("%s: Got 'key to take a reading'" % appname)
         if not self.is_measuring:
             self.enable_buttons()
             return
         if len(self.results[self.index]) < len(self.colors):
             # Take readings at 5 different brightness levels per swatch
             safe_print("%s: About to take next reading" % appname)
             self.measure()
         else:
             self.is_measuring = False
             self.show_cursor()
             self.enable_buttons()
             self.buttons[self.index].Show()
             self.buttons[self.index].SetFocus()
             self.buttons[self.index].SetBitmap(
                 getbitmap("theme/icons/16x16/checkmark"))
             self.panels[self.index].SetBackgroundColour(BGCOLOUR)
             self.panels[self.index].Refresh()
             self.panels[self.index].Update()
             if len(self.results) == self.rows * self.cols:
                 # All swatches have been measured, show results
                 # Let the user choose a location for the results html
                 display_no, geometry, client_area = self.get_display()
                 # Translate from wx display index to Argyll display index
                 geometry = "%i, %i, %ix%i" % tuple(geometry)
                 for i, display in enumerate(getcfg("displays")):
                     if display.find("@ " + geometry) > -1:
                         safe_print("Found display %s at index %i" %
                                    (display, i))
                         break
                 display = display.replace(" [PRIMARY]", "")
                 defaultFile = "Uniformity Check %s — %s — %s" % (
                     appversion, re.sub(r"[\\/:*?\"<>|]+", "_", display),
                     strftime("%Y-%m-%d %H-%M.html"))
                 defaultDir = get_verified_path(
                     None,
                     os.path.join(getcfg("profile.save_path"),
                                  defaultFile))[0]
                 dlg = wx.FileDialog(self,
                                     lang.getstr("save_as"),
                                     defaultDir,
                                     defaultFile,
                                     wildcard=lang.getstr("filetype.html") +
                                     "|*.html;*.htm",
                                     style=wx.SAVE | wx.FD_OVERWRITE_PROMPT)
                 dlg.Center(wx.BOTH)
                 result = dlg.ShowModal()
                 if result == wx.ID_OK:
                     path = dlg.GetPath()
                     if not waccess(path, os.W_OK):
                         from worker import show_result_dialog
                         show_result_dialog(
                             Error(
                                 lang.getstr("error.access_denied.write",
                                             path)), self)
                         return
                     save_path = os.path.splitext(path)[0] + ".html"
                     setcfg("last_filedialog_path", save_path)
                 dlg.Destroy()
                 if result != wx.ID_OK:
                     return
                 locus = loci.get(getcfg("whitepoint.colortemp.locus"))
                 try:
                     report.create(
                         save_path, {
                             "${REPORT_VERSION}": appversion,
                             "${DISPLAY}": display,
                             "${DATETIME}": strftime("%Y-%m-%d %H:%M:%S"),
                             "${ROWS}": str(self.rows),
                             "${COLS}": str(self.cols),
                             "${RESULTS}": str(self.results),
                             "${LOCUS}": locus
                         }, getcfg("report.pack_js"), "uniformity")
                 except (IOError, OSError) as exception:
                     from worker import show_result_dialog
                     show_result_dialog(exception, self)
                 else:
                     launch_file(save_path)
             if getcfg("uniformity.measure.continuous"):
                 self.measure(event=Event(self.buttons[self.index]))
Beispiel #21
0
    def __init__(self, parent, cgats, worker=None):
        """
		Init new CCXPlot window.

		parent   Parent window (only used for error dialogs)
		cgats    A CCMX/CCSS CGATS instance
		worker   Worker instance
		
		"""

        self.is_ccss = cgats[0].type == "CCSS"

        desc = cgats.get_descriptor()

        if cgats.filename:
            fn, ext = os.path.splitext(os.path.basename(cgats.filename))
        else:
            fn = desc
            if self.is_ccss:
                ext = ".ccss"
            else:
                ext = ".ccmx"

        desc = lang.getstr(ext[1:] + "." + fn, default=desc)

        if self.is_ccss:
            ccxx_type = "spectral"
        else:
            ccxx_type = "matrix"

        title = "%s: %s" % (lang.getstr(ccxx_type), desc)

        if self.is_ccss:
            # Convert to TI3 so we can get XYZ from spectra for coloring

            temp = worker.create_tempdir()
            if isinstance(temp, Exception):
                show_result_dialog(temp, parent)
            else:
                basename = make_filename_safe(desc)
                temp_path = os.path.join(temp, basename + ".ti3")

                cgats[0].type = "CTI3"
                cgats[0].DEVICE_CLASS = "DISPLAY"
                cgats.write(temp_path)

                temp_out_path = os.path.join(temp, basename + ".CIE.ti3")

                result = worker.exec_cmd(get_argyll_util("spec2cie"),
                                         [temp_path, temp_out_path],
                                         capture_output=True)
                if isinstance(result, Exception) or not result:
                    show_result_dialog(
                        UnloggedError(result or "".join(worker.errors)),
                        parent)
                    worker.wrapup(False)
                else:
                    try:
                        cgats = CGATS.CGATS(temp_out_path)
                    except Exception as exception:
                        show_result_dialog(exception, parent)
                    finally:
                        worker.wrapup(False)

        data_format = cgats.queryv1("DATA_FORMAT")
        data = cgats.queryv1("DATA")

        XYZ_max = 0
        self.samples = []

        if self.is_ccss:
            x_min = cgats.queryv1("SPECTRAL_START_NM")
            x_max = cgats.queryv1("SPECTRAL_END_NM")
            bands = cgats.queryv1("SPECTRAL_BANDS")
            lores = bands <= 40
            if lores:
                # Interpolate if lores
                # 1nm intervals
                steps = int(x_max - x_min) + 1
                safe_print("Up-interpolating", bands, "spectral bands to",
                           steps)
                step = (x_max - x_min) / (steps - 1.)
            else:
                step = (x_max - x_min) / (bands - 1.)
            y_min = 0
            y_max = 1

            Y_max = 0
            for i, sample in data.items():
                # Get nm and spectral power
                values = []
                x = x_min
                for k in data_format.values():
                    if k.startswith("SPEC_"):
                        y = sample[k]
                        y_min = min(y, y_min)
                        y_max = max(y, y_max)
                        if lores:
                            values.append(y)
                        else:
                            values.append((x, y))
                            x += step
                if lores:
                    # Interpolate if lores. Use Catmull-Rom instead of
                    # PolySpline as we want curves to go through points exactly
                    numvalues = len(values)
                    interp = ICCP.CRInterpolation(values)
                    values = []
                    for i in range(steps):
                        values.append(
                            (x, interp(i / (steps - 1.) * (numvalues - 1.))))
                        x += step
                # Get XYZ for colorization
                XYZ = []
                for component in "XYZ":
                    label = "XYZ_" + component
                    if label in sample:
                        v = sample[label]
                        XYZ_max = max(XYZ_max, v)
                        if label == "XYZ_Y":
                            Y_max = max(Y_max, v)
                        XYZ.append(v)
                self.samples.append((XYZ, values, {}))

            Plot = plot.PolyLine
            Plot._attributes["width"] = 1
        else:
            # CCMX
            cube_size = 2

            x_min = 0

            y_min = 0

            mtx = colormath.Matrix3x3(
                [[sample[k] for k in data_format.values()]
                 for sample in data.values()])
            imtx = mtx.inverted()

            # Get XYZ that colorimeter would measure without matrix (sRGB ref,
            # so not accurate, but useful for visual representation which is all
            # we care about here)
            if cube_size == 2:
                scale = 1
                x_max = 100 * scale
                y_max = x_max * (74.6 / 67.4)
                if sys.platform != "win32":
                    x_center = x_max / 2.
                else:
                    x_center = x_max / 2. - 2.5
                y_center = y_max / 2.
                x_center *= scale
                y_center *= scale
                pos2rgb = [((x_center - 23.7, y_center - 13.7), (0, 0, 1)),
                           ((x_center, y_center + 27.3), (0, 1, 0)),
                           ((x_center + 23.7, y_center - 13.7), (1, 0, 0)),
                           ((x_center - 23.7, y_center + 13.7), (0, 1, 1)),
                           ((x_center, y_center - 27.3), (1, 0, 1)),
                           ((x_center + 23.7, y_center + 13.7), (1, 1, 0)),
                           ((x_center, y_center), (1, 1, 1))]
                attrs_c = {'size': 10}
                attrs_r = {'size': 5}
            else:
                x_max = 100
                y_max = 100
                y = -5
                pos2rgb = []
                for R in range(cube_size):
                    for G in range(cube_size):
                        x = -5
                        y += 10
                        for B in range(cube_size):
                            x += 10
                            pos2rgb.append(((x, y), (v / (cube_size - 1.0)
                                                     for v in (R, G, B))))
                attrs_c = {'marker': 'square', 'size': 10}
                attrs_r = {'marker': 'square', 'size': 5}
            Y_max = (imtx * colormath.get_whitepoint("D65"))[1]
            for i, ((x, y), (R, G, B)) in enumerate(pos2rgb):
                XYZ = list(colormath.RGB2XYZ(R, G, B))
                X, Y, Z = imtx * XYZ
                XYZ_max = max(XYZ_max, X, Y, Z)
                self.samples.append(([X, Y, Z], [(x, y)], attrs_c))
                self.samples.append((XYZ, [(x, y)], attrs_r))

            Plot = plot.PolyMarker

        if self.is_ccss:
            # Protect against division by zero when range is zero
            if not x_max - x_min:
                x_min = 350.0
                x_max = 750.0
            if not y_max - y_min:
                y_min = 0.0
                y_max = 10.0

            y_zero = 0

            self.ccxx_axis_x = (math.floor(x_min / 50.) * 50,
                                math.ceil(x_max / 50.) * 50)
            self.spec_x = (self.ccxx_axis_x[1] - self.ccxx_axis_x[0]) / 50.
            graph_range = nicenum(y_max - y_zero, False)
            d = nicenum(graph_range / (NTICK - 1.0), True)
            self.spec_y = math.ceil(y_max / d)
            self.ccxx_axis_y = (math.floor(y_zero / d) * d, self.spec_y * d)
        else:
            self.ccxx_axis_x = (math.floor(x_min / 20.) * 20,
                                math.ceil(x_max / 20.) * 20)
            self.ccxx_axis_y = (math.floor(y_min), math.ceil(y_max))

        self.gfx = []
        for XYZ, values, attrs in self.samples:
            if len(XYZ) == 3:
                # Got XYZ
                if attrs.get("size") > 11.25:
                    # Colorimeter XYZ
                    if Y_max > 1:
                        # Colorimeter brighter than ref
                        XYZ[:] = [v / Y_max for v in XYZ]
                    else:
                        # Colorimeter dimmer than ref
                        XYZ[:] = [v * Y_max for v in XYZ]
                else:
                    # Ref XYZ
                    if Y_max > 1:
                        # Colorimeter brighter than ref
                        XYZ[:] = [v / Y_max for v in XYZ]
                RGB = tuple(
                    int(v)
                    for v in colormath.XYZ2RGB(*XYZ, scale=255, round_=True))
            else:
                RGB = (153, 153, 153)
            self.gfx.append(Plot(values, colour=wx.Colour(*RGB), **attrs))
        if self.is_ccss:
            # Add a few points at the extremes to define a bounding box
            self.gfx.append(
                plot.PolyLine(
                    [(self.ccxx_axis_x[0], self.ccxx_axis_y[0]),
                     (self.ccxx_axis_x[1], self.ccxx_axis_y[1] - y_min)],
                    colour=wx.Colour(0, 0, 0, 0)))

        ref = cgats.queryv1("REFERENCE")
        if ref:
            ref = get_canonical_instrument_name(safe_unicode(ref, "UTF-8"))

        if not self.is_ccss:
            observers_ab = {}
            for observer in config.valid_values["observer"]:
                observers_ab[observer] = lang.getstr("observer." + observer)
            x_label = [lang.getstr("matrix")]
            x_label.extend(["%9.6f %9.6f %9.6f" % tuple(row) for row in mtx])
            if ref:
                ref_observer = cgats.queryv1("REFERENCE_OBSERVER")
                if ref_observer:
                    ref += ", " + observers_ab.get(ref_observer, ref_observer)
                x_label.append("")
                x_label.append(ref)
            fit_method = cgats.queryv1("FIT_METHOD")
            if fit_method == "xy":
                fit_method = lang.getstr("ccmx.use_four_color_matrix_method")
            elif fit_method:
                fit_method = lang.getstr("perceptual")
            fit_de00_avg = cgats.queryv1("FIT_AVG_DE00")
            if not isinstance(fit_de00_avg, float):
                fit_de00_avg = None
            fit_de00_max = cgats.queryv1("FIT_MAX_DE00")
            if not isinstance(fit_de00_max, float):
                fit_de00_max = None
            if fit_method:
                x_label.append(fit_method)
            fit_de00 = []
            if fit_de00_avg:
                fit_de00.append(
                    "ΔE*00 %s %.4f" %
                    (lang.getstr("profile.self_check.avg"), fit_de00_avg))
            if fit_de00_max:
                fit_de00.append(
                    "ΔE*00 %s %.4f" %
                    (lang.getstr("profile.self_check.max"), fit_de00_max))
            if fit_de00:
                x_label.append("\n".join(fit_de00))
            x_label = "\n".join(x_label)
        else:
            x_label = ""
            if ref:
                x_label += ref + ", "
            x_label += "%.1fnm, %i-%inm" % ((x_max - x_min) /
                                            (bands - 1.0), x_min, x_max)

        scale = max(getcfg("app.dpi") / config.get_default_dpi(), 1)

        style = wx.DEFAULT_FRAME_STYLE

        wx.Frame.__init__(self, None, -1, title, style=style)
        self.SetIcons(config.get_icon_bundle([256, 48, 32, 16], appname))
        self.SetBackgroundColour(BGCOLOUR)
        self.Sizer = wx.GridSizer(1, 1, 0, 0)
        bg = wx.Panel(self)
        bg.SetBackgroundColour(BGCOLOUR)
        bg.Sizer = wx.BoxSizer(wx.VERTICAL)
        self.canvas = canvas = LUTCanvas(bg)
        if self.is_ccss:
            bg.MinSize = (513 * scale, 557 * scale)
            btnsizer = wx.BoxSizer(wx.HORIZONTAL)
            bg.Sizer.Add(btnsizer,
                         flag=wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT,
                         border=16)
            self.toggle_btn = FlatShadedButton(bg,
                                               -1,
                                               label=lang.getstr("spectral"))
            btnsizer.Add(self.toggle_btn, 1)
            self.Sizer.Add(bg, 1, flag=wx.EXPAND)
            bg.Sizer.Add(canvas, 1, flag=wx.EXPAND)
        else:
            self.Sizer.Add(bg, flag=wx.ALIGN_CENTER)
            canvas_w = 240 * scale
            canvas.MinSize = (canvas_w, canvas_w * (74.6 / 67.4))
            bg.Sizer.Add(canvas, flag=wx.ALIGN_CENTER)
        label = wx.StaticText(bg,
                              -1,
                              x_label.replace("&", "&&"),
                              style=wx.ALIGN_CENTRE_HORIZONTAL)
        label.SetForegroundColour(FGCOLOUR)
        label.SetMaxFontSize(11)
        bg.Sizer.Add(label,
                     flag=wx.ALIGN_CENTER | wx.ALL & ~wx.TOP,
                     border=16 * scale)
        canvas.SetBackgroundColour(BGCOLOUR)
        canvas.SetEnableCenterLines(False)
        canvas.SetEnableDiagonals(False)
        canvas.SetEnableGrid(True)
        canvas.enableTicks = (True, True)
        canvas.tickPen = wx.Pen(GRIDCOLOUR, canvas._pointSize[0])
        canvas.SetEnablePointLabel(False)
        canvas.SetEnableTitle(True)
        canvas.SetForegroundColour(FGCOLOUR)
        canvas.SetGridColour(GRIDCOLOUR)
        canvas.canvas.BackgroundColour = BGCOLOUR
        if self.is_ccss:
            canvas.HandCursor = wx.StockCursor(wx.CURSOR_SIZING)
            canvas.SetCursor(canvas.HandCursor)
        else:
            canvas.canvas.Unbind(wx.EVT_LEFT_DCLICK)
            canvas.SetEnableDrag(False)
            canvas.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
            canvas.SetXSpec('none')
            canvas.SetYSpec('none')

        # CallAfter is needed under GTK as usual
        wx.CallAfter(self.draw_ccxx)

        if self.is_ccss:
            self.Bind(wx.EVT_KEY_DOWN, self.key_handler)
            for child in self.GetAllChildren():
                child.Bind(wx.EVT_KEY_DOWN, self.key_handler)
                child.Bind(wx.EVT_MOUSEWHEEL, self.OnWheel)

            self.toggle_btn.Bind(wx.EVT_BUTTON, self.toggle_draw)

            self.Bind(wx.EVT_SIZE, self.OnSize)
        else:
            bg.Sizer.Add((0, 16))
        self.Sizer.SetSizeHints(self)
        self.Sizer.Layout()
Beispiel #22
0
def update(report_path, pack=True):
    """ Update existing report with current template files. 
	
	Also creates a backup copy of the old report.
	
	"""
    # read original report
    try:
        orig_report = codecs.open(report_path, "r", "UTF-8")
    except (IOError, OSError) as exception:
        raise exception.__class__(lang.getstr("error.file.open", report_path))
    orig_report_html = orig_report.read()
    orig_report.close()

    data = (
        ("${PLANCKIAN}", 'id="FF_planckian"\s*(.*?)\s*disabled="disabled"', 0),
        ("${DISPLAY}", '"FF_display"\s*value="(.+?)"\s*/?>', 0),
        ("${INSTRUMENT}", '"FF_instrument"\s*value="(.+?)"\s*/?>', 0),
        ("${CORRECTION_MATRIX}",
         '"FF_correction_matrix"\s*value="(.+?)"\s*/?>', 0),
        ("${BLACKPOINT}", '"FF_blackpoint"\s*value="(.+?)"\s*/?>', 0),
        ("${WHITEPOINT}", '"FF_whitepoint"\s*value="(.+?)"\s*/?>', 0),
        ("${WHITEPOINT_NORMALIZED}",
         '"FF_whitepoint_normalized"\s*value="(.+?)"\s*/?>', 0),
        ("${PROFILE}", '"FF_profile"\s*value="(.+?)"\s*/?>', 0),
        ("${PROFILE_WHITEPOINT}",
         '"FF_profile_whitepoint"\s*value="(.+?)"\s*/?>', 0),
        ("${PROFILE_WHITEPOINT_NORMALIZED}",
         '"FF_profile_whitepoint_normalized"\s*value="(.+?)"\s*/?>', 0),
        ("${SIMULATION_PROFILE}", 'SIMULATION_PROFILE\s*=\s*"(.+?)"[;,]', 0),
        ("${TRC_GAMMA}", 'BT_1886_GAMMA\s*=\s*(.+?)[;,]', 0),
        ("${TRC_GAMMA}", 'TRC_GAMMA\s*=\s*(.+?)[;,]', 0),
        ("${TRC_GAMMA_TYPE}", 'BT_1886_GAMMA_TYPE\s*=\s*"(.+?)"[;,]', 0),
        ("${TRC_GAMMA_TYPE}", 'TRC_GAMMA_TYPE\s*=\s*"(.+?)"[;,]', 0),
        ("${TRC_OUTPUT_OFFSET}", 'TRC_OUTPUT_OFFSET\s*=\s*(.+?)[;,]', 0),
        ("${TRC}", 'TRC\s*=\s*"(.+?)"[;,]', 0),
        ("${WHITEPOINT_SIMULATION}", 'WHITEPOINT_SIMULATION\s*=\s*(.+?)[;,]',
         0),
        ("${WHITEPOINT_SIMULATION_RELATIVE}",
         'WHITEPOINT_SIMULATION_RELATIVE\s*=\s*(.+?)[;,]', 0),
        ("${DEVICELINK_PROFILE}", 'DEVICELINK_PROFILE\s*=\s*"(.+?)"[;,]', 0),
        ("${TESTCHART}", '"FF_testchart"\s*value="(.+?)"\s*/?>', 0),
        ("${ADAPTION}", '"FF_adaption"\s*value="(.+?)"\s*/?>', 0),
        ("${DATETIME}", '"FF_datetime"\s*value="(.+?)"\s*/?>', 0),
        ("${REF}", '"FF_data_ref"\s*value="(.+?)"\s*/?>', re.DOTALL),
        ("${MEASURED}", '"FF_data_in"\s*value="(.+?)"\s*/?>', re.DOTALL),
        ("${CAL_ENTRYCOUNT}", "CAL_ENTRYCOUNT\s*=\s*(.+?)[;,]$", re.M),
        ("${CAL_RGBLEVELS}", "CAL_RGBLEVELS\s*=\s*(.+?)[;,]$", re.M),
        ("${GRAYSCALE}", "CRITERIA_GRAYSCALE\s*=\s*(.+?)[;,]$", re.M),
        ("${REPORT_TYPE}", '<title>(.+?) Report', 0),
        # Uniformity report
        ("${DISPLAY}", "\u2014 (.+?) \u2014", 0),
        ("${DATETIME}", "\u2014 .+? \u2014 (.+?)</title>", 0),
        ("${ROWS}", 'rows\s*=\s*(.+?)[;,]', 0),
        ("${COLS}", 'cols\s*=\s*(.+?)[;,]', 0),
        ("${RESULTS}", 'results\s*=\s*(.+?), locus = ', 0),
        ("${LOCUS}", "locus\s*=\s*'([^']+)'", 0))

    placeholders2data = {
        "${REPORT_VERSION}": version_short,
        "${CORRECTION_MATRIX}": "Unknown",
        "${ADAPTION}": "None",
        "${CAL_ENTRYCOUNT}": "null",
        "${CAL_RGBLEVELS}": "null",
        "${GRAYSCALE}": "null",
        "${BLACKPOINT}": "-1 -1 -1",
        "${TRC_GAMMA}": "null",
        "${TRC_OUTPUT_OFFSET}": "0",
        "${WHITEPOINT_SIMULATION}": "false",
        "${WHITEPOINT_SIMULATION_RELATIVE}": "false"
    }

    templatename = "report"
    for placeholder, pattern, flags in data:
        result = re.search(pattern, orig_report_html, flags)
        if result or not placeholders2data.get(placeholder):
            if (placeholder == "${TRC}" and not result
                    and "${TRC_GAMMA}" in placeholders2data):
                default = "BT.1886"
            else:
                default = ""
            placeholders2data[placeholder] = result.groups(
            )[0] if result else default
        if result and placeholder == "${COLS}":
            templatename = "uniformity"

    # backup original report
    shutil.copy2(report_path,
                 "%s.%s" % (report_path, strftime("%Y-%m-%d_%H-%M-%S")))

    create(report_path, placeholders2data, pack, templatename)
Beispiel #23
0
def install_profile(device_id,
                    profile,
                    timeout=CD_CLIENT_IMPORT_DAEMON_TIMEOUT / 1000.0,
                    logfn=None):
    """
	Install profile for device
	
	timeout				  Time to allow for colord to pick up new profiles
						  (recommended not below 2 secs)
	
	"""

    profile_installname = os.path.join(xdg_data_home, 'icc',
                                       os.path.basename(profile.fileName))

    profile_exists = os.path.isfile(profile_installname)
    if (profile.fileName != profile_installname and profile_exists):
        if logfn:
            logfn("About to overwrite existing", profile_installname)
        profile.fileName = None

    if profile.ID == "\0" * 16:
        profile.calculateID()
        profile.fileName = None
    profile_id = "icc-" + hexlify(profile.ID)

    # Write profile to destination
    profile_installdir = os.path.dirname(profile_installname)
    if not os.path.isdir(profile_installdir):
        os.makedirs(profile_installdir)
    # colormgr seems to have a bug where the first attempt at importing a
    # specific profile can time out. This seems to be work-aroundable by
    # writing the profile ourself first, and then importing.
    if not profile.fileName or not profile_exists:
        if logfn:
            logfn("Writing", profile_installname)
        profile.fileName = profile_installname
        profile.write()

    cdprofile = None

    if Colord and not isinstance(Colord, DBusObject):
        client = client_connect()
    else:
        # Query colord for profile
        try:
            cdprofile = get_object_path(profile_id, "profile")
        except CDObjectQueryError as exception:
            # Profile not found
            pass

        colormgr = which("colormgr")
        if not colormgr:
            raise CDError("colormgr helper program not found")

        from worker import printcmdline

        cmd = safe_str(colormgr)

        if not cdprofile:
            # Import profile

            if logfn:
                logfn("-" * 80)
                logfn(lang.getstr("commandline"))

            args = [cmd, "import-profile", safe_str(profile.fileName)]
            printcmdline(args[0], args[1:], fn=logfn)
            if logfn:
                logfn("")

            ts = time.time()

            maxtries = 3

            for n in range(1, maxtries + 1):
                if logfn:
                    logfn("Trying to import profile, attempt %i..." % n)
                try:
                    p = sp.Popen(args, stdout=sp.PIPE, stderr=sp.STDOUT)
                    stdout, stderr = p.communicate()
                except Exception as exception:
                    raise CDError(safe_str(exception))
                if logfn and stdout.strip():
                    logfn(stdout.strip())
                if p.returncode == 0 or os.path.isfile(profile_installname):
                    if logfn:
                        logfn("...ok")
                    break
                elif logfn:
                    logfn("...failed!")

            if p.returncode != 0 and not os.path.isfile(profile_installname):
                raise CDTimeout("Trying to import profile '%s' failed after "
                                "%i tries." % (profile.fileName, n))

    if not cdprofile:
        # Query colord for newly added profile
        for i in range(int(timeout / 1.0)):
            try:
                if Colord and not isinstance(Colord, DBusObject):
                    cdprofile = client.find_profile_sync(
                        profile_id, cancellable)
                else:
                    cdprofile = get_object_path(profile_id, "profile")
            except CDObjectQueryError as exception:
                # Profile not found
                pass
            if cdprofile:
                break
            # Give colord time to pick up the profile
            sleep(1)

        if not cdprofile:
            raise CDTimeout(
                "Querying for profile %r returned no result for %s "
                "secs" % (profile_id, timeout))

    errmsg = "Could not make profile %s default for device %s" % (profile_id,
                                                                  device_id)

    if Colord and not isinstance(Colord, DBusObject):
        # Connect to profile
        if not cdprofile.connect_sync(cancellable):
            raise CDError("Could not connect to profile")

        # Connect to existing device
        device = device_connect(client, device_id)

        # Add profile to device
        try:
            device.add_profile_sync(Colord.DeviceRelation.HARD, cdprofile,
                                    cancellable)
        except Exception as exception:
            # Profile may already have been added
            warnings.warn(safe_str(exception), Warning)

        # Make profile default for device
        if not device.make_profile_default_sync(cdprofile, cancellable):
            raise CDError(errmsg)
    else:
        # Find device object path
        device = get_object_path(device_id, "device")

        if logfn:
            logfn("-" * 80)
            logfn(lang.getstr("commandline"))

        # Add profile to device
        # (Ignore returncode as profile may already have been added)
        args = [cmd, "device-add-profile", device, cdprofile]
        printcmdline(args[0], args[1:], fn=logfn)
        if logfn:
            logfn("")
        try:
            p = sp.Popen(args, stdout=sp.PIPE, stderr=sp.STDOUT)
            stdout, stderr = p.communicate()
        except Exception as exception:
            raise CDError(safe_str(exception))
        if logfn and stdout.strip():
            logfn(stdout.strip())

        if logfn:
            logfn("")
            logfn(lang.getstr("commandline"))

        # Make profile default for device
        args = [cmd, "device-make-profile-default", device, cdprofile]
        printcmdline(args[0], args[1:], fn=logfn)
        if logfn:
            logfn("")
        try:
            p = sp.Popen(args, stdout=sp.PIPE, stderr=sp.STDOUT)
            stdout, stderr = p.communicate()
        except Exception as exception:
            raise CDError(safe_str(exception))
        else:
            if p.returncode != 0:
                raise CDError(stdout.strip() or errmsg)
        if logfn and stdout.strip():
            logfn(stdout.strip())
    def __init__(self,
                 parent=None,
                 handler=None,
                 keyhandler=None,
                 start_timer=True):
        BaseFrame.__init__(self,
                           parent,
                           wx.ID_ANY,
                           lang.getstr("measurement.untethered"),
                           style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL,
                           name="untetheredframe")
        self.SetIcons(get_icon_bundle([256, 48, 32, 16], appname))
        self.sizer = wx.FlexGridSizer(2, 1, 0, 0)
        self.sizer.AddGrowableCol(0)
        self.sizer.AddGrowableRow(0)
        self.sizer.AddGrowableRow(1)
        self.panel = wx_Panel(self)
        self.SetSizer(self.sizer)
        self.sizer.Add(self.panel, 1, wx.EXPAND)
        self.panel.SetBackgroundColour(BGCOLOUR)
        panelsizer = wx.FlexGridSizer(3, 2, 8, 8)
        panelsizer.AddGrowableCol(0)
        panelsizer.AddGrowableCol(1)
        panelsizer.AddGrowableRow(1)
        self.panel.SetSizer(panelsizer)
        self.label_RGB = wx.StaticText(self.panel, wx.ID_ANY, " ")
        self.label_RGB.SetForegroundColour(FGCOLOUR)
        panelsizer.Add(self.label_RGB,
                       0,
                       wx.TOP | wx.LEFT | wx.EXPAND,
                       border=8)
        self.label_XYZ = wx.StaticText(self.panel, wx.ID_ANY, " ")
        self.label_XYZ.SetForegroundColour(FGCOLOUR)
        panelsizer.Add(self.label_XYZ,
                       0,
                       wx.TOP | wx.RIGHT | wx.EXPAND,
                       border=8)
        if sys.platform == "darwin":
            style = wx.BORDER_THEME
        else:
            style = wx.BORDER_SIMPLE
        self.panel_RGB = BitmapBackgroundPanel(self.panel,
                                               size=(256, 256),
                                               style=style)
        self.panel_RGB.scalebitmap = (True, True)
        self.panel_RGB.SetBitmap(
            getbitmap("theme/checkerboard-32x32x5-333-444"))
        panelsizer.Add(self.panel_RGB, 1, wx.LEFT | wx.EXPAND, border=8)
        self.panel_XYZ = BitmapBackgroundPanel(self.panel,
                                               size=(256, 256),
                                               style=style)
        self.panel_XYZ.scalebitmap = (True, True)
        self.panel_XYZ.SetBitmap(
            getbitmap("theme/checkerboard-32x32x5-333-444"))
        panelsizer.Add(self.panel_XYZ, 1, wx.RIGHT | wx.EXPAND, border=8)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.back_btn = FlatShadedButton(self.panel,
                                         bitmap=geticon(10, "back"),
                                         label="",
                                         fgcolour=FGCOLOUR)
        self.back_btn.Bind(wx.EVT_BUTTON, self.back_btn_handler)
        sizer.Add(self.back_btn, 0, wx.LEFT | wx.RIGHT, border=8)
        self.label_index = wx.StaticText(self.panel, wx.ID_ANY, " ")
        self.label_index.SetForegroundColour(FGCOLOUR)
        sizer.Add(self.label_index, 0, wx.ALIGN_CENTER_VERTICAL)
        self.next_btn = FlatShadedButton(self.panel,
                                         bitmap=geticon(10, "play"),
                                         label="",
                                         fgcolour=FGCOLOUR)
        self.next_btn.Bind(wx.EVT_BUTTON, self.next_btn_handler)
        sizer.Add(self.next_btn, 0, wx.LEFT, border=8)
        sizer.Add((12, 1), 1)
        self.measure_auto_cb = CustomCheckBox(self.panel, wx.ID_ANY,
                                              lang.getstr("auto"))
        self.measure_auto_cb.SetForegroundColour(FGCOLOUR)
        self.measure_auto_cb.Bind(wx.EVT_CHECKBOX,
                                  self.measure_auto_ctrl_handler)
        sizer.Add(self.measure_auto_cb, 0,
                  wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
        panelsizer.Add(sizer, 0, wx.BOTTOM | wx.EXPAND, border=8)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.measure_btn = FlatShadedButton(self.panel,
                                            bitmap=geticon(10, "play"),
                                            label=lang.getstr("measure"),
                                            fgcolour=FGCOLOUR)
        self.measure_btn.Bind(wx.EVT_BUTTON, self.measure_btn_handler)
        sizer.Add(self.measure_btn, 0, wx.RIGHT, border=6)
        # Sound when measuring
        # Needs to be stereo!
        self.measurement_sound = audio.Sound(get_data_path("beep.wav"))
        self.commit_sound = audio.Sound(get_data_path("camera_shutter.wav"))
        bitmap = self.get_sound_on_off_btn_bitmap()
        self.sound_on_off_btn = FlatShadedButton(self.panel,
                                                 bitmap=bitmap,
                                                 fgcolour=FGCOLOUR)
        self.sound_on_off_btn.SetToolTipString(
            lang.getstr("measurement.play_sound"))
        self.sound_on_off_btn.Bind(wx.EVT_BUTTON,
                                   self.measurement_play_sound_handler)
        sizer.Add(self.sound_on_off_btn, 0)
        sizer.Add((12, 1), 1)
        self.finish_btn = FlatShadedButton(self.panel,
                                           label=lang.getstr("finish"),
                                           fgcolour=FGCOLOUR)
        self.finish_btn.Bind(wx.EVT_BUTTON, self.finish_btn_handler)
        sizer.Add(self.finish_btn, 0, wx.RIGHT, border=8)
        panelsizer.Add(sizer, 0, wx.BOTTOM | wx.EXPAND, border=8)

        self.grid = CustomGrid(self, -1, size=(536, 256))
        self.grid.DisableDragColSize()
        self.grid.DisableDragRowSize()
        self.grid.SetScrollRate(0, 5)
        self.grid.SetCellHighlightROPenWidth(0)
        self.grid.SetColLabelSize(self.grid.GetDefaultRowSize())
        self.grid.SetDefaultCellAlignment(wx.ALIGN_CENTER, wx.ALIGN_CENTER)
        self.grid.SetRowLabelAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTER)
        self.grid.draw_horizontal_grid_lines = False
        self.grid.draw_vertical_grid_lines = False
        self.grid.style = ""
        self.grid.CreateGrid(0, 9)
        self.grid.SetRowLabelSize(62)
        for i in range(9):
            if i in (3, 4):
                size = self.grid.GetDefaultRowSize()
                if i == 4:
                    attr = wx.grid.GridCellAttr()
                    attr.SetBackgroundColour(wx.Colour(0, 0, 0, 0))
                    self.grid.SetColAttr(i, attr)
            else:
                size = 62
            self.grid.SetColSize(i, size)
        for i, label in enumerate(
            ["R", "G", "B", "", "", "L*", "a*", "b*", ""]):
            self.grid.SetColLabelValue(i, label)
        self.grid.SetCellHighlightPenWidth(0)
        self.grid.SetDefaultCellBackgroundColour(
            self.grid.GetLabelBackgroundColour())
        font = self.grid.GetDefaultCellFont()
        if font.PointSize > 11:
            font.PointSize = 11
            self.grid.SetDefaultCellFont(font)
        self.grid.SetSelectionMode(wx.grid.Grid.wxGridSelectRows)
        self.grid.EnableEditing(False)
        self.grid.EnableGridLines(False)
        self.grid.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK,
                       self.grid_left_click_handler)
        self.grid.Bind(wx.grid.EVT_GRID_SELECT_CELL,
                       self.grid_left_click_handler)
        self.sizer.Add(self.grid, 1, wx.EXPAND)

        self.Fit()
        self.SetMinSize(self.GetSize())

        self.keyhandler = keyhandler
        self.id_to_keycode = {}
        if sys.platform == "darwin":
            # Use an accelerator table for tab, space, 0-9, A-Z, numpad,
            # navigation keys and processing keys
            keycodes = [wx.WXK_TAB, wx.WXK_SPACE]
            keycodes.extend(list(range(ord("0"), ord("9"))))
            keycodes.extend(list(range(ord("A"), ord("Z"))))
            keycodes.extend(numpad_keycodes)
            keycodes.extend(nav_keycodes)
            keycodes.extend(processing_keycodes)
            for keycode in keycodes:
                self.id_to_keycode[wx.Window.NewControlId()] = keycode
            accels = []
            for id, keycode in self.id_to_keycode.items():
                self.Bind(wx.EVT_MENU, self.key_handler, id=id)
                accels.append((wx.ACCEL_NORMAL, keycode, id))
                if keycode == wx.WXK_TAB:
                    accels.append((wx.ACCEL_SHIFT, keycode, id))
            self.SetAcceleratorTable(wx.AcceleratorTable(accels))
        else:
            self.Bind(wx.EVT_CHAR_HOOK, self.key_handler)

        self.Bind(wx.EVT_KEY_DOWN, self.key_handler)

        # Event handlers
        self.Bind(wx.EVT_CLOSE, self.OnClose, self)
        self.Bind(wx.EVT_MOVE, self.OnMove, self)
        self.Bind(wx.EVT_SIZE, self.OnResize, self)
        self.timer = wx.Timer(self)
        if handler:
            self.Bind(wx.EVT_TIMER, handler, self.timer)
        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)

        # Final initialization steps
        for child in self.GetAllChildren():
            if (sys.platform == "win32" and sys.getwindowsversion() >= (6, )
                    and isinstance(child, wx.Panel)):
                # No need to enable double buffering under Linux and Mac OS X.
                # Under Windows, enabling double buffering on the panel seems
                # to work best to reduce flicker.
                child.SetDoubleBuffered(True)
        self.logger = get_file_logger("untethered")
        self._setup()

        self.Show()

        if start_timer:
            self.start_timer()
 def parse_txt(self, txt):
     if not txt:
         return
     self.logger.info("%r" % txt)
     data_len = len(self.cgats[0].DATA)
     if (self.grid.GetNumberRows() < data_len):
         self.index = 0
         self.index_max = data_len - 1
         self.grid.AppendRows(data_len - self.grid.GetNumberRows())
         for i in self.cgats[0].DATA:
             self.grid.SetRowLabelValue(i, "%i" % (i + 1))
             row = self.cgats[0].DATA[i]
             RGB = []
             for j, label in enumerate("RGB"):
                 value = int(round(row["RGB_%s" % label] / 100.0 * 255))
                 self.grid.SetCellValue(row.SAMPLE_ID - 1, j, "%i" % value)
                 RGB.append(value)
             self.grid.SetCellBackgroundColour(row.SAMPLE_ID - 1, 3,
                                               wx.Colour(*RGB))
     if "Connecting to the instrument" in txt:
         self.Pulse(lang.getstr("instrument.initializing"))
     if "Spot read needs a calibration" in txt:
         self.is_measuring = False
     if "Spot read failed" in txt:
         self.last_error = txt
     if "Result is XYZ:" in txt:
         self.last_error = None
         if getcfg("measurement.play_sound"):
             self.measurement_sound.safe_play()
         # Result is XYZ: d.dddddd d.dddddd d.dddddd, D50 Lab: d.dddddd d.dddddd d.dddddd
         XYZ = re.search(
             "XYZ:\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)",
             txt)
         if not XYZ:
             return
         XYZ = [float(v) for v in XYZ.groups()]
         row = self.cgats[0].DATA[self.index]
         if (row["RGB_R"] == 100 and row["RGB_G"] == 100
                 and row["RGB_B"] == 100):
             # White
             if XYZ[1] > 0:
                 self.cgats[0].add_keyword("LUMINANCE_XYZ_CDM2",
                                           "%.6f %.6f %.6f" % tuple(XYZ))
                 self.white_XYZ = XYZ
         Lab1 = colormath.XYZ2Lab(*self.last_XYZ)
         Lab2 = colormath.XYZ2Lab(*XYZ)
         delta = colormath.delta(*Lab1 + Lab2)
         if debug or test or verbose > 1:
             safe_print("Last recorded Lab: %.4f %.4f %.4f" % Lab1)
             safe_print("Current Lab: %.4f %.4f %.4f" % Lab2)
             safe_print("Delta E to last recorded Lab: %.4f" % delta["E"])
             safe_print("Abs. delta L to last recorded Lab: %.4f" %
                        abs(delta["L"]))
             safe_print("Abs. delta C to last recorded Lab: %.4f" %
                        abs(delta["C"]))
         if (delta["E"] > getcfg("untethered.min_delta") or
             (abs(delta["L"]) > getcfg("untethered.min_delta.lightness")
              and abs(delta["C"]) < getcfg("untethered.max_delta.chroma"))):
             self.measure_count += 1
             if self.measure_count == 2:
                 if getcfg("measurement.play_sound"):
                     self.commit_sound.safe_play()
                 self.measure_count = 0
                 # Reset row label
                 self.grid.SetRowLabelValue(self.index,
                                            "%i" % (self.index + 1))
                 # Update CGATS
                 query = self.cgats[0].queryi({
                     "RGB_R": row["RGB_R"],
                     "RGB_G": row["RGB_G"],
                     "RGB_B": row["RGB_B"]
                 })
                 for i in query:
                     index = query[i].SAMPLE_ID - 1
                     if index not in self.measured:
                         self.measured.append(index)
                     if index == self.index + 1:
                         # Increment the index if we have consecutive patches
                         self.index = index
                     query[i]["XYZ_X"], query[i]["XYZ_Y"], query[i][
                         "XYZ_Z"] = XYZ
                 if getcfg("untethered.measure.auto"):
                     self.show_RGB(False, False)
                 self.show_XYZ()
                 Lab, color = self.get_Lab_RGB()
                 for i in query:
                     row = query[i]
                     self.grid.SetCellBackgroundColour(
                         query[i].SAMPLE_ID - 1, 4, wx.Colour(*color))
                     for j in range(3):
                         self.grid.SetCellValue(query[i].SAMPLE_ID - 1,
                                                5 + j, "%.2f" % Lab[j])
                 self.grid.MakeCellVisible(self.index, 0)
                 self.grid.ForceRefresh()
                 if len(self.measured) == data_len:
                     self.finished = True
                     self.finish_btn.Enable()
                 else:
                     # Jump to the next or previous unmeasured patch, if any
                     index = self.index
                     for i in range(self.index + 1, data_len):
                         if (getcfg("untethered.measure.auto")
                                 or not i in self.measured):
                             self.index = i
                             break
                     if self.index == index:
                         for i in range(self.index - 1, -1, -1):
                             if not i in self.measured:
                                 self.index = i
                                 break
                     if self.index != index:
                         # Mark the row containing the next/previous patch
                         self.grid.SetRowLabelValue(
                             self.index, "\u25ba %i" % (self.index + 1))
                         self.grid.MakeCellVisible(self.index, 0)
     if "key to take a reading" in txt and not self.last_error:
         if getcfg("untethered.measure.auto") and self.is_measuring:
             if not self.finished and self.keepGoing:
                 self.measure()
             else:
                 self.enable_btns()
         else:
             show_XYZ = self.index in self.measured
             delay = getcfg("untethered.measure.manual.delay") * 1000
             wx.CallLater(delay, self.show_RGB, not show_XYZ)
             if show_XYZ:
                 wx.CallLater(delay, self.show_XYZ)
             wx.CallLater(delay, self.enable_btns)
 def Pulse(self, msg=""):
     if msg == lang.getstr("instrument.initializing"):
         self.label_RGB.SetLabel(msg)
     return self.keepGoing, False
def extract_device_gray_primaries(ti3,
                                  gray=True,
                                  logfn=None,
                                  include_neutrals=False,
                                  neutrals_ab_threshold=0.1):
    """
	Extract gray or primaries into new TI3
	
	Return extracted ti3, extracted RGB to XYZ mapping and remaining RGB to XYZ

	"""
    filename = ti3.filename
    ti3 = ti3.queryi1("DATA")
    ti3.filename = filename
    ti3_extracted = CGATS.CGATS("""CTI3
DEVICE_CLASS "DISPLAY"
COLOR_REP "RGB_XYZ"
BEGIN_DATA_FORMAT
END_DATA_FORMAT
BEGIN_DATA
END_DATA""")[0]
    ti3_extracted.DATA_FORMAT.update(ti3.DATA_FORMAT)
    subset = [(100.0, 100.0, 100.0), (0.0, 0.0, 0.0)]
    if not gray:
        subset.extend([(100.0, 0.0, 0.0), (0.0, 100.0, 0.0), (0.0, 0.0, 100.0),
                       (50.0, 50.0, 50.0)])
        if logfn:
            logfn("Extracting neutrals and primaries from %s" % ti3.filename)
    else:
        if logfn:
            logfn("Extracting neutrals from %s" % ti3.filename)
    RGB_XYZ_extracted = OrderedDict()
    RGB_XYZ_remaining = OrderedDict()
    dupes = {}
    if include_neutrals:
        white = ti3.get_white_cie("XYZ")
        str_thresh = str(neutrals_ab_threshold)
        round_digits = len(str_thresh[str_thresh.find(".") + 1:])
    for i, item in ti3.DATA.items():
        if not i:
            # Check if fields are missing
            for prefix in ("RGB", "XYZ"):
                for suffix in prefix:
                    key = "%s_%s" % (prefix, suffix)
                    if not key in item:
                        raise Error(
                            lang.getstr("error.testchart.missing_fields",
                                        (ti3.filename, key)))
        RGB = (item["RGB_R"], item["RGB_G"], item["RGB_B"])
        XYZ = (item["XYZ_X"], item["XYZ_Y"], item["XYZ_Z"])
        for RGB_XYZ in (RGB_XYZ_extracted, RGB_XYZ_remaining):
            if RGB in RGB_XYZ:
                if RGB != (100.0, 100.0, 100.0):
                    # Add to existing values for averaging later
                    # if it's not white (all other readings are scaled to the
                    # white Y by dispread, so we don't alter it. Note that it's
                    # always the first encountered white that will have Y = 100,
                    # even if subsequent white readings may be higher)
                    XYZ = tuple(RGB_XYZ[RGB][i] + XYZ[i] for i in range(3))
                    if not RGB in dupes:
                        dupes[RGB] = 1.0
                    dupes[RGB] += 1.0
                elif RGB in subset:
                    # We have white already, remove it from the subset so any
                    # additional white readings we encounter are ignored
                    subset.remove(RGB)
        if ((gray and (item["RGB_R"] == item["RGB_G"] == item["RGB_B"] or
                       (include_neutrals and all(
                           round(abs(v), round_digits) <= neutrals_ab_threshold
                           for v in colormath.XYZ2Lab(item["XYZ_X"],
                                                      item["XYZ_Y"],
                                                      item["XYZ_Z"],
                                                      whitepoint=white)[1:])))
             and not RGB in [(100.0, 100.0, 100.0), (0.0, 0.0, 0.0)])
                or RGB in subset):
            ti3_extracted.DATA.add_data(item)
            RGB_XYZ_extracted[RGB] = XYZ
        elif not RGB in [(100.0, 100.0, 100.0), (0.0, 0.0, 0.0)]:
            RGB_XYZ_remaining[RGB] = XYZ
    for RGB, count in dupes.items():
        for RGB_XYZ in (RGB_XYZ_extracted, RGB_XYZ_remaining):
            if RGB in RGB_XYZ:
                # Average values
                XYZ = tuple(RGB_XYZ[RGB][i] / count for i in range(3))
                RGB_XYZ[RGB] = XYZ
    return ti3_extracted, RGB_XYZ_extracted, RGB_XYZ_remaining
def extract_cal_from_profile(profile,
                             out_cal_path=None,
                             raise_on_missing_cal=True,
                             prefer_cal=False):
    """ Extract calibration from 'targ' tag in profile or vcgt as fallback """

    white = False

    # Check if calibration is included in TI3
    targ = profile.tags.get("targ", profile.tags.get("CIED"))
    if isinstance(targ, ICCP.Text):
        cal = extract_cal_from_ti3(targ)
        if cal:
            check = cal
            get_cgats = CGATS.CGATS
            arg = cal
    else:
        cal = None
    if not cal:
        # Convert calibration information from embedded WCS profile
        # (if present) to VideCardFormulaType if the latter is not present
        if (isinstance(profile.tags.get("MS00"), ICCP.WcsProfilesTagType)
                and not "vcgt" in profile.tags):
            profile.tags["vcgt"] = profile.tags["MS00"].get_vcgt()

        # Get the calibration from profile vcgt
        check = isinstance(profile.tags.get("vcgt"), ICCP.VideoCardGammaType)
        get_cgats = vcgt_to_cal
        arg = profile

    if not check:
        if raise_on_missing_cal:
            raise Error(lang.getstr("profile.no_vcgt"))
        else:
            return False
    else:
        try:
            cgats = get_cgats(arg)
        except (IOError, CGATS.CGATSError) as exception:
            raise Error(lang.getstr("cal_extraction_failed"))
    if (cal and not prefer_cal
            and isinstance(profile.tags.get("vcgt"), ICCP.VideoCardGammaType)):
        # When vcgt is nonlinear, prefer it
        # Check for video levels encoding
        if cgats.queryv1("TV_OUTPUT_ENCODING") == "YES":
            black, white = (16, 235)
        else:
            output_enc = cgats.queryv1("OUTPUT_ENCODING")
            if output_enc:
                try:
                    black, white = (float(v) for v in output_enc.split())
                except (TypeError, ValueError):
                    white = False
        cgats = vcgt_to_cal(profile)
        if white and (black, white) != (0, 255):
            safe_print("Need to un-scale vcgt from video levels (%s..%s)" %
                       (black, white))
            # Need to un-scale video levels
            data = cgats.queryv1("DATA")
            if data:
                safe_print("Un-scaling vcgt from video levels (%s..%s)" %
                           (black, white))
                encoding_mismatch = False
                # For video encoding the extra bits of
                # precision are created by bit shifting rather
                # than scaling, so we need to scale the fp
                # value to account for this
                oldmin = (black / 256.0) * (65536 / 65535.)
                oldmax = (white / 256.0) * (65536 / 65535.)
                for entry in data.values():
                    for column in "RGB":
                        v_old = entry["RGB_" + column]
                        lvl = round(v_old * (65535 / 65536.) * 256, 2)
                        if lvl < round(black, 2) or lvl > round(white, 2):
                            # Can't be right. Metadata says it's video encoded,
                            # but clearly exceeds the encoding range.
                            safe_print("Warning: Metadata claims video levels "
                                       "(%s..%s) but vcgt value %s exceeds "
                                       "encoding range. Using values as-is." %
                                       (round(black, 2), round(white, 2), lvl))
                            encoding_mismatch = True
                            break
                        v_new = colormath.convert_range(
                            v_old, oldmin, oldmax, 0, 1)
                        entry["RGB_" + column] = min(max(v_new, 0), 1)
                    if encoding_mismatch:
                        break
                if encoding_mismatch:
                    cgats = vcgt_to_cal(profile)
                # Add video levels hint to CGATS
                elif (black, white) == (16, 235):
                    cgats[0].add_keyword("TV_OUTPUT_ENCODING", "YES")
                else:
                    cgats[0].add_keyword(
                        "OUTPUT_ENCODING",
                        " ".join(str(v) for v in (black, white)))
            else:
                safe_print("Warning - no un-scaling applied - no "
                           "calibration data!")
    if out_cal_path:
        cgats.write(out_cal_path)
    return cgats
Beispiel #29
0
    def __init__(self,
                 parent=None,
                 handler=None,
                 keyhandler=None,
                 start_timer=True,
                 rows=None,
                 cols=None):
        if not rows:
            rows = getcfg("uniformity.rows")
        if not cols:
            cols = getcfg("uniformity.cols")
        BaseFrame.__init__(self,
                           parent,
                           wx.ID_ANY,
                           lang.getstr("report.uniformity"),
                           style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL,
                           name="displayuniformityframe")
        self.SetIcons(get_icon_bundle([256, 48, 32, 16], appname))
        self.SetBackgroundColour(BGCOLOUR)
        self.sizer = wx.GridSizer(rows, cols, 0, 0)
        self.SetSizer(self.sizer)

        self.rows = rows
        self.cols = cols
        self.colors = (wx.WHITE, wx.Colour(192, 192, 192),
                       wx.Colour(128, 128, 128), wx.Colour(64, 64, 64))
        self.labels = {}
        self.panels = []
        self.buttons = []
        for index in range(rows * cols):
            panel = wx_Panel(self, style=wx.BORDER_SIMPLE)
            panel.SetBackgroundColour(BGCOLOUR)
            sizer = wx.BoxSizer(wx.VERTICAL)
            panel.SetSizer(sizer)
            self.panels.append(panel)
            button = FlatShadedNumberedButton(
                panel,
                label=lang.getstr("measure"),
                bitmap=getbitmap("theme/icons/10x10/record"),
                index=index)
            button.Bind(wx.EVT_BUTTON, self.measure)
            self.buttons.append(button)
            label = wx.StaticText(panel)
            label.SetForegroundColour(wx.WHITE)
            self.labels[index] = label
            sizer.Add(label, 1, wx.ALIGN_CENTER)
            sizer.Add(button,
                      0,
                      wx.ALIGN_BOTTOM | wx.ALIGN_CENTER | wx.BOTTOM | wx.LEFT
                      | wx.RIGHT,
                      border=8)
            self.sizer.Add(panel, 1, wx.EXPAND)
        self.disable_buttons()

        self.keyhandler = keyhandler
        self.id_to_keycode = {}
        if sys.platform == "darwin":
            # Use an accelerator table for tab, space, 0-9, A-Z, numpad,
            # navigation keys and processing keys
            keycodes = [wx.WXK_TAB, wx.WXK_SPACE]
            keycodes.extend(list(range(ord("0"), ord("9"))))
            keycodes.extend(list(range(ord("A"), ord("Z"))))
            keycodes.extend(numpad_keycodes)
            keycodes.extend(nav_keycodes)
            keycodes.extend(processing_keycodes)
            for keycode in keycodes:
                self.id_to_keycode[wx.Window.NewControlId()] = keycode
            accels = []
            for id, keycode in self.id_to_keycode.items():
                self.Bind(wx.EVT_MENU, self.key_handler, id=id)
                accels.append((wx.ACCEL_NORMAL, keycode, id))
                if keycode == wx.WXK_TAB:
                    accels.append((wx.ACCEL_SHIFT, keycode, id))
            self.SetAcceleratorTable(wx.AcceleratorTable(accels))
        else:
            self.Bind(wx.EVT_CHAR_HOOK, self.key_handler)

        # Event handlers
        self.Bind(wx.EVT_CLOSE, self.OnClose, self)
        self.Bind(wx.EVT_MOVE, self.OnMove, self)
        self.timer = wx.Timer(self)
        if handler:
            self.Bind(wx.EVT_TIMER, handler, self.timer)
        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)

        # Final initialization steps
        self.logger = get_file_logger("uniformity")
        self._setup()

        self.Show()

        if start_timer:
            self.start_timer()
Beispiel #30
0
def vrmlfile2x3dfile(vrmlpath=None,
                     x3dpath=None,
                     html=True,
                     embed=False,
                     view=False,
                     force=False,
                     cache=True,
                     worker=None,
                     gui=True):
    """ Convert VRML to HTML. Output is written to <vrmlfilename>.x3d.html
	unless you set x3dpath to desired output path, or False to be prompted
	for an output path. """
    while not vrmlpath or not os.path.isfile(vrmlpath):
        if not gui:
            if not vrmlpath or vrmlpath.startswith("--"):
                safe_print("No filename given.")
            else:
                safe_print("%r is not a file." % vrmlpath)
            return False
        if not wx.GetApp():
            app = BaseApp(0)
        defaultDir, defaultFile = config.get_verified_path("last_vrml_path")
        dlg = wx.FileDialog(None,
                            lang.getstr("file.select"),
                            defaultDir=defaultDir,
                            defaultFile=defaultFile,
                            wildcard=lang.getstr("filetype.vrml") +
                            "|*.vrml;*.vrml.gz;*.wrl.gz;*.wrl;*.wrz",
                            style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
        dlg.Center(wx.BOTH)
        result = dlg.ShowModal()
        vrmlpath = dlg.GetPath()
        dlg.Destroy()
        if result != wx.ID_OK:
            return
        config.setcfg("last_vrml_path", vrmlpath)
        config.writecfg(module="VRML-to-X3D-converter",
                        options=("last_vrml_path", ))
    filename, ext = os.path.splitext(vrmlpath)
    if x3dpath is None:
        x3dpath = filename + ".x3d"
    if x3dpath:
        dirname = os.path.dirname(x3dpath)
    while not x3dpath or not waccess(dirname, os.W_OK):
        if not gui:
            if not x3dpath:
                safe_print("No HTML output filename given.")
            else:
                safe_print("%r is not writable." % dirname)
            return False
        if not wx.GetApp():
            app = BaseApp(0)
        if x3dpath:
            defaultDir, defaultFile = os.path.split(x3dpath)
        else:
            defaultFile = os.path.basename(filename) + ".x3d"
        dlg = wx.FileDialog(None,
                            lang.getstr("error.access_denied.write", dirname),
                            defaultDir=defaultDir,
                            defaultFile=defaultFile,
                            wildcard=lang.getstr("filetype.x3d") + "|*.x3d",
                            style=wx.SAVE | wx.FD_OVERWRITE_PROMPT)
        dlg.Center(wx.BOTH)
        result = dlg.ShowModal()
        dlg.Destroy()
        if result != wx.ID_OK:
            return
        x3dpath = dlg.GetPath()
        dirname = os.path.dirname(x3dpath)
    vrmlpath, x3dpath = [safe_unicode(path) for path in (vrmlpath, x3dpath)]
    if sys.platform == "win32":
        vrmlpath = make_win32_compatible_long_path(vrmlpath)
        x3dpath = make_win32_compatible_long_path(x3dpath)
    if html:
        finalpath = x3dpath + ".html"
        if sys.platform == "win32":
            finalpath = make_win32_compatible_long_path(finalpath)
            x3dpath = finalpath[:-5]
    else:
        finalpath = x3dpath
    if worker:
        worker.clear_cmd_output()
        worker.start(
            lambda result: show_result_dialog(result,
                                              wx.GetApp().GetTopWindow())
            if isinstance(result, Exception
                          ) else result and view and launch_file(finalpath),
            x3dom.vrmlfile2x3dfile,
            wargs=(vrmlpath, x3dpath, html, embed, force, cache, worker),
            progress_title=lang.getstr("vrml_to_x3d_converter"),
            progress_start=1,
            resume=worker.progress_wnd
            and worker.progress_wnd.IsShownOnScreen(),
            fancy=False)
    else:
        result = x3dom.vrmlfile2x3dfile(vrmlpath, x3dpath, html, embed, force,
                                        cache, None)
        if not isinstance(result, Exception) and result:
            if view:
                launch_file(finalpath)
        else:
            return False
    return True