当前位置: 首页>>代码示例>>Python>>正文


Python DataBlockFactory.from_imageset方法代码示例

本文整理汇总了Python中dxtbx.datablock.DataBlockFactory.from_imageset方法的典型用法代码示例。如果您正苦于以下问题:Python DataBlockFactory.from_imageset方法的具体用法?Python DataBlockFactory.from_imageset怎么用?Python DataBlockFactory.from_imageset使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在dxtbx.datablock.DataBlockFactory的用法示例。


在下文中一共展示了DataBlockFactory.from_imageset方法的9个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。

示例1: run

# 需要导入模块: from dxtbx.datablock import DataBlockFactory [as 别名]
# 或者: from dxtbx.datablock.DataBlockFactory import from_imageset [as 别名]
    def run(self):
        params, options = self.parser.parse_args(show_diff_phil=True)
        assert params.input.single_img is not None

        filebase = os.path.splitext(params.input.single_img)[0]

        for item in dir(params.output):
            value = getattr(params.output, item)
            try:
                if "%s" in value:
                    setattr(params.output, item, value % filebase)
            except Exception:
                pass

        self.params = params
        self.options = options

        # load the image
        img = dxtbx.load(params.input.single_img)
        imgset = MemImageSet([img])
        datablock = DataBlockFactory.from_imageset(imgset)[0]

        # Cannot export MemImageSets
        # if self.params.output.datablock_filename:
        # from dxtbx.datablock import DataBlockDumper
        # dump = DataBlockDumper(datablock)
        # dump.as_json(self.params.output.datablock_filename)

        observed = self.find_spots(datablock)
        experiments, indexed = self.index(datablock, observed)
        experiments = self.refine(experiments, indexed)
        integrated = self.integrate(experiments, indexed)
开发者ID:dials,项目名称:dials_scratch,代码行数:34,代码来源:in_memory_process2.py

示例2: tst_from_datablock

# 需要导入模块: from dxtbx.datablock import DataBlockFactory [as 别名]
# 或者: from dxtbx.datablock.DataBlockFactory import from_imageset [as 别名]
  def tst_from_datablock(self):
    from dxtbx.imageset import ImageSweep, NullReader, SweepFileList
    from dxtbx.model import Beam, Detector, Goniometer, Scan
    from dxtbx.datablock import DataBlockFactory
    from dxtbx.model.crystal import crystal_model

    imageset = ImageSweep(NullReader(SweepFileList("filename%01d.cbf", (0, 2))))
    imageset.set_beam(Beam())
    imageset.set_detector(Detector())
    imageset.set_goniometer(Goniometer())
    imageset.set_scan(Scan((1, 2), (0, 1)))

    crystal = crystal_model((1, 0, 0), (0, 1, 0), (0, 0, 1), space_group_symbol=0)

    datablock = DataBlockFactory.from_imageset(imageset)

    experiments = ExperimentListFactory.from_datablock_and_crystal(
      datablock, crystal)

    assert(len(experiments) == 1)
    assert(experiments[0].imageset is not None)
    assert(experiments[0].beam is not None)
    assert(experiments[0].detector is not None)
    assert(experiments[0].goniometer is not None)
    assert(experiments[0].scan is not None)
    assert(experiments[0].crystal is not None)

    print 'OK'
    pass
开发者ID:dalekreitler,项目名称:cctbx-playground,代码行数:31,代码来源:tst_experiment_list.py

示例3: do_import

# 需要导入模块: from dxtbx.datablock import DataBlockFactory [as 别名]
# 或者: from dxtbx.datablock.DataBlockFactory import from_imageset [as 别名]
def do_import(filename):
  logger.info("Loading %s"%os.path.basename(filename))
  try:
    datablocks = DataBlockFactory.from_json_file(filename)
  except ValueError:
    datablocks = DataBlockFactory.from_filenames([filename])
  if len(datablocks) == 0:
    raise Abort("Could not load %s"%filename)
  if len(datablocks) > 1:
    raise Abort("Got multiple datablocks from file %s"%filename)

  # Ensure the indexer and downstream applications treat this as set of stills
  from dxtbx.imageset import ImageSet
  reset_sets = []

  for imageset in datablocks[0].extract_imagesets():
    imageset = ImageSet(imageset.reader(), imageset.indices())
    imageset._models = imageset._models
    imageset.set_scan(None)
    imageset.set_goniometer(None)
    reset_sets.append(imageset)

  return DataBlockFactory.from_imageset(reset_sets)[0]
开发者ID:dials,项目名称:dials,代码行数:25,代码来源:stills_process.py

示例4: tst_from_null_sweep

# 需要导入模块: from dxtbx.datablock import DataBlockFactory [as 别名]
# 或者: from dxtbx.datablock.DataBlockFactory import from_imageset [as 别名]
  def tst_from_null_sweep(self):
    from dxtbx.datablock import DataBlockFactory
    from dxtbx.imageset import NullReader, ImageSweep, SweepFileList
    from dxtbx.model import Beam, Detector, Goniometer, Scan

    sweep = ImageSweep(NullReader(SweepFileList("template_%2d.cbf", (0, 10))))
    sweep.set_beam(Beam((0, 0, 1)))
    sweep.set_detector(Detector())
    sweep.set_goniometer(Goniometer((1, 0, 0)))
    sweep.set_scan(Scan((1, 10), (0, 0.1)))

    # Create the datablock
    datablock = DataBlockFactory.from_imageset(sweep)
    assert(len(datablock) == 1)
    datablock = datablock[0]

    sweeps = datablock.extract_sweeps()
    assert(len(sweeps) == 1)
    assert(sweeps[0].get_beam() == sweep.get_beam())
    assert(sweeps[0].get_detector() == sweep.get_detector())
    assert(sweeps[0].get_goniometer() == sweep.get_goniometer())
    assert(sweeps[0].get_scan() == sweep.get_scan())

    print 'OK'
开发者ID:cctbx,项目名称:cctbx-playground,代码行数:26,代码来源:tst_datablock.py

示例5: run

# 需要导入模块: from dxtbx.datablock import DataBlockFactory [as 别名]
# 或者: from dxtbx.datablock.DataBlockFactory import from_imageset [as 别名]
  def run(self):
    '''Execute the script.'''
    from dials.util import log
    from time import time
    from libtbx import easy_mp
    import copy

    # Parse the command line
    params, options, all_paths = self.parser.parse_args(show_diff_phil=False, return_unhandled=True)

    # Check we have some filenames
    if not all_paths:
      self.parser.print_help()
      return

    # Save the options
    self.options = options
    self.params = params

    st = time()

    # Configure logging
    log.config(
      params.verbosity,
      info='dials.process.log',
      debug='dials.process.debug.log')

    # Log the diff phil
    diff_phil = self.parser.diff_phil.as_str()
    if diff_phil is not '':
      logger.info('The following parameters have been modified:\n')
      logger.info(diff_phil)

    self.load_reference_geometry()
    from dials.command_line.dials_import import ManualGeometryUpdater
    update_geometry = ManualGeometryUpdater(params)

    # Import stuff
    logger.info("Loading files...")
    pre_import = params.dispatch.pre_import or len(all_paths) == 1
    if pre_import:
      # Handle still imagesets by breaking them apart into multiple datablocks
      # Further handle single file still imagesets (like HDF5) by tagging each
      # frame using its index

      datablocks = [do_import(path) for path in all_paths]
      if self.reference_detector is not None:
        from dxtbx.model import Detector
        for datablock in datablocks:
          for imageset in datablock.extract_imagesets():
            for i in range(len(imageset)):
              imageset.set_detector(
                Detector.from_dict(self.reference_detector.to_dict()),
                index=i)

      for datablock in datablocks:
        for imageset in datablock.extract_imagesets():
          update_geometry(imageset)

      indices = []
      basenames = []
      split_datablocks = []
      for datablock in datablocks:
        for imageset in datablock.extract_imagesets():
          paths = imageset.paths()
          for i in xrange(len(imageset)):
            subset = imageset[i:i+1]
            split_datablocks.append(DataBlockFactory.from_imageset(subset)[0])
            indices.append(i)
            basenames.append(os.path.splitext(os.path.basename(paths[i]))[0])
      tags = []
      for i, basename in zip(indices, basenames):
        if basenames.count(basename) > 1:
          tags.append("%s_%05d"%(basename, i))
        else:
          tags.append(basename)

      # Wrapper function
      def do_work(item):
        Processor(copy.deepcopy(params)).process_datablock(item[0], item[1])

      iterable = zip(tags, split_datablocks)

    else:
      basenames = [os.path.splitext(os.path.basename(filename))[0] for filename in all_paths]
      tags = []
      for i, basename in enumerate(basenames):
        if basenames.count(basename) > 1:
          tags.append("%s_%05d"%(basename, i))
        else:
          tags.append(basename)

      # Wrapper function
      def do_work(item):
        tag, filename = item

        datablock = do_import(filename)
        imagesets = datablock.extract_imagesets()
        if len(imagesets) == 0 or len(imagesets[0]) == 0:
          logger.info("Zero length imageset in file: %s"%filename)
#.........这里部分代码省略.........
开发者ID:dials,项目名称:dials,代码行数:103,代码来源:stills_process.py

示例6: process_event

# 需要导入模块: from dxtbx.datablock import DataBlockFactory [as 别名]
# 或者: from dxtbx.datablock.DataBlockFactory import from_imageset [as 别名]

#.........这里部分代码省略.........
                                                    apply_gain_mask=self.params.format.cbf.gain_mask_value is not None,
                                                    gain_mask_value=self.params.format.cbf.gain_mask_value,
                                                    per_pixel_gain=False)
      if data is None:
        print "No data"
        self.debug_write("no_data", "skip")
        return

      if self.params.format.cbf.override_distance is None:
        distance = cspad_tbx.env_distance(self.params.input.address, run.env(), self.params.format.cbf.detz_offset)
        if distance is None:
          print "No distance, skipping shot"
          self.debug_write("no_distance", "skip")
          return
      else:
        distance = self.params.format.cbf.override_distance

      if self.params.format.cbf.override_energy is None:
        wavelength = cspad_tbx.evt_wavelength(evt)
        if wavelength is None:
          print "No wavelength, skipping shot"
          self.debug_write("no_wavelength", "skip")
          return
      else:
        wavelength = 12398.4187/self.params.format.cbf.override_energy

    if self.params.format.file_format == 'pickle':
      image_dict = evt.get(self.params.format.pickle.out_key)
      data = image_dict['DATA']

    timestamp = t = ts
    s = t[0:4] + t[5:7] + t[8:10] + t[11:13] + t[14:16] + t[17:19] + t[20:23]
    print "Processing shot", s

    if self.params.format.file_format == 'cbf':
      # stitch together the header, data and metadata into the final dxtbx format object
      cspad_img = cspad_cbf_tbx.format_object_from_data(self.base_dxtbx, data, distance, wavelength, timestamp, self.params.input.address)

      if self.params.input.reference_geometry is not None:
        from dxtbx.model import Detector
        # copy.deep_copy(self.reference_detctor) seems unsafe based on tests. Use from_dict(to_dict()) instead.
        cspad_img._detector_instance = Detector.from_dict(self.reference_detector.to_dict())
        cspad_img.sync_detector_to_cbf()

    elif self.params.format.file_format == 'pickle':
      from dxtbx.format.FormatPYunspecifiedStill import FormatPYunspecifiedStillInMemory
      cspad_img = FormatPYunspecifiedStillInMemory(image_dict)

    cspad_img.timestamp = s

    if self.params.dispatch.dump_all:
      self.save_image(cspad_img, self.params, os.path.join(self.params.output.output_dir, "shot-" + s))

    self.cache_ranges(cspad_img, self.params)

    imgset = MemImageSet([cspad_img])
    if self.params.dispatch.estimate_gain_only:
      from dials.command_line.estimate_gain import estimate_gain
      estimate_gain(imgset)
      return

    if not self.params.dispatch.find_spots:
      self.debug_write("data_loaded", "done")
      return

    datablock = DataBlockFactory.from_imageset(imgset)[0]

    # before calling DIALS for processing, set output paths according to the templates
    if self.indexed_filename_template is not None and "%s" in self.indexed_filename_template:
      self.params.output.indexed_filename = os.path.join(self.params.output.output_dir, self.indexed_filename_template%("idx-" + s))
    if "%s" in self.refined_experiments_filename_template:
      self.params.output.refined_experiments_filename = os.path.join(self.params.output.output_dir, self.refined_experiments_filename_template%("idx-" + s))
    if "%s" in self.integrated_filename_template:
      self.params.output.integrated_filename = os.path.join(self.params.output.output_dir, self.integrated_filename_template%("idx-" + s))
    if "%s" in self.reindexedstrong_filename_template:
      self.params.output.reindexedstrong_filename = os.path.join(self.params.output.output_dir, self.reindexedstrong_filename_template%("idx-" + s))

    # Load a dials mask from the trusted range and psana mask
    from dials.util.masking import MaskGenerator
    generator = MaskGenerator(self.params.border_mask)
    mask = generator.generate(imgset)
    if self.params.format.file_format == "cbf":
      mask = tuple([a&b for a, b in zip(mask,self.dials_mask)])
    if self.spotfinder_mask is None:
      self.params.spotfinder.lookup.mask = mask
    else:
      self.params.spotfinder.lookup.mask = tuple([a&b for a, b in zip(mask,self.spotfinder_mask)])
    if self.integration_mask is None:
      self.params.integration.lookup.mask = mask
    else:
      self.params.integration.lookup.mask = tuple([a&b for a, b in zip(mask,self.integration_mask)])

    self.debug_write("spotfind_start")
    try:
      observed = self.find_spots(datablock)
    except Exception, e:
      import traceback; traceback.print_exc()
      print str(e), "event", timestamp
      self.debug_write("spotfinding_exception", "fail")
      return
开发者ID:cctbx,项目名称:cctbx-playground,代码行数:104,代码来源:xtc_process.py

示例7: run

# 需要导入模块: from dxtbx.datablock import DataBlockFactory [as 别名]
# 或者: from dxtbx.datablock.DataBlockFactory import from_imageset [as 别名]
  def run(self):
    '''Execute the script.'''
    from dials.util import log
    from logging import info
    from time import time
    from libtbx.utils import Abort
    from libtbx import easy_mp
    import os, copy
    from dxtbx.datablock import DataBlockFactory

    # Parse the command line
    params, options, all_paths = self.parser.parse_args(show_diff_phil=False, return_unhandled=True)

    # Check we have some filenames
    if len(all_paths) == 0:
      self.parser.print_help()
      return

    # Save the options
    self.options = options
    self.params = params

    st = time()

    # Configure logging
    log.config(
      params.verbosity,
      info='dials.process.log',
      debug='dials.process.debug.log')

    # Log the diff phil
    diff_phil = self.parser.diff_phil.as_str()
    if diff_phil is not '':
      info('The following parameters have been modified:\n')
      info(diff_phil)

    # Import stuff
    info("Loading files...")
    if len(all_paths) == 1:
      datablocks = DataBlockFactory.from_filenames(all_paths)
    else:
      def do_import(filename):
        info("Loading %s"%os.path.basename(filename))
        datablocks = DataBlockFactory.from_filenames([filename])
        if len(datablocks) == 0:
          raise Abort("Could not load %s"%filename)
        if len(datablocks) > 1:
          raise Abort("Got multiple datablocks from file %s"%filename)
        return datablocks[0]

      datablocks = easy_mp.parallel_map(
        func=do_import,
        iterable=all_paths,
        processes=params.mp.nproc,
        method=params.mp.method,
        preserve_order=True,
        preserve_exception_message=True)

    if len(datablocks) == 0:
      raise Abort('No datablocks specified')

    # Handle still imagesets by breaking them apart into multiple datablocks
    # Further handle single file still imagesets (like HDF5) by tagging each
    # frame using its index
    indices = []
    basenames = []
    split_datablocks = []
    for datablock in datablocks:
      for imageset in datablock.extract_imagesets():
        for i in xrange(len(imageset)):
          subset = imageset[i:i+1]
          split_datablocks.append(DataBlockFactory.from_imageset(subset)[0])
          indices.append(i)
          basenames.append(os.path.splitext(os.path.basename(subset.paths()[0]))[0])
    tags = []
    for i, basename in zip(indices, basenames):
      if basenames.count(basename) > 1:
        tags.append("%s_%d"%(basename, i))
      else:
        tags.append(basename)

    # Wrapper function
    def do_work(item):
      Processor(copy.deepcopy(params)).process_datablock(item[0], item[1])

    # Process the data
    easy_mp.parallel_map(
      func=do_work,
      iterable=zip(tags, split_datablocks),
      processes=params.mp.nproc,
      method=params.mp.method,
      preserve_order=True,
      preserve_exception_message=True)

     # Total Time
    info("")
    info("Total Time Taken = %f seconds" % (time() - st))
开发者ID:biochem-fan,项目名称:dials,代码行数:99,代码来源:stills_process.py

示例8: run

# 需要导入模块: from dxtbx.datablock import DataBlockFactory [as 别名]
# 或者: from dxtbx.datablock.DataBlockFactory import from_imageset [as 别名]
def run():
  parser = OptionParser(
    phil = phil_scope)

  params, options = parser.parse_args(show_diff_phil=True)
  assert params.input.single_img is not None
  assert params.output_dir is not None

  # load the image
  img = dxtbx.load(params.input.single_img)
  imgset = MemImageSet([img])
  datablock = DataBlockFactory.from_imageset(imgset)[0]

  spotfinder = SpotFinderFactory.from_parameters(params)
  reflections = spotfinder(datablock)

  base_name = os.path.splitext(params.input.single_img)[0]
  reflections.as_pickle(os.path.join(params.output_dir, base_name + "_strong.pickle"))

  # DGW commented out as reflections.minimum_number_of_reflections no longer exists
  #if len(reflections) < params.refinement.reflections.minimum_number_of_reflections:
  #  print "Not enough spots to index"
  #  return

  # create the spot finder

  print "Spotfinder spots found:", len(reflections)

  if params.indexing.method == "fft3d":
    from dials.algorithms.indexing.fft3d import indexer_fft3d as indexer
  elif params.indexing.method == "fft1d":
    from dials.algorithms.indexing.fft1d import indexer_fft1d as indexer
  elif params.method == "real_space_grid_search":
    from dials.algorithms.indexing.real_space_grid_search \
         import indexer_real_space_grid_search as indexer
  try:
    idxr = indexer(reflections, [imgset], params=params.indexing)
  except (RuntimeError, Sorry) as e:
    print str(e)
    return

  indexed = idxr.refined_reflections
  experiments = idxr.refined_experiments
  #from dxtbx.model.experiment.experiment_list import ExperimentListDumper
  #dump = ExperimentListDumper(experiments)
  #dump.as_json(os.path.join(params.output_dir, base_name + "_experiments.json"))
  indexed.as_pickle(os.path.join(params.output_dir, base_name + "_indexed.pickle"))

  refiner = RefinerFactory.from_parameters_data_experiments(
    params, indexed, experiments)

  refiner.run()
  refined_experiments = refiner.get_experiments()
  #dump = ExperimentListDumper(refined_experiments)
  #dump.as_json(os.path.join(params.output_dir, base_name + "_refined.json"))

  # Compute the profile model
  # Predict the reflections
  # Match the predictions with the reference
  # Create the integrator
  reference = indexed

  reference = process_reference(reference)
  profile_model = ProfileModelFactory.create(params, refined_experiments, reference)
  predicted = flex.reflection_table.from_predictions_multi(
    refined_experiments,
    dmin=params.prediction.dmin,
    dmax=params.prediction.dmax,
    margin=params.prediction.margin,
    force_static=params.prediction.force_static)
  predicted.match_with_reference(reference)
  integrator = IntegratorFactory.create(params, experiments, profile_model, predicted)

  # Integrate the reflections
  integrated = integrator.integrate()
  integrated.as_pickle(os.path.join(params.output_dir, base_name + "_integrated.pickle"))
开发者ID:dials,项目名称:dials_scratch,代码行数:78,代码来源:in_memory_process.py

示例9: process_event

# 需要导入模块: from dxtbx.datablock import DataBlockFactory [as 别名]
# 或者: from dxtbx.datablock.DataBlockFactory import from_imageset [as 别名]
  def process_event(self, run, timestamp):
    """
    Process a single event from a run
    @param run psana run object
    @param timestamp psana timestamp object
    """
    ts = cspad_tbx.evt_timestamp((timestamp.seconds(),timestamp.nanoseconds()/1e6))
    if ts is None:
      print "No timestamp, skipping shot"
      return

    if len(self.params_cache.debug.event_timestamp) > 0 and ts not in self.params_cache.debug.event_timestamp:
      return

    if self.params_cache.debug.skip_processed_events or self.params_cache.debug.skip_unprocessed_events or self.params_cache.debug.skip_bad_events:
      if ts in self.known_events:
        if self.known_events[ts] == "unknown":
          if self.params_cache.debug.skip_bad_events and self.known_events[ts] == "unknown":
            print "Skipping event %s: possibly caused an unknown exception previously"%ts
            return
        elif self.params_cache.debug.skip_processed_events:
          print "Skipping event %s: processed successfully previously"%ts
          return
      else:
        if self.params_cache.debug.skip_unprocessed_events:
          print "Skipping event %s: not processed previously"%ts
          return

    print "Accepted", ts

    self.debug_file_handle.write("%s,%s"%(socket.gethostname(), ts))

    self.params = copy.deepcopy(self.params_cache)

    evt = run.event(timestamp)
    id = evt.get(psana.EventId)
    if evt.get("skip_event"):
      print "Skipping event",id
      self.debug_file_handle.write(",psana_skip\n")
      return

    # the data needs to have already been processed and put into the event by psana
    if self.params.format.file_format == 'cbf':
      # get numpy array, 32x185x388
      data = self.psana_det.calib(evt) # applies psana's complex run-dependent calibrations
      if data is None:
        print "No data"
        self.debug_file_handle.write(",no_data\n")
        return

      if self.params.format.cbf.gain_mask_value is not None:
        # apply gain mask
        data *= self.gain_mask

      distance = cspad_tbx.env_distance(self.params.input.address, run.env(), self.params.format.cbf.detz_offset)
      if distance is None:
        print "No distance, skipping shot"
        self.debug_file_handle.write(",no_distance\n")
        return

      if self.params.format.cbf.override_energy is None:
        wavelength = cspad_tbx.evt_wavelength(evt)
        if wavelength is None:
          print "No wavelength, skipping shot"
          self.debug_file_handle.write(",no_wavelength\n")
          return
      else:
        wavelength = 12398.4187/self.params.format.cbf.override_energy

    if self.params.format.file_format == 'pickle':
      image_dict = evt.get(self.params.format.pickle.out_key)
      data = image_dict['DATA']

    timestamp = t = ts
    s = t[0:4] + t[5:7] + t[8:10] + t[11:13] + t[14:16] + t[17:19] + t[20:23]
    print "Processing shot", s

    if self.params.format.file_format == 'cbf':
      # stitch together the header, data and metadata into the final dxtbx format object
      cspad_img = cspad_cbf_tbx.format_object_from_data(self.base_dxtbx, data, distance, wavelength, timestamp, self.params.input.address)
    elif self.params.format.file_format == 'pickle':
      from dxtbx.format.FormatPYunspecifiedStill import FormatPYunspecifiedStillInMemory
      cspad_img = FormatPYunspecifiedStillInMemory(image_dict)

    cspad_img.timestamp = s

    if self.params.dispatch.dump_all:
      self.save_image(cspad_img, self.params, os.path.join(self.params.output.output_dir, "shot-" + s))

    self.cache_ranges(cspad_img, self.params)

    imgset = MemImageSet([cspad_img])
    datablock = DataBlockFactory.from_imageset(imgset)[0]

    # before calling DIALS for processing, set output paths according to the templates
    if self.indexed_filename_template is not None and "%s" in self.indexed_filename_template:
      self.params.output.indexed_filename = os.path.join(self.params.output.output_dir, self.indexed_filename_template%("idx-" + s))
    if "%s" in self.refined_experiments_filename_template:
      self.params.output.refined_experiments_filename = os.path.join(self.params.output.output_dir, self.refined_experiments_filename_template%("idx-" + s))
    if "%s" in self.integrated_filename_template:
#.........这里部分代码省略.........
开发者ID:keitaroyam,项目名称:cctbx_fork,代码行数:103,代码来源:xtc_process.py


注:本文中的dxtbx.datablock.DataBlockFactory.from_imageset方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。